From 8683baa38581e664f92fcfd7d38edf6b01e8b157 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 07 八月 2025 16:19:09 +0800
Subject: [PATCH] 121 【武将】武将系统-服务端(重生扣除货币)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 1164 ++++++++++++++++++++++-----------------------------------
 1 files changed, 445 insertions(+), 719 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 e1e95ad..1bc7528 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -31,12 +31,13 @@
 import NPCCommon
 import ShareDefine
 import PyGameData
-import IPY_GameWorld
 import ItemControler
 import SkillCommon
-import SkillShell
 import AttackCommon
-import FBLogic
+import BattleObj
+import TurnSkill
+import TurnBuff
+import ObjPool
 
 import random
 import time
@@ -55,129 +56,61 @@
 FightState_Award, # 4 结算奖励
 FightState_Over, # 5 结束状态,无特殊意义,仅代表所有处理结束了,与Start对应
 ) = range(6)
-
-Def_FactionA = 1
-Def_FactionB = 2
-
+    
 class BatLineup():
     ## 战斗阵容
     
-    def __init__(self, faction, num, fightMgr):
-        self.fightMgr = fightMgr
+    def __init__(self, faction, num, turnFight):
+        self.turnFight = turnFight # TurnFight
         self.faction = faction # 所属阵营
         self.num = num # 该阵容所在阵营中的编号,不同阵营可重复,多V多
         self.ownerID = 0 # 阵容所属玩家ID,可能为0,0代表非玩家阵容
-        self.npcPosDict = {} # 阵容NPC {站位编号:curNPC, ...}, 站位编号小于0为非主战单位,如主公、红颜等
-        self.npcObjIDDict = {} # NPC实例ID字典 {objID:curNPC, ...}
         self.shapeType = 0 # 阵型
-        self.actionNum = ActionNumStart # 行动位置,从1开始
-        self.lordAttrDict = {} # 主公属性
-        self.npcAttrDict = {} # 阵容NPC属性 {npcID:{attrID:value, ...}, ...}
         self.fightPower = 0 # 阵容总战力
-        
-        # 战斗统计
-        self.hurtStatDict = {} # 输出统计 {objID:totalValue, ...}
-        self.defStatDict = {} # 承伤统计 {objID:totalValue, ...}
-        self.cureStatDict = {} # 治疗统计 {objID:totalValue, ...}
+        self.posObjIDDict = {} # 站位对应战斗实体 {站位编号:batObjID, ...}, 站位编号小于0为非主战单位,如主公、红颜等
+        self.actionNum = ActionNumStart # 行动位置,从1开始
         return
     
-    def getGUID(self): return self.fightMgr.guid
-    def getPlayerID(self): return self.fightMgr.playerID # 发起的玩家ID
+    def getPlayerID(self): return self.turnFight.playerID # 发起的玩家ID
     
-    def isEmpty(self): return not self.npcPosDict
+    def isEmpty(self): return not self.posObjIDDict
     
     def setLineup(self, lineupInfo):
         ## 设置阵容
         # @param lineupInfo: 阵容信息
         self.clearLineup()
         self.ownerID = lineupInfo.get("PlayerID", 0) # 阵容所属的玩家ID
-        self.shapeType = lineupInfo.get("Shape", 0)
-        self.lordAttrDict = lineupInfo.get("LordAttrDict", {})
+        self.shapeType = lineupInfo.get("ShapeType", 0)
+        self.fightPower = lineupInfo.get("FightPower", 0)
         SummonLineupObjs(self, self.faction, self.num, lineupInfo, self.getPlayerID())
-        return
-    
-    def refreshFightPower(self):
-        ## 刷新阵容总战力
-        if self.fightPower:
-            return self.fightPower
-        
-        return self.fightPower
-    
-    def __resetStat(self):
-        ## 重置战斗统计
-        self.actionNum = ActionNumStart
-        self.hurtStatDict = {}
-        self.defStatDict = {}
-        self.cureStatDict = {}
-        return
-    
-    def __resetAttrState(self, isReborn=True):
-        ## 重置属性状态
-        # @param isReborn: 是否复活
-        initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
-        for curNPC in self.npcPosDict.values():
-            if not curNPC:
-                continue
-            if GameObj.GetHP(curNPC) <= 0 and not isReborn:
-                continue
-            # 回满血,清除buff
-            GameObj.SetHPFull(curNPC, False)
-            # 重置怒气
-            GameObj.SetXP(curNPC, initXP, False)
-            # ...
-            
         return
     
     def resetLineup(self, isReborn=True):
         ## 重置阵容
-        self.__resetAttrState(isReborn)
-        self.__resetStat()
+        batObjMgr = BattleObj.GetBatObjMgr()
+        for objID in self.posObjIDDict.values():
+            batObj = batObjMgr.getBatObj(objID)
+            if not batObj:
+                continue
+            batObj.ResetBatObj(isReborn)
         return
     
     def clearLineup(self):
         ## 清除阵容
-        if not self.npcPosDict:
+        if not self.posObjIDDict:
             return
-        for curNPC in self.npcPosDict.values():
-            if not curNPC:
-                continue
-            NPCCommon.SetDeadEx(curNPC)
-        self.npcPosDict = {}
-        self.npcObjIDDict = {}
-        self.npcAttrDict = {}
+        batObjMgr = BattleObj.GetBatObjMgr()
+        for objID in self.posObjIDDict.values():
+            batObjMgr.delBatObj(objID)
+        self.posObjIDDict = {}
         self.fightPower = 0
-        self.__resetStat()
         return
-    
-    def statHurtValue(self, objID, hurtValue):
-        ## 统计输出
-        if objID not in self.npcObjIDDict:
-            return
-        updValue = self.hurtStatDict.get(objID, 0) + hurtValue
-        self.hurtStatDict[objID] = updValue
-        return updValue
-    
-    def statDefValue(self, objID, lostHP):
-        ## 统计承伤
-        if objID not in self.npcObjIDDict:
-            return
-        updValue = self.defStatDict.get(objID, 0) + lostHP
-        self.defStatDict[objID] = updValue
-        return updValue
-    
-    def statCureValue(self, objID, cureValue):
-        ## 统计治疗
-        if objID not in self.npcObjIDDict:
-            return
-        updValue = self.cureStatDict.get(objID, 0) + cureValue
-        self.cureStatDict[objID] = updValue
-        return updValue
     
 class BatFaction():
     ## 战斗阵营
     
-    def __init__(self, faction, fightMgr):
-        self.fightMgr = fightMgr
+    def __init__(self, faction, turnFight):
+        self.turnFight = turnFight # TurnFight
         self.faction = faction
         self.lineupDict = {} # 该阵营所有阵容信息 {编号:BatLineup, ...}
         return
@@ -188,7 +121,7 @@
         if num in self.lineupDict:
             lineup = self.lineupDict[num]
         else:
-            lineup = BatLineup(self.faction, num, self.fightMgr)
+            lineup = BatLineup(self.faction, num, self.turnFight)
             self.lineupDict[num] = lineup
         return lineup
     
@@ -237,9 +170,6 @@
         
         self.startTime = 0 # 开始时间戳,支持毫秒小数
         self.costTime = 0 # 单场战斗总耗时,支持毫秒小数
-        
-        #玩家武将行动后击杀目标
-        self.playerKillObjIDList = [] # [objID, ...]
         return
     
     def setTurn(self, mapID, funcLineID, turnMax, isNeedReport=False, msgDict={}):
@@ -281,7 +211,6 @@
             if not lineupInfo:
                 continue
             batLineup.setLineup(lineupInfo)
-            batLineup.refreshFightPower()
         return
     
     def sortActionQueue(self):
@@ -290,7 +219,7 @@
         for batFaction in self.factionDict.values():
             faction = batFaction.faction
             for num, batLineup in batFaction.lineupDict.items():
-                fightPower = batLineup.refreshFightPower()
+                fightPower = batLineup.fightPower
                 sortValue = -(faction * 10 + num)
                 sortList.append([fightPower, sortValue, faction, num])
         sortList.sort(reverse=True) # 战力高的先手
@@ -304,7 +233,7 @@
         GameWorld.DebugLog("阵容行动顺序[f, n]: %s" % self.actionSortList)
         return
     
-    def getBatFaction(self, faction=Def_FactionA):
+    def getBatFaction(self, faction=ChConfig.Def_FactionA):
         ## 默认阵营1
         batFaction = None
         if faction in self.factionDict:
@@ -321,21 +250,25 @@
         if self.winFaction:
             return self.winFaction
         
+        batObjMgr = BattleObj.GetBatObjMgr()
         for faction, batFaction in self.factionDict.items():
             allKilled = True
             for batLineup in batFaction.lineupDict.values():
                 if not allKilled:
                     break
-                for posNum, curNPC in batLineup.npcPosDict.items():
+                for posNum, objID in batLineup.posObjIDDict.items():
                     if posNum <= 0:
                         # 非主战位置不判断
                         continue
-                    if GameObj.GetHP(curNPC) > 0:
+                    batObj = batObjMgr.getBatObj(objID)
+                    if not batObj:
+                        continue
+                    if batObj.GetHP() > 0:
                         allKilled = False
                         break
                     
             if allKilled:
-                self.winFaction = Def_FactionA if faction == Def_FactionB else Def_FactionA
+                self.winFaction = ChConfig.Def_FactionA if faction == ChConfig.Def_FactionB else ChConfig.Def_FactionA
                 DoTurnFightOver(self.guid)
                 return self.winFaction
             
@@ -363,6 +296,8 @@
         clientPack.Msg = msg
         clientPack.Len = len(clientPack.Msg)
         clientPack.FactionList = []
+        
+        batObjMgr = BattleObj.GetBatObjMgr()
         for faction in self.factionDict.keys():
             batFaction = self.getBatFaction(faction)
             tfFaction = ChPyNetSendPack.tagSCTurnFightFaction()
@@ -375,19 +310,22 @@
                 tfLineup.OwnerID = batLineup.ownerID
                 tfLineup.ShapeType = batLineup.shapeType
                 tfLineup.ObjList = []
-                for posNum, curNPC in batLineup.npcPosDict.items():
+                for posNum, objID in batLineup.posObjIDDict.items():
+                    batObj = batObjMgr.getBatObj(objID)
+                    if not batObj:
+                        continue
                     tfObj = ChPyNetSendPack.tagSCTurnFightObj()
-                    tfObj.ObjID = curNPC.GetID()
-                    tfObj.NPCID = curNPC.GetNPCID()
-                    tfObj.HeroID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
-                    tfObj.SkinID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_SkinID)
-                    tfObj.HP = curNPC.GetHP()
-                    tfObj.HPEx = curNPC.GetHPEx()
-                    tfObj.MaxHP = curNPC.GetMaxHP()
-                    tfObj.MaxHPEx = curNPC.GetMaxHPEx()
-                    tfObj.LV = NPCCommon.GetNPCLV(curNPC)
+                    tfObj.ObjID = batObj.GetID()
+                    tfObj.NPCID = batObj.GetNPCID()
+                    tfObj.HeroID = batObj.GetHeroID()
+                    tfObj.SkinID = batObj.GetSkinID()
+                    tfObj.HP = batObj.GetHP() % ChConfig.Def_PerPointValue
+                    tfObj.HPEx = batObj.GetHP() / ChConfig.Def_PerPointValue
+                    tfObj.MaxHP = batObj.GetMaxHP() % ChConfig.Def_PerPointValue
+                    tfObj.MaxHPEx = batObj.GetMaxHP() / ChConfig.Def_PerPointValue
+                    tfObj.LV = batObj.GetLV()
                     tfObj.PosNum = posNum
-                    tfObj.AngreXP = GameObj.GetXP(curNPC)
+                    tfObj.AngreXP = batObj.GetXP()
                     tfLineup.ObjList.append(tfObj)
                 tfLineup.ObjCnt = len(tfLineup.ObjList)
                 tfFaction.LineupList.append(tfLineup)
@@ -411,7 +349,7 @@
         self.addBatPack(clientPack)
         return
     
-    def syncObjAction(self, turnNum, objType, objID):
+    def syncObjAction(self, turnNum, objID):
         clientPack = ChPyNetSendPack.tagMCTurnFightObjAction()
         clientPack.Clear()
         clientPack.TurnNum = turnNum
@@ -432,6 +370,8 @@
         # 有玩家的统一每个包单独发送,同样也支持战报统计
         if self.curPlayer:
             NetPackCommon.SendFakePack(self.curPlayer, clientPack)
+        else:
+            ObjPool.GetPoolMgr().release(clientPack)
         return
     
 class TurnFightMgr():
@@ -439,7 +379,6 @@
     
     def __init__(self):
         self.turnFightDict = {} # {guid:TurnFight, ...}
-        self.npcGUIDDict = {} # npc所属的某场战斗guid {objID:guid, ...}
         return
     
     def addTurnFight(self, mapID, funcLineID=0, playerID=0):
@@ -462,27 +401,6 @@
         elif False:
             tf = TurnFight()
         return tf
-    
-    def getNPCTurnFight(self, objID):
-        ## 获取NPC所在的回合战斗,如果该npc不属于某场回合战斗则返回None
-        tf = None
-        if objID in self.npcGUIDDict:
-            guid = self.npcGUIDDict[objID]
-            if guid in self.turnFightDict:
-                tf = self.turnFightDict[guid]
-        if not tf and False:
-            tf = TurnFight()
-        return tf
-    
-    def setNPCGUID(self, objID, guid):
-        ## 设置NPC所属回合战斗guid
-        self.npcGUIDDict[objID] = guid
-        GameWorld.DebugLog("设置NPC所属回合战斗guid: %s,%s" % (objID, guid))
-        return
-    def delNPCGUID(self, objID):
-        guid = self.npcGUIDDict.pop(objID, None)
-        GameWorld.DebugLog("删除NPC所属回合战斗guid: %s,%s" % (objID, guid))
-        return
     
 def GetTurnFightMgr():
     tfMgr = None
@@ -513,10 +431,6 @@
         ## 当前战斗是否关卡boss
         return self.turnFight.mapID == ChConfig.Def_FBMapID_MainBoss
     
-    def clear(self):
-        self.turnFight.clearFight()
-        return
-    
 def GetMainFightMgr(curPlayer):
     ## 获取主线战斗管理
     olPlayer = PlayerOnline.GetOnlineMgr().GetOnlinePlayer(curPlayer)
@@ -532,71 +446,50 @@
                           % (chapterID, levelNum, nowChapterID, fixNowValue), curPlayer.GetPlayerID())
     return
 
-def GetPlayerLineupByCache(playerID, lineupID):
+def GetPlayerLineupInfoByCache(playerID, lineupID):
     ## 获取玩家阵容信息 - 根据玩家查看缓存
-    return {}
+    lineupInfo = {}
+    return lineupInfo
 
-def GetPlayerLineup(curPlayer, lineupID):
-    ## 获取玩家阵容信息
+def GetPlayerLineupInfo(curPlayer, lineupID):
+    ## 获取玩家阵容信息,可用于战斗或查看缓存,因为可能取玩家的缓存进行对战,所以统一使用json格式,前端通用
     # @param lineupID: 阵容ID
     # @return: 阵容全部信息json字典,前端通用格式
     
     playerID = curPlayer.GetPlayerID()
+    lineup = PlayerOnline.GetOnlinePlayer(curPlayer).GetLineup(lineupID)
     
-    # 武将
+    lineupInfo = {"PlayerID":playerID, "FightPower":lineup.fightPower, "ShapeType":lineup.shapeType}
     heroDict = {}
-    heroCount = 0
     curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero)
-    for index in range(curPack.GetCount()):
-        heroItem = curPack.GetAt(index)
-        if not heroItem or heroItem.IsEmpty():
-            continue
-        lineupCount = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroLineup)
-        if not lineupCount:
-            continue
-        posNum = 0 # 站位
-        for lpIndex in range(lineupCount):
-            lineupValue = heroItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroLineup, lpIndex)
-            #阵容类型*10000+阵型类型*100+位置编号
-            if lineupValue / 10000 != lineupID:
-                continue
-            posNum = lineupValue % 100
-            break
-        
-        if not posNum:
-            continue
-        
-        heroID = heroItem.GetItemTypeID()
-        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
-        if not heroIpyData:
-            continue
-        skinIDList = heroIpyData.GetSkinIDList()
-        skinIndex = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroSkin)
-        if skinIndex < 0 or skinIndex >= len(skinIDList):
-            continue
-        skinID = skinIDList[skinIndex]
+    for posNum in lineup.lineupHeroDict.keys():
+        hero = lineup.GetLineupHero(posNum)
+        heroID = hero.heroID
+        itemIndex = hero.itemIndex
+        userData = ""
+        heroLV = 1
+        if itemIndex >= 0 and itemIndex < curPack.GetCount():
+            heroItem = curPack.GetAt(itemIndex)
+            if heroItem and not heroItem.IsEmpty():
+                userData = heroItem.GetUserData()
+                heroLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroLV)
+                
+        skillIDlist = []
+        skillIDlist += hero.heroSkillIDList
         heroDict[str(posNum)] = {
                                  "HeroID":heroID,
-                                 "SkinID":skinID,
-                                 "Data":heroItem.GetUserData(),
+                                 "SkinID":hero.skinID,
+                                 "LV":heroLV,
+                                 "Data":userData,
+                                 "FightPower":hero.fightPower,
+                                 "AttrDict":{str(k):v for k, v in hero.heroBatAttrDict.items() if v > 0},
+                                 "SkillIDList":skillIDlist,
                                  }
-        
-        heroCount += 1
-        if heroCount >= ShareDefine.LineupObjMax:
-            break
-        
-    if not heroDict:
-        return {}
+    lineupInfo.update({"Hero":heroDict})
     
-    # 主公属性
-    lordAttrDict = PlayerControl.GetLordAttr(curPlayer)
-    
-    # 其他
-    
-    lineupInfo = {"PlayerID":playerID, "LordAttrDict":lordAttrDict, "Hero":heroDict}
     return lineupInfo
 
-def GetNPCLineup(lineupID):
+def GetNPCLineupInfo(lineupID):
     ## 获取NPC阵容信息
     # @param lineupID: 阵容ID
     # @return: 阵容全部信息json字典,前端通用格式
@@ -611,10 +504,26 @@
         npcID = getattr(ipyData, "GetPosNPCID%s" % posNum)()
         if not npcID:
             continue
+        npcData = NPCCommon.GetNPCDataPy(npcID)
+        if not npcData:
+            continue
+        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(), 
+                       ChConfig.AttrID_SuperHitRate:npcData.GetSuperHitRate(), ChConfig.AttrID_SuperHitRateDef:npcData.GetSuperHitRateDef(), 
+                       ChConfig.AttrID_StunRate:npcData.GetStunRate(), ChConfig.AttrID_StunRateDef:npcData.GetStunRateDef(), 
+                       ChConfig.AttrID_ComboRate:npcData.GetComboRate(), ChConfig.AttrID_ComboRateDef:npcData.GetComboRateDef(), 
+                       ChConfig.AttrID_ParryRate:npcData.GetParryRate(), ChConfig.AttrID_ParryRateDef:npcData.GetParryRateDef(), 
+                       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
+                                 }
         
-        heroDict[str(posNum)] = {"NPCID":npcID}
-        
-    lineupInfo = {"Hero":heroDict}
+    lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict}
     return lineupInfo
 
 def SummonLineupObjs(batLineup, faction, num, lineupInfo, playerID=0):
@@ -624,115 +533,79 @@
     @param lineupInfo: 阵容信息
     @param playerID: 发起的玩家ID,系统场次为0
     '''
-    
-    '''关于视野层级说明 sightLevel
-        玩家发起的战斗视野层级只能用玩家ID,才能达到只通知该玩家的效果
-        但是由于同个玩家可能同时存在多场战斗,如主线战斗 + 其他战斗,所以视野层级只能用作仅通知该玩家的作用,
-        不能用于处理NPC视野来遍历伤害对象等,因为不同战场的NPC视野层级可能相同,对于同场战斗NPC的遍历处理只能用 turnFight 管理遍历
-        鉴于视野层级仅用于通知的作用,故系统场次理论上可以只用一个视野层级,但是为了减少不必要的问题,系统场次的视野层级还是尽量区分开来
-        这里暂时用时间戳的后4位来做短时间内的理论上唯一视野层级
-    '''
     GameWorld.DebugLog("SummonLineupObjs faction:%s,num:%s,lineupInfo=%s" % (faction, num, lineupInfo), playerID)
     if playerID:
         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         if not curPlayer:
             return
-        posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY()
-        sightLevel = playerID
         
-        # 开发过程中可以先开启视野层级及视野,方便检查战斗相关是否有遗漏
-        if curPlayer.GetSightLevel() != sightLevel:
-            PlayerControl.SetPlayerSightLevel(curPlayer, sightLevel)
-        sight = ChConfig.Def_PlayerSight_Default * 5
-        if curPlayer.GetSight() != sight:
-            PlayerControl.SetSight(curPlayer, sight)
-    else:
-        gameMap = GameWorld.GetMap()
-        posX, posY = gameMap.GetRebornMapX(), gameMap.GetRebornMapY() # 系统战斗默认取当前地图的复活点,需要优化
-        sightLevel = 2000000000 + int(time.time()) % 10000
-        
-    GameWorld.DebugLog("sightLevel=%s,pos=(%s,%s)" % (sightLevel, posX, posY), playerID)
-    
+    tfGUID = batLineup.turnFight.guid
     lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
     heroDict = lineupInfo.get("Hero", {})
-    tick = GameWorld.GetGameWorld().GetTick()
     
+    batObjMgr = BattleObj.GetBatObjMgr()
     initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
-    baseAtkSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 3)
-    tfMgr = GetTurnFightMgr()
-    space = 3
+    atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 3)
     for posNumKey, heroInfo in heroDict.items():
         posNum = int(posNumKey)
         
-        heroID, skinID = 0, 0
-        baseAtkSkillID = 0 # 基础普攻ID
-        skillIDList = []
+        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)
-            npcID = FighterNPCID
+            lv = heroInfo.get("LV", 1)
+            fightPower = heroInfo.get("FightPower", 0)
             heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
             if not heroIpyData:
                 continue
-            normalSkillID = heroIpyData.GetNormalSkillID()
-            angerSkillID = heroIpyData.GetAngerSkillID()
-            skillIDList += [normalSkillID, angerSkillID]
             atkDistType = heroIpyData.GetAtkDistType()
+            objName = heroIpyData.GetName()
         else:
             npcID = heroInfo.get("NPCID", 0)
-            npcDataEx = NPCCommon.GetNPCDataEx(npcID)
+            npcDataEx = NPCCommon.GetNPCDataPy(npcID)
             if not npcDataEx:
                 continue
-            skillIDList += npcDataEx.GetSkillIDList()
+            objName = npcDataEx.GetNPCName()
             atkDistType = npcDataEx.GetAtkDistType()
+            lv = npcDataEx.GetLV()
             
-        if not npcID:
-            continue
-        
-        npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)
-        if not npcData:
-            continue
-        curSummon = GameWorld.GetNPCManager().AddPlayerSummonNPC()
-        if not curSummon:
-            continue
-        objID = curSummon.GetID()
-        batLineup.npcPosDict[posNum] = curSummon
-        batLineup.npcObjIDDict[objID] = curSummon
-        tfMgr.setNPCGUID(objID, batLineup.getGUID())
-        
-        curSummon.SetNPCTypeID(npcID)
-        curSummon.SetBornTime(tick)
-        curSummon.SetAIType(0)
-        curSummon.SetSightLevel(sightLevel)
-        curSummon.SetIsNeedProcess(False)
-        curSummon.SetCanAttack(True)
-        curSummon.SetVisible(True)
-        curSummon.SetDict(ChConfig.Def_Obj_Dict_TurnFightPosInfo, num * 100 + posNum)
-        curSummon.SetDict(ChConfig.Def_Obj_Dict_LineupPlayerID, lineupPlayerID)
-        curSummon.SetDict(ChConfig.Def_Obj_Dict_HeroID, heroID)
-        curSummon.SetDict(ChConfig.Def_Obj_Dict_SkinID, skinID)
-        GameObj.SetFaction(curSummon, faction)
-        GameObj.SetXP(curSummon, initXP, False)
+        batObj = batObjMgr.addBatObj()
+        if not batObj:
+            break
+        objID = batObj.GetID()
+        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.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP)
         
         if atkDistType == ChConfig.AtkDistType_Short:
-            baseAtkSkillID = baseAtkSkillIDList[0] if len(baseAtkSkillIDList) > 0 else 0
+            atkBackSkillID = atkBackSkillIDList[0] if len(atkBackSkillIDList) > 0 else 0
         elif atkDistType == ChConfig.AtkDistType_Long:
-            baseAtkSkillID = baseAtkSkillIDList[1] if len(baseAtkSkillIDList) > 1 else 0
+            atkBackSkillID = atkBackSkillIDList[1] if len(atkBackSkillIDList) > 1 else 0
+        if atkBackSkillID:
+            skillIDList.append(atkBackSkillID)
+        skillManager = batObj.GetSkillManager()
+        skillManager.SkillReset()
+        for skillID in skillIDList:
+            skillManager.LearnSkillByID(skillID)
             
-        skillManager = curSummon.GetSkillManager()
-        #有指定的技能,重新学习
-        if skillIDList:
-            skillManager.ResetSkill()
-            for skillID in skillIDList:
-                skillManager.LVUPSkillByID(skillID)
-        if baseAtkSkillID:
-            skillManager.LVUPSkillByID(baseAtkSkillID)
-            
-        rebornX = posX - space + (faction - 1) * space * 3 + ((posNum - 1) / 3 * space * 2 * (-1 if faction == 1 else 1))
-        rebornY = posY + (posNum - 1) % 3 * space
-        GameWorld.DebugLog("SummonNPC ID:%s,faction:%s,num=%s,posNum=%s,baseAtkSkillID=%s,%s" % (curSummon.GetID(), faction, num, posNum, baseAtkSkillID, skillIDList))
-        curSummon.Reborn(rebornX, rebornY, False)
-        NPCCommon.NPCControl(curSummon).DoNPCRebornCommLogic(tick)
+        batLineup.posObjIDDict[posNum] = objID
+        GameWorld.DebugLog("AddBatObj ID:%s,faction:%s,num=%s,posNum=%s,skill=%s,atk=%s,def=%s,hp=%s" 
+                           % (objID, faction, num, posNum, skillIDList, batObj.GetAtk(), batObj.GetDef(), batObj.GetHP()))
         
     return
 
@@ -841,7 +714,7 @@
     teamNum = 1
     lineupID = waveLineupList[teamNum - 1] # NPC阵容ID
     
-    lineupMainInfo = GetPlayerLineup(curPlayer, ShareDefine.Lineup_Main)
+    lineupMainInfo = GetPlayerLineupInfo(curPlayer, ShareDefine.Lineup_Main)
     if not lineupMainInfo:
         GameWorld.DebugLog("没有设置主阵容!", playerID)
         return
@@ -862,8 +735,8 @@
     
     turnFight = mainFightMgr.turnFight
     turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax})
-    turnFight.setFactionLineup(Def_FactionA, {1:lineupMainInfo}, True)
-    turnFight.setFactionLineup(Def_FactionB, {1:GetNPCLineup(lineupID)})
+    turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}, True)
+    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)})
     turnFight.sortActionQueue()
     turnFight.syncInit()
     return
@@ -915,7 +788,7 @@
     
     wave = waveMax = 1 # 关卡boss固定只有一波
     
-    lineupMainInfo = GetPlayerLineup(curPlayer, ShareDefine.Lineup_Main)
+    lineupMainInfo = GetPlayerLineupInfo(curPlayer, ShareDefine.Lineup_Main)
     if not lineupMainInfo:
         GameWorld.DebugLog("没有设置主阵容!", playerID)
         return
@@ -936,8 +809,8 @@
     
     turnFight = mainFightMgr.turnFight
     turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax})
-    turnFight.setFactionLineup(Def_FactionA, {1:lineupMainInfo}, True)
-    turnFight.setFactionLineup(Def_FactionB, {1:GetNPCLineup(lineupID)})
+    turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}, True)
+    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)})
     turnFight.sortActionQueue()
     turnFight.syncInit()
     
@@ -965,7 +838,7 @@
             mainFightMgr.nextTeam = False
             turnFight.resetTurn({"teamNum":teamNum})
             # 切换小队时,玩家阵容不需要处理,保留状态
-            turnFight.setFactionLineup(Def_FactionB, {1:GetNPCLineup(lineupID)})
+            turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)})
             turnFight.sortActionQueue()
             turnFight.syncInit()
             
@@ -993,6 +866,7 @@
     doMax = (PosNumMax + 2) * len(turnFight.actionSortList) # 防止死循环,做最大循环次数限制 = (最大位置数 + 主公、红颜位置)*行动阵容数
     overLineupList = [] # 本回合已经结束行动的阵容列表 [(faction, num), ...], 所有阵容全部结束代表本回合结束
     
+    batObjMgr = BattleObj.GetBatObjMgr()
     turnNum = turnFight.turnNum
     GameWorld.DebugLog("turnNum=%s,doMax=%s,actionIndex=%s,%s" % (turnNum, doMax, turnFight.actionIndex, turnFight.actionSortList))
     while doCnt < doMax and len(overLineupList) < len(turnFight.actionSortList):
@@ -1011,8 +885,9 @@
                 batFaction = turnFight.getBatFaction(faction)
                 batLineup = batFaction.getBatlineup(num)
                 batLineup.actionNum = ActionNumStart
-                for curNPC in batLineup.npcPosDict.values():
-                    TurnFightObjPerTurnStart(curNPC, None, turnNum, tick)
+                for objID in batLineup.posObjIDDict.values():
+                    batObj = batObjMgr.getBatObj(objID)
+                    TurnFightObjPerTurnStart(turnFight, batObj, turnNum)
                     
         if turnFight.actionIndex >= len(turnFight.actionSortList):
             turnFight.actionIndex = 0
@@ -1021,14 +896,14 @@
         faction, num = turnFight.actionSortList[turnFight.actionIndex]
         batFaction = turnFight.getBatFaction(faction)
         batLineup = batFaction.getBatlineup(num)
-        if batLineup.actionNum > max(batLineup.npcPosDict):
+        if batLineup.actionNum > max(batLineup.posObjIDDict):
             if (faction, num) not in overLineupList:
                 overLineupList.append((faction, num))
                 
             turnFight.actionIndex += 1
             continue
         
-        if faction == Def_FactionA:
+        if faction == ChConfig.Def_FactionA:
             if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint):
                 GameWorld.DebugLog("战锤不足!")
                 return
@@ -1046,31 +921,21 @@
         elif batLineup.actionNum > 0:
             for posNum in range(batLineup.actionNum, PosNumMax + 1):
                 batLineup.actionNum = posNum
-                if posNum not in batLineup.npcPosDict:
+                if posNum not in batLineup.posObjIDDict:
                     continue
-                curNPC = batLineup.npcPosDict[posNum]
-                if not curNPC or GameObj.GetHP(curNPC) <= 0:
-                    continue
-                objType = curNPC.GetGameObjType()
-                objID = curNPC.GetID()
-                turnFight.syncObjAction(turnNum, objType, objID)
-                
-                objName = GetObjName(curNPC)
-                curHP = GameObj.GetHP(curNPC)
-                
-                GameWorld.DebugLog("★回合%s %s 行动 : curHP=%s" % (turnNum, objName, curHP))
-                if not DoAttack(curNPC, None, tick):
-                    GameWorld.DebugLog("        攻击失败")
+                objID = batLineup.posObjIDDict[posNum]
+                batObj = batObjMgr.getBatObj(objID)
+                if not OnObjAction(turnFight, batObj):
                     continue
                 
-                if faction == Def_FactionA:
+                if faction == ChConfig.Def_FactionA:
                     playerHeroAtk = True
                     
                 break
             
         turnFight.actionIndex += 1
         batLineup.actionNum += 1
-        if batLineup.actionNum > max(batLineup.npcPosDict):
+        if batLineup.actionNum > max(batLineup.posObjIDDict):
             GameWorld.DebugLog("该阵容本回合已经全部行动完了: turnNum=%s,faction=%s,num=%s,actionNum=%s" % (turnFight.turnNum, faction, num, batLineup.actionNum))
             if (faction, num) not in overLineupList:
                 overLineupList.append((faction, num))
@@ -1097,7 +962,7 @@
             for faction, num in turnFight.actionSortList:
                 batFaction = turnFight.getBatFaction(faction)
                 batLineup = batFaction.getBatlineup(num)
-                for curNPC in batLineup.npcPosDict.values():
+                for objID in batLineup.posObjIDDict.values():
                     pass
                 
             if turnFight.checkOverByKilled():
@@ -1116,6 +981,7 @@
     curPlayer = turnFight.curPlayer
     turnMax = turnFight.turnMax
     EntryLogic(turnFight)
+    batObjMgr = BattleObj.GetBatObjMgr()
     for turnNum in range(1, turnMax + 1):
         turnFight.turnNum = turnNum
         GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】" % turnNum)
@@ -1128,8 +994,9 @@
             batFaction = turnFight.getBatFaction(faction)
             batLineup = batFaction.getBatlineup(num)
             batLineup.actionNum = 1
-            for curNPC in batLineup.npcPosDict.values():
-                TurnFightObjPerTurnStart(curNPC, None, turnNum, tick)
+            for objID in batLineup.posObjIDDict.values():
+                batObj = batObjMgr.getBatObj(objID)
+                TurnFightObjPerTurnStart(turnFight, batObj, turnNum)
                 
         # 主公
         for faction, num in turnFight.actionSortList:
@@ -1156,20 +1023,11 @@
             batLineup = batFaction.getBatlineup(num)
             for posNum in range(batLineup.actionNum, PosNumMax + 1):
                 batLineup.actionNum = posNum + 1
-                if posNum not in batLineup.npcPosDict:
+                if posNum not in batLineup.posObjIDDict:
                     continue
-                curNPC = batLineup.npcPosDict[posNum]
-                if not curNPC or GameObj.GetHP(curNPC) <= 0:
-                    continue
-                objType = curNPC.GetGameObjType()
-                objID = curNPC.GetID()
-                turnFight.syncObjAction(turnNum, objType, objID)
-                
-                objName = GetObjName(curNPC)
-                curHP = GameObj.GetHP(curNPC)
-                
-                GameWorld.DebugLog("★回合%s %s 行动 : curHP=%s" % (turnNum, objName, curHP))
-                if not DoAttack(curNPC, None, tick):
+                objID = batLineup.posObjIDDict[posNum]
+                batObj = batObjMgr.getBatObj(objID)
+                if not OnObjAction(turnFight, batObj):
                     continue
                 
                 break
@@ -1184,7 +1042,7 @@
             GameWorld.DebugLog("回合结束逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
             batFaction = turnFight.getBatFaction(faction)
             batLineup = batFaction.getBatlineup(num)
-            for curNPC in batLineup.npcPosDict.values():
+            for objID in batLineup.posObjIDDict.values():
                 pass
             
         if turnFight.checkOverByKilled():
@@ -1212,14 +1070,15 @@
     #funcLineID = clientData.FuncLineID
     return
 
-def GetObjName(gameObj):
-    objName = gameObj.GetName()
-    faction = GameObj.GetFaction(gameObj)
-    posInfo = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo)
-    heroID = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
+def GetObjName(batObj):
+    faction = batObj.faction
+    num = batObj.lineupNum
+    posNum = batObj.posNum
+    heroID = batObj.heroID
     if not heroID:
-        heroID = gameObj.GetNPCID()
-    return "%s%s %s[%s-%s]" % ("A" if faction == Def_FactionA else "B", posInfo, objName, gameObj.GetID(), heroID)
+        heroID = 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)
 
 def EntryLogic(turnFight):
     ## 执行进场逻辑
@@ -1230,11 +1089,32 @@
     turnFight.enterLogic = True
     return
 
-def TurnFightObjPerTurnStart(gameObj, tagObj, turnNum, tick):
+def TurnFightObjPerTurnStart(turnFight, batObj, turnNum):
     ## 回合制战斗实例 - 每回合开始时处理
-    if not gameObj:
+    if not batObj:
         return
     
+    if batObj.GetHP() <= 0:
+        return
+    
+    curID = batObj.GetID()
+    buffMgr = batObj.GetBuffManager()
+    GameWorld.DebugLog("更新buff: curID=%s,buffCount=%s" % (curID, buffMgr.GetBuffCount()))
+    for index in range(buffMgr.GetBuffCount()):
+        buff = buffMgr.GetBuffByIndex(index)
+        curRemainTime = buff.GetRemainTime()
+        if not curRemainTime:
+            # 永久buff不处理
+            continue
+        buffID = buff.GetBuffID()
+        updRemainTime = curRemainTime - 1
+        GameWorld.DebugLog("    更新buff剩余回合数: buffID=%s,updRemainTime=%s" % (buffID, updRemainTime))
+        if updRemainTime > 0:
+            buff.SetRemainTime(curRemainTime - 1)
+            TurnBuff.SyncBuffRefresh(turnFight, batObj, buff)
+        else:
+            TurnBuff.SyncBuffDel(turnFight, batObj, buffID)
+            
 #    SetTimeline(gameObj, turnNum, 0)
 #    # 重置连击、反击数
 #    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
@@ -1272,190 +1152,201 @@
 
 def AddTurnObjCureHP(curObj, srcObj, addValue, cureHP, skillID=0):
     ## 回合对象添加治疗值
-    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
+    # @param curObj: 获得治疗的对象
+    # @param srcObj: 来自谁的治疗
+    # @param addValue: 治疗值
+    # @param cureHP: 实际回血量
+    if not srcObj:
         return
-    
-    curFaction = GameObj.GetFaction(curObj)
-    if not srcObj or curFaction != GameObj.GetFaction(srcObj):
-        # 同阵营的治疗才统计
-        return
-    
     curID = curObj.GetID()
     srcID = srcObj.GetID()
-    turnFight = GetTurnFightMgr().getNPCTurnFight(curID)
-    if not turnFight:
-        return
-    
-    curBatFaction = turnFight.getBatFaction(curFaction)
-    for num in curBatFaction.lineupDict.keys():
-        batLineup = curBatFaction.getBatlineup(num)
-        updStatValue = batLineup.statCureValue(srcID, cureHP)
-        if updStatValue == None:
-            continue
-        GameWorld.DebugLog("        统计治疗: curTD=%s,srcID=%s,skillID=%s,addValue=%s,cureHP=%s,updStatValue=%s" 
-                       % (curID, srcID, skillID, addValue, cureHP, updStatValue))
-        break
-    
+    updStatValue = srcObj.StatCureValue(cureHP)
+    GameWorld.DebugLog("        统计治疗: curID=%s,srcID=%s,skillID=%s,addValue=%s,cureHP=%s,updStatValue=%s" 
+                   % (curID, srcID, skillID, addValue, cureHP, updStatValue))
+        
     return
 
-def AddTurnObjHurtValue(curObj, tagObj, hurtType, hurtValue, lostHP, curSkill=None):
+def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, curSkill=None, isBounce=False):
     ## 回合对象添加伤害值
-    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
-        return
-    curID = curObj.GetID()
-    tagID = tagObj.GetID()
+    # @param isBounce: 是否反弹伤害
+    curID = curBatObj.GetID()
+    tagID = tagBatObj.GetID()
     skillID = curSkill.GetSkillID() if curSkill else 0
-    turnFight = GetTurnFightMgr().getNPCTurnFight(curID)
-    if not turnFight:
-        return
-    
     if curID != tagID:
-        curBatFaction = turnFight.getBatFaction(GameObj.GetFaction(curObj))
-        for num in curBatFaction.lineupDict.keys():
-            batLineup = curBatFaction.getBatlineup(num)
-            updStatValue = batLineup.statHurtValue(curID, lostHP)
-            if updStatValue == None:
-                continue
-            GameWorld.DebugLog("        统计伤血: curTD=%s,tagID=%s,skillID=%s,hurtType=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,tagHP=%s" 
-                           % (curID, tagID, skillID, hurtType, hurtValue, lostHP, updStatValue, GameObj.GetHP(tagObj)))
-            break
+        updStatValue = curBatObj.StatHurtValue(hurtValue)
+        GameWorld.DebugLog("        统计伤血: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,tagHP=%s,isBounce=%s" 
+                       % (curID, tagID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
         
-        tagBatFaction = turnFight.getBatFaction(GameObj.GetFaction(tagObj))
-        for num in tagBatFaction.lineupDict.keys():
-            batLineup = tagBatFaction.getBatlineup(num)
-            updStatValue = batLineup.statDefValue(tagID, lostHP)
-            if updStatValue == None:
-                continue
-            GameWorld.DebugLog("        统计承伤: curTD=%s,tagID=%s,skillID=%s,hurtType=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,curHP=%s" 
-                           % (tagID, curID, skillID, hurtType, hurtValue, lostHP, updStatValue, GameObj.GetHP(tagObj)))
-            break
-        
+        if tagBatObj:
+            updStatValue = tagBatObj.StatDefValue(lostHP)
+            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))
+            
     else:
         # 如换血类技能,自残的伤害不算输出
-        GameWorld.DebugLog("        自残: curTD=%s,tagID=%s,skillID=%s,hurtType=%s,hurtValue=%s,lostHP=%s,curHP=%s" 
-                           % (curID, tagID, skillID, hurtType, hurtValue, lostHP, GameObj.GetHP(curObj)))
-        
-    if lostHP > 0 and curID != tagID:
-        addXP = IpyGameDataPY.GetFuncCfg("AngerXP", 4)
-        AddTurnFightXP(tagObj, addXP, "skillID:%s" % skillID)
+        GameWorld.DebugLog("        自残: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,curHP=%s" 
+                           % (curID, tagID, skillID, hurtValue, lostHP, curBatObj.GetHP()))
     return
 
-def AddTurnFightXP(gameObj, addXP, reason=""):
-    ## 回合战斗增加XP
-    if addXP <= 0 or not addXP:
-        #GameWorld.DebugLog("        没有增加XP! curID=%s" % (gameObj.GetID()))
+def OnObjAction(turnFight, curBatObj):
+    ## 战斗单位行动
+    if not curBatObj:
         return
-    posNum = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo) % 10
-    if posNum <= 0:
-        #非主战单位不加
+    
+    curHP = curBatObj.GetHP()
+    objID = curBatObj.GetID()
+    if curHP <= 0:
         return
-    curXP = GameObj.GetXP(gameObj)
-    updXP = curXP + addXP
-    GameObj.SetXP(gameObj, updXP)
-    GameWorld.DebugLog("        更新XP: curID=%s,curXP=%s,addXP=%s,updXP=%s,reason=%s" % (gameObj.GetID(), curXP, addXP, updXP, reason))
+    
+    turnNum = turnFight.turnNum
+    objName = GetObjName(curBatObj)
+    
+    # 是否可行动状态判断
+    canAction = True
+    
+    if not canAction:
+        GameWorld.DebugLog("★回合%s %s 当前状态不可行动!" % (turnNum, objName))
+        return
+    
+    GameWorld.DebugLog("★回合%s %s 行动 : curHP=%s" % (turnNum, objName, curHP))
+    turnFight.syncObjAction(turnNum, objID)
+    
+    curXP = curBatObj.GetXP()
+    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):
+            if curXP < xpMax:
+                continue
+            useCnt = -1 # xp技能优先释放
+        else:
+            useCnt = curBatObj.GetSkillUseCnt(skillID)
+        useSkillList.append([useCnt, skillID, useSkill])
+        
+    useSkillList.sort() # 按使用次数优先升序排,使用次数低的优先判断使用
+    #GameWorld.DebugLog('    技能使用顺序 = useSkillList%s' % str(useSkillList), npcID)
+    
+    for useInfo in useSkillList:
+        useSkill = useInfo[-1]
+        if TurnSkill.OnUseSkill(turnFight, curBatObj, useSkill):
+            return True
+        
     return
 
-def DoAttack(curNPC, tagNPC, tick, turnBattleType=ChConfig.TurnBattleType_Normal, useSkill=None):
-    curID = curNPC.GetID()
-    npcID = curNPC.GetNPCID()
-    objName = GetObjName(curNPC)
-    GameWorld.DebugLog("    ● %s DoAttack: curID=%s,,turnBattleType=%s" % (objName, curID, turnBattleType))
-    
-    atkOK = False
-    tagObj = tagNPC
-    curNPC.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, turnBattleType)
-    
-    if turnBattleType == ChConfig.TurnBattleType_AtkBack:
-        if not tagObj:
-            return
-        skillManager = curNPC.GetSkillManager()
-        for index in range(0, skillManager.GetSkillCount()):
-            skill = skillManager.GetSkillByIndex(index)
-            #已经到尾部了
-            if not skill or skill.GetSkillTypeID() == 0:
-                break
-            if skill.GetFuncType() == ChConfig.Def_SkillFuncType_NormalAttack:
-                useSkill = skill
-                break
-        atkOK = SkillShell.DoLogic_UseSkill(curNPC, tagObj, useSkill, tick)
-    elif turnBattleType == ChConfig.TurnBattleType_Combo:
-        if not tagObj:
-            return
-        atkOK = SkillShell.DoLogic_UseSkill(curNPC, tagObj, useSkill, tick)
-    else:
-        curXP = GameObj.GetXP(curNPC)
-        xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2) 
-        skillManager = curNPC.GetSkillManager()
-        useSkillList = []
-        #GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
-        for index in range(0, skillManager.GetSkillCount()):
-            useSkill = skillManager.GetSkillByIndex(index)
-            #已经到尾部了
-            if not useSkill or useSkill.GetSkillTypeID() == 0:
-                break
-            if useSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_NormalAttack]:
-                #基础普攻不能主动释放,目前仅用于反击
-                continue
-            #被动技能无法使用
-            if SkillCommon.isPassiveSkill(useSkill):
-                continue
-            #还在冷却时间内无法释放
-            if SkillCommon.RefreshSkillRemainTime(useSkill, tick) != 0:
-                continue
-            skillTypeID = useSkill.GetSkillTypeID()
-            # 常规攻击优先xp
-            if SkillCommon.isAngerSkill(useSkill) and turnBattleType == ChConfig.TurnBattleType_Normal:
-                if curXP < xpMax:
-                    continue
-                useCnt = -1 # xp技能优先释放
-            else:
-                useCnt = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillUseCnt % skillTypeID) # 该技能已使用次数
-            useSkillList.append([useCnt, index, skillTypeID, useSkill])
-            
-        useSkillList.sort() # 按使用次数优先升序排,使用次数低的优先判断使用
-        #GameWorld.DebugLog('    技能使用顺序 = useSkillList%s' % str(useSkillList), npcID)
-        
-        for useInfo in useSkillList:
-            useSkill = useInfo[-1]
-            #skillID = useSkill.GetSkillID()
-            atkOK, tagObj = DoNPCUseSkill(curNPC, useSkill, tick)
-            if atkOK:
-                break
-            
-    curNPC.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)
-        
+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):
@@ -1512,224 +1403,58 @@
                        % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
     return True
 
-def DoNPCUseSkill(curNPC, useSkill, tick):
-    '''NPC使用技能
-    @return: 是否成功, tagObj
-    '''
-    if not useSkill or useSkill.GetSkillTypeID() == 0:
-        return False, None
-    
-    #检查是否几率触发
-    rate = useSkill.GetHappenRate()
-    if rate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(rate, ChConfig.Def_MaxRateValue):
-        #GameWorld.Log('检查是否几率触发 = %s失败 = %s'%(rate, useSkill.GetSkillName()))
-        return False, None
-    
-    tagObj = None
-    skillTag = SkillShell.GetSkillAffectTag(useSkill)
-    skillAim = SkillShell.GetSkillFireAim(useSkill)
-    
-    # 注: 多V多的情况友好目标仅针对本阵容、敌对目标可针对任意敌对阵容
-    
-    #---对自己释放,或者无目标技能---
-    if skillTag in ChConfig.Def_ST_CanNPCUseSkill or skillAim == ChConfig.Def_UseSkillAim_None:
-        #释放自身类技能
-        tagObj = curNPC
-        isOK = SkillShell.DoLogic_UseSkill(curNPC, tagObj, useSkill, tick)
-        return isOK, tagObj
-    
-    # 召唤兽对主人释放技能
-    elif skillTag == ChConfig.Def_UseSkillTag_SummonMaster:
-        if not NPCCommon.IsSummonNPC(curNPC):
-            GameWorld.ErrLog("该NPC非召唤兽,无法获得主人释放技能")
-            return False, None
-        
-        curSummonOwner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curNPC)    
-        if curSummonOwner == None:
-            curSummonOwner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotNPC, curNPC)
-            
-        if curSummonOwner == None:
-            GameWorld.ErrLog("召唤兽(%s)对主人释放技能,找不到主人" % curNPC.GetNPCID())
-            return False, None
-        
-        tagObj = curSummonOwner
-        
-    # 友好死亡目标,一般是复活技能
-    elif skillTag == ChConfig.Def_UseSkillTag_FriendDeath:
-        deathList = GetFriendDeathList(curNPC)
-        if not deathList:
-            return False, None
-        tagObj = random.choice(deathList) # 随机选一个
-        
-    # 友好目标
-    elif skillTag in ChConfig.Def_ST_CanNPCUseSkillFriend:
-        friendList = GetFriendObjList(curNPC)
-        if not friendList:
-            return False, None
-        tagObj = random.choice(friendList) # 随机选一个,可扩展其他选择规则
-        
-    # 敌方目标
-    else:
-        tagObj = GetEnemyObj(curNPC)
-        
-    if not tagObj:
-        return False, None
-    
-    GameWorld.DebugLog("    技能释放: skillID=%s,atkID=%s,def=%s,HP:%s/%s" 
-                       % (useSkill.GetSkillID(), curNPC.GetID(), GetObjName(tagObj), GameObj.GetHP(tagObj), GameObj.GetMaxHP(tagObj)))
-    isOK = SkillShell.DoLogic_UseSkill(curNPC, tagObj, useSkill, tick)
-    return isOK, tagObj
+#def GetEnemyObj(curNPC, ruleType=0):
+#    ## 获取一个敌对单位,针对所有敌对阵容主战单位,优先选择对位阵容单位,仅限活着的单位
+#    # @param ruleType: 选择规则,默认0任意,1-最低血量;2-最高血量
+#    objID = curNPC.GetID()
+#    faction = GameObj.GetFaction(curNPC)
+#    posInfo = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo)
+#    num = posInfo / 100 # 阵容编号
+#    posNum = posInfo % 100 # 所在阵容站位
+#    turnFight = GetTurnFightMgr().getTurnFight(curNPC.GetTFGUID())
+#    if not turnFight:
+#        return
+#    
+#    tagBatFaction = turnFight.getBatFaction(Def_FactionB if faction == Def_FactionA else Def_FactionA)
+#    
+#    tagLineupNumList = [num] # 目标阵容选择顺序,优先对位阵容,再其他阵容
+#    if num in tagBatFaction.lineupDict:
+#        tagLineupNumList = [num]
+#    for tagNum in tagBatFaction.lineupDict.keys():
+#        if tagNum not in tagLineupNumList:
+#            tagLineupNumList.append(tagNum)
+#            
+#    batObjMgr = BattleObj.GetBatObjMgr()
+#    for tagNum in tagLineupNumList:
+#        tagLineup = tagBatFaction.getBatlineup(tagNum)
+#        tagPosNumList = [posNum] # 优先对位位置,再其他位置按顺序遍历
+#        pNumList = tagLineup.posObjIDDict.keys()
+#        pNumList.sort()
+#        for pNum in pNumList:
+#            if pNum > 0 and pNum not in tagPosNumList:
+#                tagPosNumList.append(pNum)
+#        for pNum in tagPosNumList:
+#            batObj = batObjMgr.getBatObj(objID)
+#            if not batObj:
+#                continue
+#            if batObj.GetHP( )<= 0:
+#                continue
+#            return batObj
+#    return
 
-def GetFriendDeathList(curNPC):
-    ## 获取友方死亡单位,仅针对本阵容主战单位
-    objID = curNPC.GetID()
-    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
-    if not turnFight:
-        return []
-    batFaction = turnFight.getBatFaction(GameObj.GetFaction(curNPC))
-    num = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo) / 100
-    batLineup = batFaction.getBatlineup(num)
-    deathList = []
-    for posNum, tagNPC in batLineup.npcPosDict.items():
-        if posNum <= 0 or not tagNPC:
-            continue
-        if GameObj.GetHP(tagNPC) > 0:
-            continue
-        deathList.append(tagNPC)
-        
-    return deathList
-
-def GetFriendObjList(curNPC):
-    ## 获取友方单位,仅针对本阵容主战单位
-    objID = curNPC.GetID()
-    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
-    if not turnFight:
-        return []
-    batFaction = turnFight.getBatFaction(GameObj.GetFaction(curNPC))
-    num = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo) / 100
-    batLineup = batFaction.getBatlineup(num)
-    friendList = []
-    for posNum, tagNPC in batLineup.npcPosDict.items():
-        if posNum <= 0 or not tagNPC:
-            continue
-        if GameObj.GetHP(tagNPC) <= 0:
-            continue
-        friendList.append(tagNPC)
-    return friendList
-
-def GetEnemyObj(curNPC, ruleType=0):
-    ## 获取一个敌对单位,针对所有敌对阵容主战单位,优先选择对位阵容单位,仅限活着的单位
-    # @param ruleType: 选择规则,默认0任意,1-最低血量;2-最高血量
-    objID = curNPC.GetID()
-    faction = GameObj.GetFaction(curNPC)
-    posInfo = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo)
-    num = posInfo / 100 # 阵容编号
-    posNum = posInfo % 100 # 所在阵容站位
-    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
-    if not turnFight:
-        return
-    
-    tagBatFaction = turnFight.getBatFaction(Def_FactionB if faction == Def_FactionA else Def_FactionA)
-    
-    tagLineupNumList = [num] # 目标阵容选择顺序,优先对位阵容,再其他阵容
-    if num in tagBatFaction.lineupDict:
-        tagLineupNumList = [num]
-    for tagNum in tagBatFaction.lineupDict.keys():
-        if tagNum not in tagLineupNumList:
-            tagLineupNumList.append(tagNum)
-            
-    for tagNum in tagLineupNumList:
-        tagLineup = tagBatFaction.getBatlineup(tagNum)
-        tagPosNumList = [posNum] # 优先对位位置,再其他位置按顺序遍历
-        pNumList = tagLineup.npcPosDict.keys()
-        pNumList.sort()
-        for pNum in pNumList:
-            if pNum > 0 and pNum not in tagPosNumList:
-                tagPosNumList.append(pNum)
-        for pNum in tagPosNumList:
-            tagNPC = tagLineup.npcPosDict.get(pNum)
-            if not tagNPC:
-                continue
-            if GameObj.GetHP(tagNPC) <= 0:
-                continue
-            return tagNPC
-    return
-
-def SetTurnObjKilled(gameObj, killer=None):
-    if not gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
-        #GameWorld.DebugLog("非回合战斗主体被击杀: curID=%s" % gameObj.GetID())
-        return
-    
+def SetObjKilled(turnFight, gameObj, killer=None, useSkill=None):
     objID = gameObj.GetID()
     GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s" % (GetObjName(gameObj), objID))
-    gameObj.SetCurAction(IPY_GameWorld.laNPCDie)
-    if GameObj.GetHP(gameObj) != 0:
-        GameObj.SetHP(gameObj, 0) # 回合制死亡仅设置为0,实例暂时不回收
-    gameObj.SetVisible(False)
+    gameObj.SetHP(0)
+    killerObjID = killer.GetID() if killer else 0
+    skillID = useSkill.GetSkillID() if useSkill else 0
     
-    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
-    if not turnFight:
-        return True
-    clientPack = ChPyNetSendPack.tagMCTurnFightObjDead()
+    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagMCTurnFightObjDead)
     clientPack.ObjID = objID
-    turnFight.addBatPack(clientPack)
-    
-    # 记录主动发起的玩家阵营击杀
-    curPlayer = turnFight.curPlayer
-    if killer and curPlayer and killer.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID) == curPlayer.GetPlayerID():
-        if objID not in turnFight.playerKillObjIDList:
-            turnFight.playerKillObjIDList.append(objID)
-        GameWorld.DebugLog("玩家单次击杀统计: %s" % turnFight.playerKillObjIDList)
-        
+    clientPack.KillerObjID = killerObjID
+    clientPack.SkillID = skillID
+    turnFight.addBatPack(clientPack)        
     return True
-
-def OnTurnfightAttackSuccess(curObj, tagObj, curSkill):
-    ## 回合战斗攻击成功额外处理,AttackResult之前,一般处理技能相关
-    if curObj.GetGameObjType() != IPY_GameWorld.gotNPC:
-        return
-    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
-        return
-    
-    objID = curObj.GetID()
-    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
-    if not turnFight:
-        return
-    
-    skillID = curSkill.GetSkillID() if curSkill else 0
-    isXP = SkillCommon.isAngerSkill(curSkill)
-    if isXP:
-        GameObj.SetXP(curObj, 0)
-    elif curSkill:
-        if SkillCommon.isTurnNormalSkill(curSkill):
-            addXP = IpyGameDataPY.GetFuncCfg("AngerXP", 3)
-            AddTurnFightXP(curObj, addXP, "skillID:%s" % skillID)
-            
-    curPlayer = turnFight.curPlayer
-    # 仅主动发起玩家阵容触发
-    if curPlayer and curObj.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID) == curPlayer.GetPlayerID():
-        FBLogic.OnPlayerLineupAttackSuccess(curPlayer, curObj, tagObj, curSkill, turnFight.mapID, turnFight.funcLineID)
-        
-    return
-
-def OnTurnfightAttackResult(curObj, tagObj, curSkill):
-    ## 回合战斗攻击结果额外处理,AttackResult 之后,一般处理击杀结算相关
-    if curObj.GetGameObjType() != IPY_GameWorld.gotNPC:
-        return
-    if not curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo):
-        return
-    
-    objID = curObj.GetID()
-    turnFight = GetTurnFightMgr().getNPCTurnFight(objID)
-    if not turnFight:
-        return
-    
-    curPlayer = turnFight.curPlayer
-    # 仅主动发起玩家阵容触发
-    if curPlayer and curObj.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID) == curPlayer.GetPlayerID():
-        FBLogic.OnPlayerLineupAttackResult(curPlayer, curObj, tagObj, curSkill, turnFight.mapID, turnFight.funcLineID)
-        
-    turnFight.playerKillObjIDList = []
-    return
 
 def OnTurnAllOver(guid):
     ## 所有回合已经全部执行完毕
@@ -1743,10 +1468,10 @@
     
     if turnFight.playerID:
         # 玩家发起的,未击杀对方,算玩家输
-        turnFight.winFaction = Def_FactionB
+        turnFight.winFaction = ChConfig.Def_FactionB
     else:
         # 系统场次,按一定规则来,这里先随机
-        turnFight.winFaction = random.choice([Def_FactionA, Def_FactionB])
+        turnFight.winFaction = random.choice([ChConfig.Def_FactionA, ChConfig.Def_FactionB])
         
     DoTurnFightOver(guid)
     return
@@ -1763,6 +1488,7 @@
     GameWorld.DebugLog("--- 战斗结束处理 --- %s, winFaction=%s, costTime=%ss" % (guid, winFaction, turnFight.costTime))
     
     # 统计明细
+    batObjMgr = BattleObj.GetBatObjMgr()
     statInfo = {}
     for faction in turnFight.factionDict.keys():
         if str(faction) not in statInfo:
@@ -1774,26 +1500,26 @@
                 facStatInfo[str(num)] = {}
             lineupStatInfo = facStatInfo[str(num)]
             batLineup = batFaction.getBatlineup(num)
-            hurtStatDict = batLineup.hurtStatDict
-            defStatDict = batLineup.defStatDict
-            cureStatDict = batLineup.cureStatDict
             GameWorld.DebugLog("阵容明细: faction=%s,num=%s" % (faction, num))
-            for posNum, curNPC in batLineup.npcPosDict.items():
-                objID = curNPC.GetID()
-                npcID = curNPC.GetNPCID()
-                heroID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
-                atkHurt = hurtStatDict.get(objID, 0)
-                defHurt = defStatDict.get(objID, 0)
-                cureHP = cureStatDict.get(objID, 0)
+            for posNum, objID in batLineup.posObjIDDict.items():
+                batObj = batObjMgr.getBatObj(objID)
+                if not batObj:
+                    continue
+                objID = batObj.GetID()
+                npcID = batObj.GetNPCID()
+                heroID = batObj.GetHeroID()
+                atkHurt = batObj.hurtStat
+                defHurt = batObj.defStat
+                cureHP = batObj.cureStat
                 GameWorld.DebugLog("    Pos:%s ID=%s-%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" 
-                                   % (posNum, objID, npcID, heroID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC), atkHurt, defHurt, cureHP))
+                                   % (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}
                 
     awardItemList = []
     playerID = turnFight.playerID
     if playerID:
         curPlayer = turnFight.curPlayer
-        isWin = (winFaction == Def_FactionA)
+        isWin = (winFaction == ChConfig.Def_FactionA)
         # 主线小怪
         if turnFight.mapID == ChConfig.Def_FBMapID_Main:
             OnOver_MainLevel(curPlayer, isWin, awardItemList)

--
Gitblit v1.8.0