|  |  | 
 |  |  | import BuffSkill | 
 |  |  | import FBCommon | 
 |  |  | import ItemControler | 
 |  |  | import PlayerPet | 
 |  |  |  | 
 |  |  | # 回合战斗流程状态 | 
 |  |  | ( | 
 |  |  | FightState_Start, | 
 |  |  | FightState_Fighting, | 
 |  |  | FightState_Win, | 
 |  |  | FightState_Fail, | 
 |  |  | FightState_Over, | 
 |  |  | ) = range(5) | 
 |  |  | FightState_Start, # 0 起始状态,无特殊意义,仅代表开始了,与Over对应 | 
 |  |  | FightState_PrepareOK, # 1 准备完毕,包含对战NPC召唤OK、其他等 | 
 |  |  | FightState_Fighting, # 2 战斗中 | 
 |  |  | FightState_FightEnd, # 3 战斗结束 | 
 |  |  | FightState_Award, # 4 结算奖励 | 
 |  |  | FightState_Over, # 5 结束状态,无特殊意义,仅代表所有处理结束了,与Start对应 | 
 |  |  | ) = range(6) | 
 |  |  |  | 
 |  |  | # 回合战斗复活类型 | 
 |  |  | ( | 
 |  |  | RebornType_PetSkill, | 
 |  |  | ) = range(1, 1 + 1) | 
 |  |  |  | 
 |  |  | def GetObjName(gameObj): | 
 |  |  |     objName = gameObj.GetName() | 
 |  |  |     mirrorPlayerID = gameObj.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) | 
 |  |  |     if mirrorPlayerID: | 
 |  |  |         objName = "%s[%s]" % (objName, mirrorPlayerID) | 
 |  |  |     faction = GameObj.GetFaction(gameObj) | 
 |  |  |     fightPlaceNum = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_FightPetPlaceNum) | 
 |  |  |     curID = gameObj.GetNPCID() if gameObj.GetGameObjType() == IPY_GameWorld.gotNPC else "" | 
 |  |  |     return "%s%s %s%s" % ("A" if faction == 1 else "B", fightPlaceNum, objName, curID) | 
 |  |  |     curID = gameObj.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) | 
 |  |  |     if not curID and gameObj.GetGameObjType() == IPY_GameWorld.gotNPC: | 
 |  |  |         curID = gameObj.GetNPCID() | 
 |  |  |     return "%s%s %s[%s-%s]" % ("A" if faction == 1 else "B", fightPlaceNum, objName, gameObj.GetID(), curID) | 
 |  |  |  | 
 |  |  | #// B4 10 回合制战斗 #tagCMTurnFight | 
 |  |  | # | 
 |  |  | 
 |  |  |  | 
 |  |  | def DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick): | 
 |  |  |     playerID = curPlayer.GetPlayerID() | 
 |  |  |     posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY() | 
 |  |  |     GameWorld.DebugLog("===== 执行回合制战斗: mapID=%s,funcLineID=%s,playerID=%s,tagPlayerID=%s" % (mapID, funcLineID, playerID, tagPlayerID)) | 
 |  |  |      | 
 |  |  |     PlayerViewCacheTube.UpdPlayerPropPlusCache(curPlayer) # 强制刷一下自己的镜像缓存 | 
 |  |  |     factionInfoA = {"playerID":playerID, "pet":PlayerPet.GetPetCacheInfo(curPlayer)} | 
 |  |  |     factionInfoB = {} | 
 |  |  |     ipyData = None | 
 |  |  |     tagObj = None | 
 |  |  |     if tagPlayerID: | 
 |  |  |         npcID = ChConfig.Def_NPCID_PVP | 
 |  |  |         tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID, mirrorPlayerID=tagPlayerID) | 
 |  |  |         if not tagObj: | 
 |  |  |             return | 
 |  |  |         PlusData = PlayerViewCacheTube.GetPlayerPropPlusDictByID(playerID)[1] # 从缓存中获取 | 
 |  |  |         petCacheInfo = PlusData.get("Pet") | 
 |  |  |         fightPetObjListB = PetControl.CalloutFightPet(tagObj, petCacheInfo) | 
 |  |  |         PlusData = PlayerViewCacheTube.GetPlayerPropPlusDictByID(tagPlayerID)[1] # 从缓存中获取 | 
 |  |  |         factionInfoB = {"playerID":tagPlayerID, "pet":PlusData.get("Pet")} | 
 |  |  |     else: | 
 |  |  |         ipyData = IpyGameDataPY.GetIpyGameData("FBTurn", mapID, funcLineID) | 
 |  |  |         if not ipyData: | 
 |  |  | 
 |  |  |         npcID = ipyData.GetNPCID() | 
 |  |  |         if not npcID: | 
 |  |  |             return | 
 |  |  |         tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID) | 
 |  |  |         if not tagObj: | 
 |  |  |             return | 
 |  |  |         petNPCIDList = ipyData.GetPetNPCIDList() | 
 |  |  |         petCacheInfo = [] # 从配表中读取组合,技能默认取NPC表配置的 | 
 |  |  |         for state, petNPCID in enumerate(petNPCIDList, 1): | 
 |  |  |             petCacheInfo.append({"npcID":petNPCID, "state":state, "quality":0}) | 
 |  |  |         fightPetObjListB = PetControl.CalloutFightPet(tagObj, petCacheInfo) | 
 |  |  |         factionInfoB = {"npcID":npcID, "pet":petCacheInfo} | 
 |  |  |          | 
 |  |  |     ret = ProcessAutoTurnFight(mapID, funcLineID, factionInfoA, factionInfoB, tick, curPlayer) | 
 |  |  |     if not ret: | 
 |  |  |         return | 
 |  |  |     isWin, turnNum, turnMax, factionTotalHurtDict, playbackID = ret | 
 |  |  |      | 
 |  |  |     # 结算奖励...待扩展 | 
 |  |  |     awardItemList = [] | 
 |  |  |     if isWin and ipyData: | 
 |  |  |         # 山寨测试先默认都是首次奖励,正式后需删除 | 
 |  |  |         awardItemList = ipyData.GetAwardItemListFirst() | 
 |  |  |          | 
 |  |  |     GameWorld.DebugLog("奖励物品: %s" % awardItemList) | 
 |  |  |     ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["TurnFight", False, {"mapID":mapID, "funcLineID":funcLineID}]) | 
 |  |  |      | 
 |  |  |     overMsg = {"isWin":isWin, "itemInfo":FBCommon.GetJsonItemList(awardItemList), "totalHurt":factionTotalHurtDict.get(1, 0)} | 
 |  |  |     playbackID and overMsg.update({"playbackID":playbackID}) | 
 |  |  |     SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Award, turnNum, turnMax, overMsg) | 
 |  |  |     return | 
 |  |  |  | 
 |  |  | def ProcessAutoTurnFight(mapID, funcLineID, factionInfoA, factionInfoB, tick, syncPlayer=None, isSavePlayback=False): | 
 |  |  |     ''' 处理自动回合战斗过程,仅做战斗流程处理,不做及其他功能逻辑 | 
 |  |  |     @param mapID: 可视为功能ID | 
 |  |  |     @param funcLineID: 对功能ID的扩展 | 
 |  |  |     @param factionInfoA: A方阵营信息,playerID 和 npcID 二选一 {"playerID":主体玩家镜像ID, "npcID":主体NPCID, "pet":[{出战灵宠信息兼容玩家缓存的灵宠信息k:v, ...}, ...]} | 
 |  |  |     @param factionInfoB: B方阵营信息 | 
 |  |  |     @param syncPlayer: 需要通知的玩家,可能为None,注意仅做通知用,该玩家可能和AB阵营无任何关系 | 
 |  |  |     @param isSavePlayback: 是否保存战斗回放 | 
 |  |  |     @return: None-无结果;或 (isWin, turnNum, turnMax, factionTotalHurtDict) | 
 |  |  |                         isWin: 是否获胜 | 
 |  |  |                         turnNum: 打了几回合 | 
 |  |  |                         factionTotalHurtDict: 双方伤血统计 | 
 |  |  |     ''' | 
 |  |  |     if syncPlayer: | 
 |  |  |         syncPlayer.SetCanAttack(False) # 该玩家设置为不可被攻击 | 
 |  |  |         playerID = syncPlayer.GetPlayerID() | 
 |  |  |         sightLevel, posX, posY = playerID, syncPlayer.GetPosX(), syncPlayer.GetPosY() | 
 |  |  |     else: | 
 |  |  |         playerID = 0 | 
 |  |  |         sightLevel, posX, posY = 99, 192, 109 # 系统默认处理的层级及坐标 | 
 |  |  |          | 
 |  |  |     objRetA = __SummonFactionObjs(factionInfoA, sightLevel, posX, posY) | 
 |  |  |     objRetB = __SummonFactionObjs(factionInfoB, sightLevel, posX, posY) | 
 |  |  |     objA, petObjListA, factionSyncInfoA = objRetA if objRetA else (None, []) | 
 |  |  |     objB, petObjListB, factionSyncInfoB = objRetB if objRetB else (None, []) | 
 |  |  |     if not objA or not objB: | 
 |  |  |         return | 
 |  |  |     playerIDA = objA.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) # 可能为0,非玩家镜像时为0 | 
 |  |  |     playerIDB = objB.GetDictByKey(ChConfig.Def_NPC_Dict_MirrorPlayerID) # 可能为0,非玩家镜像时为0 | 
 |  |  |      | 
 |  |  |     objNameA = GetObjName(objA) | 
 |  |  |     objNameB = GetObjName(objB) | 
 |  |  |     GameWorld.DebugLog("===== 执行回合制战斗: %s VS %s =====" % (objNameA, objNameB)) | 
 |  |  |      | 
 |  |  |     turnMax = IpyGameDataPY.GetFuncCfg("TurnFight", 1) | 
 |  |  |     # 宠物先攻击 | 
 |  |  |     fightPetObjListA = PetControl.CalloutFightPet(curPlayer) | 
 |  |  |     factionListA = fightPetObjListA + [curPlayer] | 
 |  |  |     factionListB = fightPetObjListB + [tagObj] | 
 |  |  |     factionListA = petObjListA + [objA] | 
 |  |  |     factionListB = petObjListB + [objB] | 
 |  |  |     atkFactionList = [factionListA, factionListB] | 
 |  |  |      | 
 |  |  |     # 设置战斗主体 | 
 |  |  |     curPlayer.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) | 
 |  |  |     tagObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) | 
 |  |  |     objA.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) | 
 |  |  |     objB.SetDict(ChConfig.Def_Obj_Dict_TurnFightMainRole, 1) | 
 |  |  |      | 
 |  |  |     # 战斗前初始化,可能会改变攻速,所以先初始化 | 
 |  |  |     for faction, factionObjList in enumerate(atkFactionList, 1): | 
 |  |  | 
 |  |  |         fightObjList.sort(key=lambda o: (GameObj.GetAtkSpeed(o), (10 - GameObj.GetFaction(o)), o.GetID()), reverse=True) | 
 |  |  |     #方式2:根据阵营主角攻速决定先手,然后每个阵营轮流固定位置攻击 | 
 |  |  |     elif sortType == 2: | 
 |  |  |         if GameObj.GetAtkSpeed(curPlayer) < GameObj.GetAtkSpeed(tagObj): | 
 |  |  |         if GameObj.GetAtkSpeed(objA) < GameObj.GetAtkSpeed(objB): | 
 |  |  |             atkFactionList = [factionListB, factionListA] | 
 |  |  |         for i in range(len(factionListA)): | 
 |  |  |             for factionObjList in atkFactionList: | 
 |  |  |                 fightObjList.append(factionObjList[i]) | 
 |  |  |                  | 
 |  |  |     SyncTurnFightState(syncPlayer, mapID, funcLineID, playerIDB, FightState_PrepareOK, msg=[factionSyncInfoA, factionSyncInfoB]) | 
 |  |  |      | 
 |  |  |     isWin = None | 
 |  |  |     for turnNum in range(1, turnMax + 1): | 
 |  |  |         GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】" % turnNum) | 
 |  |  |         SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Fighting, turnNum, turnMax) | 
 |  |  |         SyncTurnFightState(syncPlayer, mapID, funcLineID, playerIDB, FightState_Fighting, turnNum, turnMax) | 
 |  |  |          | 
 |  |  |         # 回合开始: 做一些每回合重置逻辑或者某些根据回合触发的效果等 | 
 |  |  |         for gameObj in fightObjList: | 
 |  |  |             TurnFightObjPerTurnStart(gameObj, turnNum, tick) | 
 |  |  |              | 
 |  |  |         isWin = CheckIswin(curPlayer, tagObj) | 
 |  |  |         isWin = CheckIswin(objA, objB) | 
 |  |  |         if isWin != None: | 
 |  |  |             break | 
 |  |  |          | 
 |  |  | 
 |  |  |                  | 
 |  |  |             objType = gameObj.GetGameObjType() | 
 |  |  |             objID = gameObj.GetID() | 
 |  |  |             SyncTurnFightObjAction(curPlayer, turnNum, objType, objID) | 
 |  |  |             SyncTurnFightObjAction(syncPlayer, turnNum, objType, objID) | 
 |  |  |              | 
 |  |  |             if GameObj.GetHP(gameObj) <= 0: | 
 |  |  |                 # 复活时机在自己行动节点 | 
 |  |  | 
 |  |  |             objName = GetObjName(gameObj) | 
 |  |  |             curHP = GameObj.GetHP(gameObj) | 
 |  |  |              | 
 |  |  |             tagGameObj = tagObj if faction == 1 else curPlayer | 
 |  |  |             tagGameObj = objB if faction == 1 else objA | 
 |  |  |             tagObjType = tagGameObj.GetGameObjType() | 
 |  |  |             tagObjID = tagGameObj.GetID() | 
 |  |  |             tagHP = GameObj.GetHP(tagGameObj) | 
 |  |  | 
 |  |  |             if not DoAttack(gameObj, tagGameObj, tick): | 
 |  |  |                 continue | 
 |  |  |              | 
 |  |  |             isWin = CheckIswin(curPlayer, tagObj) | 
 |  |  |             isWin = CheckIswin(objA, objB) | 
 |  |  |             if isWin != None: | 
 |  |  |                 break | 
 |  |  |              | 
 |  |  |         if isWin != None: | 
 |  |  |             break | 
 |  |  |                  | 
 |  |  |     GameWorld.DebugLog("--- 战斗结束处理 ---") | 
 |  |  |          | 
 |  |  |     GameWorld.DebugLog("--- 战斗结束处理 --- isWin=%s" % isWin) | 
 |  |  |     isWin = 1 if isWin else 0 | 
 |  |  |      | 
 |  |  |     # 统计总伤害 | 
 |  |  |     factionTotalHurtDict = {} | 
 |  |  |     for gameObj in fightObjList: | 
 |  |  | 
 |  |  |     for faction, totalHurt in factionTotalHurtDict.items(): | 
 |  |  |         GameWorld.DebugLog("faction=%s, 阵营总输出: %s" % (faction, totalHurt)) | 
 |  |  |          | 
 |  |  |     GameWorld.DebugLog("玩家剩余血量: %s / %s" % (GameObj.GetHP(curPlayer), GameObj.GetMaxHP(curPlayer))) | 
 |  |  |     GameWorld.DebugLog("对方剩余血量: %s / %s" % (GameObj.GetHP(tagObj), GameObj.GetMaxHP(tagObj))) | 
 |  |  |     GameWorld.DebugLog("A剩余血量: %s / %s" % (GameObj.GetHP(objA), GameObj.GetMaxHP(objA))) | 
 |  |  |     GameWorld.DebugLog("B剩余血量: %s / %s" % (GameObj.GetHP(objB), GameObj.GetMaxHP(objB))) | 
 |  |  |      | 
 |  |  |     # 结算奖励...待扩展 | 
 |  |  |     awardItemList = [] | 
 |  |  |     if isWin and ipyData: | 
 |  |  |         # 山寨测试先默认都是首次奖励,正式后需删除 | 
 |  |  |         awardItemList = ipyData.GetAwardItemListFirst() | 
 |  |  |          | 
 |  |  |     GameWorld.DebugLog("奖励物品: %s" % awardItemList) | 
 |  |  |     ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["TurnFight", False, {"mapID":mapID, "funcLineID":funcLineID}]) | 
 |  |  |      | 
 |  |  |     overMsg = {"itemInfo":FBCommon.GetJsonItemList(awardItemList), "totalHurt":factionTotalHurtDict.get(1, 0)} | 
 |  |  |     overState = FightState_Win if isWin else FightState_Fail | 
 |  |  |     SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, overState, turnNum, turnMax, str(overMsg)) | 
 |  |  |     SyncTurnFightState(syncPlayer, mapID, funcLineID, playerIDB, FightState_FightEnd, turnNum, turnMax) | 
 |  |  |      | 
 |  |  |     for gameObj in fightObjList: | 
 |  |  |         TurnFightObjOverReset(gameObj, tick) | 
 |  |  |          | 
 |  |  |     GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,playerID=%s,tagPlayerID=%s,isWin=%s,overState=%s"  | 
 |  |  |                        % (mapID, funcLineID, playerID, tagPlayerID, isWin, overState)) | 
 |  |  |     return | 
 |  |  |     playbackID = 0 # 战斗回放ID,可根据该ID查看回放 | 
 |  |  |     #playbackInfo = "" # 战斗回放信息 | 
 |  |  |     if isSavePlayback: | 
 |  |  |         pass | 
 |  |  |      | 
 |  |  |     GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,playerIDA=%s,playerIDB=%s,isWin=%s"  | 
 |  |  |                        % (mapID, funcLineID, playerIDA, playerIDB, isWin)) | 
 |  |  |     return isWin, turnNum, turnMax, factionTotalHurtDict, playbackID | 
 |  |  |  | 
 |  |  | def __SummonFactionObjs(factionInfo, sightLevel, posX, posY): | 
 |  |  |     ## 召唤阵营战斗实例 | 
 |  |  |     factionSyncInfo = {} # 同步前端的阵营信息,包含主ID、灵宠、其他灵通等 | 
 |  |  |     playerID = factionInfo.get("playerID") | 
 |  |  |     npcID = factionInfo.get("npcID") | 
 |  |  |     if playerID: | 
 |  |  |         npcID = ChConfig.Def_NPCID_PVP | 
 |  |  |         mainObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=sightLevel, mirrorPlayerID=playerID) | 
 |  |  |         factionSyncInfo["playerID"] = playerID | 
 |  |  |     elif npcID: | 
 |  |  |         mainObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=sightLevel) | 
 |  |  |         factionSyncInfo["npcID"] = npcID | 
 |  |  |     else: | 
 |  |  |         return | 
 |  |  |     if not mainObj: | 
 |  |  |         return | 
 |  |  |     petObjList = PetControl.CalloutFightPet(mainObj, factionInfo.get("pet")) | 
 |  |  |     petObjIDList = [] | 
 |  |  |     for petObj in petObjList: | 
 |  |  |         if petObj: | 
 |  |  |             petObjIDList.append(petObj.GetID()) | 
 |  |  |     factionSyncInfo.update({"objID":mainObj.GetID(), "petObjIDList":petObjIDList}) | 
 |  |  |     return mainObj, petObjList, factionSyncInfo | 
 |  |  |  | 
 |  |  | def CheckIswin(curPlayer, tagObj): | 
 |  |  |     ## 检查是否结束 | 
 |  |  | 
 |  |  |     return useSkillResult | 
 |  |  |  | 
 |  |  | def SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, state, turnNum=0, turnMax=0, msg=""): | 
 |  |  |     if not curPlayer: | 
 |  |  |         return | 
 |  |  |     clientPack = ChPyNetSendPack.tagMCTurnFightState() | 
 |  |  |     clientPack.Clear() | 
 |  |  |     clientPack.MapID = mapID | 
 |  |  | 
 |  |  |     clientPack.State = state | 
 |  |  |     clientPack.TurnNum = turnNum | 
 |  |  |     clientPack.TurnMax = turnMax | 
 |  |  |     clientPack.Msg = msg | 
 |  |  |     clientPack.Msg = str(msg) | 
 |  |  |     clientPack.Len = len(clientPack.Msg)     | 
 |  |  |     NetPackCommon.SendFakePack(curPlayer, clientPack) | 
 |  |  |     return | 
 |  |  |  | 
 |  |  | def SyncTurnFightObjAction(curPlayer, turnNum, objType, objID): | 
 |  |  |     if not curPlayer: | 
 |  |  |         return | 
 |  |  |     clientPack = ChPyNetSendPack.tagMCTurnFightObjAction() | 
 |  |  |     clientPack.Clear() | 
 |  |  |     clientPack.TurnNum = turnNum |