| | |
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: 回合制攻击逻辑,均使用NPC实例作为战斗主体
|
| | | # 实时战斗: 仅用于主线,每个玩家最多仅允许存在一个实时战斗
|
| | | # 由前端控制战斗流程,后端进行计算
|
| | | # 瞬时战斗: 用于非主线外的各种战斗,如副本PVE挑战,PVP挑战等,一样仅有一个瞬时战斗,
|
| | | # 一次性处理完,后端控制整体战斗流程及计算,前端仅做战报解析表现战斗过程
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2023-11-30 15:30"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import ChConfig
|
| | | import PlayerTask
|
| | | import PlayerViewCache
|
| | | import ChPyNetSendPack
|
| | | import NetPackCommon
|
| | | import PlayerControl
|
| | | import GameWorld
|
| | | import GameObj
|
| | | import FBCommon
|
| | | import IpyGameDataPY
|
| | | import PlayerOnline
|
| | | import NPCCommon
|
| | | import ShareDefine
|
| | | import PyGameData
|
| | | import SkillCommon
|
| | | import BattleObj
|
| | | import TurnPassive
|
| | | import TurnSkill
|
| | | import TurnBuff
|
| | | import CommFunc
|
| | | import ObjPool
|
| | | import FBLogic
|
| | |
|
| | | import random
|
| | | import time
|
| | | import json
|
| | |
|
| | | TimelineSet = 10000 # 单回合最大时间轴
|
| | | PosNumMax = 7 # 最大站位编号
|
| | | ActionNumStart = -1 # 起始行动位置编号,一般是从1开始,如果有加主公、红颜等则扣除相应位置值,如从0或-1开始
|
| | |
|
| | | # 回合战斗流程状态
|
| | | (
|
| | |
| | | FightState_FightEnd, # 3 战斗结束
|
| | | FightState_Award, # 4 结算奖励
|
| | | FightState_Over, # 5 结束状态,无特殊意义,仅代表所有处理结束了,与Start对应
|
| | | ) = range(6)
|
| | | FightState_Rest, # 6 结束并休息,一般是前端主动退出并休息的
|
| | | ) = range(7)
|
| | | |
| | | class BatLineup():
|
| | | ## 战斗阵容
|
| | | |
| | | def __init__(self, faction, num, turnFight):
|
| | | self.turnFight = turnFight # TurnFight
|
| | | self.faction = faction # 所属阵营
|
| | | self.num = num # 该阵容所在阵营中的编号,不同阵营可重复,多V多
|
| | | self.ownerID = 0 # 阵容所属玩家ID,可能为0,0代表非玩家阵容
|
| | | self.shapeType = 0 # 阵型
|
| | | self.fightPower = 0 # 阵容总战力
|
| | | self.posObjIDDict = {} # 站位对应战斗实体 {站位编号:batObjID, ...}, 站位编号小于0为非主战单位,如主公、红颜等
|
| | | self.lingshouObjIDDict = {} # 灵兽战斗单位 {位置编号:batObjID, ...}
|
| | | self.beautyObjIDDict = {} # 红颜战斗单位 {位置编号:batObjID, ...}
|
| | | self.actionNum = ActionNumStart # 行动位置,从1开始
|
| | | return
|
| | | |
| | | def getPlayerID(self): return self.turnFight.playerID # 发起的玩家ID
|
| | | |
| | | 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("ShapeType", 0)
|
| | | self.fightPower = lineupInfo.get("FightPower", 0)
|
| | | SummonLineupObjs(self, self.faction, self.num, lineupInfo, self.getPlayerID())
|
| | | return
|
| | | |
| | | def clearLineup(self):
|
| | | ## 清除阵容
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | for objID in self.posObjIDDict.values():
|
| | | batObjMgr.delBatObj(objID)
|
| | | for objID in self.lingshouObjIDDict.values():
|
| | | batObjMgr.delBatObj(objID)
|
| | | for objID in self.beautyObjIDDict.values():
|
| | | batObjMgr.delBatObj(objID)
|
| | | self.posObjIDDict = {}
|
| | | self.lingshouObjIDDict = {}
|
| | | self.beautyObjIDDict = {}
|
| | | self.fightPower = 0
|
| | | return
|
| | | |
| | | class BatFaction():
|
| | | ## 战斗阵营
|
| | | |
| | | def __init__(self, faction, turnFight):
|
| | | self.turnFight = turnFight # TurnFight
|
| | | self.faction = faction
|
| | | self.lineupDict = {} # 该阵营所有阵容信息 {编号:BatLineup, ...}
|
| | | return
|
| | | |
| | | def getBatlineup(self, num=1):
|
| | | ## 获取战斗阵容
|
| | | lineup = None
|
| | | if num in self.lineupDict:
|
| | | lineup = self.lineupDict[num]
|
| | | else:
|
| | | lineup = BatLineup(self.faction, num, self.turnFight)
|
| | | self.lineupDict[num] = lineup
|
| | | return lineup
|
| | | |
| | | def clearLineups(self):
|
| | | ## 清除所有战斗阵容
|
| | | for lineup in self.lineupDict.values():
|
| | | lineup.clearLineup()
|
| | | return
|
| | | |
| | | class TurnFight():
|
| | | '''某场回合战斗,支持多V多,所有战斗通用,主线、爬塔、PVP等
|
| | | 可能为系统后台发起的,则攻击方、防守方阵容以玩家所保存的阵容镜像进行战斗
|
| | | 如果玩家发起的,则攻击方为发起方玩家,目标为防守方,支持多V多,如组队PK
|
| | | 多V多的情况也是某个队员各自发起战斗,只是用到队友的镜像阵容一起战斗,队友无感知
|
| | | |
| | | 多V多可使用两种模式:
|
| | | 1. 多个阵容一起出场,在一场战斗中完成
|
| | | 2. 以单阵容方式轮流出场战斗,该方式同样可以使用方式1的逻辑实现,固优先使用方式1战斗逻辑,方便扩展
|
| | | '''
|
| | | |
| | | def __init__(self, mapID=0, funcLineID=0, playerID=0, isNeedReport=False):
|
| | | self.guid = GameWorld.GetGUID() # 某场战斗的唯一guid,可用于存储记录如战报等
|
| | | self.playerID = playerID # 可能为0,系统后台自动处理的战斗时为0,某个玩家发起则为发起玩家ID,同个玩家ID可能同时存在多场战斗,如主线+其他
|
| | | self.curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID) if playerID else None
|
| | | self.mapID = mapID
|
| | | self.funcLineID = funcLineID
|
| | | self.state = -1 # -1 代表未战斗
|
| | | self.turnNum = 1 # 当前第x回合,默认第1回合开始
|
| | | self.turnMax = 15 # 最大回合数
|
| | | self.enterLogic = False # 是否已执行进场逻辑
|
| | | self.winFaction = 0 # 本场战斗结束标记,获胜阵营,为0时代表未结束,所有小队打完或失败才有结果,0-未结束,>0-获胜的阵营
|
| | | self.isWin = False
|
| | | self.batBuffer = "" # 战报buffer,战报暂时只保留最后一个小队的
|
| | | self.isNeedReport = isNeedReport # 是否需要战报
|
| | | self.msgDict = {} # 扩展信息字典,一般由MapID绑定的功能决定信息内容 {k:v, ...}
|
| | | |
| | | self.factionDict = {} # 战斗阵营 {faction:BatFaction, ...},一般是只有两个阵营,faction为1或2,每个阵营支持多个阵容
|
| | | self.actionSortList = [] # 阵容行动顺序 [[faction, num], ...]
|
| | | self.actionIndex = 0 # 行动顺序索引 |
| | | self.timeline = 0 # 时间轴节点 turnNum*1000+actionIndex*100++actionNum
|
| | | self.startTime = 0 # 开始时间戳,支持毫秒小数
|
| | | self.costTime = 0 # 单场战斗总耗时,支持毫秒小数
|
| | | |
| | | # pve 多小队 - 一般只有PVE用到
|
| | | self.lineupIndex = 0 # 当前小队索引
|
| | | self.lineupIDList = [] # npc小队列表
|
| | | self.strongerLV = 0 # npc成长等级
|
| | | self.difficulty = 0 # npc难度
|
| | | |
| | | # pvp 目标
|
| | | self.tagPlayerID = 0
|
| | | self.tagViewCache = None
|
| | | return
|
| | | |
| | | def setTurnFight(self, mapID, funcLineID, turnMax, isNeedReport=False, msgDict={}):
|
| | | ## 设置本场回合战斗设定
|
| | | self.mapID = mapID
|
| | | self.funcLineID = funcLineID
|
| | | self.turnMax = turnMax # 最大回合数
|
| | | self.isNeedReport = isNeedReport
|
| | | self.setPVE()
|
| | | self.setPVP()
|
| | | self.msgDict = {}
|
| | | self.nextTurnFight(msgDict)
|
| | | return
|
| | | |
| | | def setPVE(self, lineupIDList=[], strongerLV=0, difficulty=0):
|
| | | self.lineupIndex = 0
|
| | | self.lineupIDList = lineupIDList
|
| | | self.strongerLV = strongerLV
|
| | | self.difficulty = difficulty
|
| | | return
|
| | | |
| | | def setPVP(self, tagPlayerID=0, tagViewCache=None):
|
| | | self.tagPlayerID = tagPlayerID
|
| | | self.tagViewCache = tagViewCache
|
| | | return
|
| | | |
| | | #def setPVPTeam(self):
|
| | | # return
|
| | | |
| | | def nextTurnFight(self, msgDict={}, resetByNextTeam=False):
|
| | | ## 一般用于玩家发起的战斗,在需要保留玩家阵容属性及状态的情况下,重置回合进入下一场战斗
|
| | | self.turnNum = 1
|
| | | self.enterLogic = False
|
| | | self.winFaction = 0
|
| | | self.isWin = False
|
| | | self.msgDict.update(msgDict)
|
| | | self.timeline = 0
|
| | | self.startTime = time.time()
|
| | | self.costTime = 0
|
| | | if resetByNextTeam:
|
| | | ResetByNextTeam(self)
|
| | | return
|
| | | |
| | | def haveNextLineup(self):
|
| | | ## 是否可以打下一小队,获胜且还有下一小队时可打
|
| | | return (self.winFaction == ChConfig.Def_FactionA and self.lineupIndex < len(self.lineupIDList) - 1)
|
| | | def nextLineupID(self):
|
| | | ## 下一小队ID
|
| | | if not self.haveNextLineup():
|
| | | return 0
|
| | | self.lineupIndex += 1
|
| | | return self.lineupIDList[self.lineupIndex]
|
| | | |
| | | def setFactionLineup(self, faction, lineupDict):
|
| | | ## 设置阵营阵容
|
| | | # @param lineupDict: {阵容编号:阵容信息, ...} 每个阵营支持多个阵容,即支持多V多
|
| | | batFaction = self.getBatFaction(faction)
|
| | | batFaction.clearLineups()
|
| | | for num, lineupInfo in lineupDict.items():
|
| | | if not lineupInfo:
|
| | | continue
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | batLineup.setLineup(lineupInfo)
|
| | | return
|
| | | |
| | | def sortActionQueue(self):
|
| | | ## 刷新出手顺序队列
|
| | | sortList = []
|
| | | for batFaction in self.factionDict.values():
|
| | | faction = batFaction.faction
|
| | | for num, batLineup in batFaction.lineupDict.items():
|
| | | isPlayer = 1 if batLineup.ownerID else 0 # 玩家阵容优先攻击
|
| | | fightPower = batLineup.fightPower
|
| | | sortValue = -(faction * 10 + num)
|
| | | sortList.append([isPlayer, fightPower, sortValue, faction, num])
|
| | | sortList.sort(reverse=True) # 战力高的先手
|
| | | |
| | | self.actionIndex = 0
|
| | | self.actionSortList = []
|
| | | for _, _, _, faction, num in sortList:
|
| | | self.actionSortList.append([faction, num])
|
| | | |
| | | GameWorld.DebugLog("阵容战力排序[isPlayer, fp, sortV, f, n]: %s" % sortList)
|
| | | GameWorld.DebugLog("阵容行动顺序[f, n]: %s" % self.actionSortList)
|
| | | return
|
| | | |
| | | def getTurnNumStartTimelin(self, turnNum): return turnNum * TimelineSet + 0 # 每回合的时间节点起点
|
| | | def getTimeline(self): return self.timeline
|
| | | def setTimeline(self, timeline, isEmpty=False):
|
| | | '''回合战斗的时间轴节点 ,即第几回合开始,每个回合支持9999个行动节点
|
| | | @param turnNum: 第x回合
|
| | | '''
|
| | | self.timeline = timeline
|
| | | GameWorld.DebugLog("时间节点更新: %s" % self.timeline)
|
| | | if isEmpty:
|
| | | # 空位置的节点可直接跳过
|
| | | return timeline
|
| | | |
| | | OnTimelineChange(self)
|
| | | return timeline
|
| | | |
| | | def getBatFaction(self, faction=ChConfig.Def_FactionA):
|
| | | ## 默认阵营1
|
| | | batFaction = None
|
| | | if faction in self.factionDict:
|
| | | batFaction = self.factionDict[faction]
|
| | | else:
|
| | | batFaction = BatFaction(faction, self)
|
| | | self.factionDict[faction] = batFaction
|
| | | return batFaction
|
| | | |
| | | def checkOverByKilled(self):
|
| | | ##检查是否击杀结束
|
| | | # @return: 0-无获胜阵营,同时也代表战斗未结束;>0-获胜的阵营ID,同时也代表战斗已全部结束
|
| | | |
| | | 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, objID in batLineup.posObjIDDict.items():
|
| | | if posNum <= 0:
|
| | | # 非主战位置不判断
|
| | | continue
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | if not batObj:
|
| | | continue
|
| | | if batObj.IsAlive():
|
| | | allKilled = False
|
| | | break
|
| | | |
| | | if allKilled:
|
| | | self.winFaction = ChConfig.Def_FactionA if faction == ChConfig.Def_FactionB else ChConfig.Def_FactionB
|
| | | DoTurnFightOver(self.guid)
|
| | | return self.winFaction
|
| | | |
| | | return 0
|
| | | |
| | | def exitFight(self, rest=False):
|
| | | ## 退出战斗
|
| | | self.syncState(FightState_Over if not rest else FightState_Rest)
|
| | | for batFaction in self.factionDict.values():
|
| | | batFaction.clearLineups()
|
| | | self.state = -1
|
| | | return
|
| | | |
| | | def startFight(self):
|
| | | ## 准备就绪,开始战斗
|
| | | self.state = FightState_Start
|
| | | self.turnNum = 1
|
| | | self.timeline = self.getTurnNumStartTimelin(self.turnNum)
|
| | | self.syncInit()
|
| | | return
|
| | | |
| | | def isInFight(self): return self.state != -1
|
| | | |
| | | def syncInit(self):
|
| | | ## 初始化通知
|
| | | msg = json.dumps(self.msgDict, ensure_ascii=False)
|
| | | msg = msg.replace(" ", "")
|
| | | clientPack = ChPyNetSendPack.tagSCTurnFightInit()
|
| | | clientPack.MapID = self.mapID
|
| | | clientPack.FuncLineID = self.funcLineID
|
| | | clientPack.TurnMax = self.turnMax
|
| | | 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()
|
| | | tfFaction.Faction = faction
|
| | | tfFaction.LineupList = []
|
| | | for num in batFaction.lineupDict.keys():
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | tfLineup = ChPyNetSendPack.tagSCTurnFightLineup()
|
| | | tfLineup.Num = num
|
| | | tfLineup.OwnerID = batLineup.ownerID
|
| | | tfLineup.ShapeType = batLineup.shapeType
|
| | | tfLineup.ObjList = []
|
| | | for posNum, objID in batLineup.posObjIDDict.items():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | if not batObj:
|
| | | continue
|
| | | tfObj = ChPyNetSendPack.tagSCTurnFightObj()
|
| | | 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 = batObj.GetXP()
|
| | | tfLineup.ObjList.append(tfObj)
|
| | | tfLineup.ObjCnt = len(tfLineup.ObjList)
|
| | | tfFaction.LineupList.append(tfLineup)
|
| | | tfFaction.LineupCnt = len(tfFaction.LineupList)
|
| | | clientPack.FactionList.append(tfFaction)
|
| | | clientPack.FactionCnt = len(clientPack.FactionList)
|
| | | self.addBatPack(clientPack)
|
| | | return
|
| | | |
| | | def syncState(self, state, msgDict={}):
|
| | | self.state = state
|
| | | msg = json.dumps(msgDict, ensure_ascii=False)
|
| | | msg = msg.replace(" ", "")
|
| | | clientPack = ChPyNetSendPack.tagMCTurnFightState()
|
| | | clientPack.Clear()
|
| | | clientPack.MapID = self.mapID
|
| | | clientPack.FuncLineID = self.funcLineID
|
| | | clientPack.State = state
|
| | | clientPack.TurnNum = self.turnNum
|
| | | clientPack.Msg = msg
|
| | | clientPack.Len = len(clientPack.Msg)
|
| | | self.addBatPack(clientPack)
|
| | | return
|
| | | |
| | | def syncObjAction(self, turnNum, objID):
|
| | | clientPack = ChPyNetSendPack.tagMCTurnFightObjAction()
|
| | | clientPack.Clear()
|
| | | clientPack.TurnNum = turnNum
|
| | | clientPack.ObjID = objID
|
| | | self.addBatPack(clientPack)
|
| | | return
|
| | | |
| | | def addBatPack(self, clientPack):
|
| | | ## 添加战斗过程封包,非战斗相关的封包可以不使用该函数发送,如加经验、掉落等
|
| | | ## 注:战斗相关的封包需调用本函数方便统一管理战报
|
| | | if hasattr(clientPack, "Head"):
|
| | | headStr = "%02x%02x" % (clientPack.Head.Cmd, clientPack.Head.SubCmd)
|
| | | else:
|
| | | headStr = "%02x%02x" % (clientPack.Cmd, clientPack.SubCmd)
|
| | | if self.isNeedReport:
|
| | | packBuff = clientPack.GetBuffer()
|
| | | buffLen = len(packBuff)
|
| | | GameWorld.DebugLog("回合战斗过程封包: %s, len:%s" % (headStr, buffLen))
|
| | | self.batBuffer += CommFunc.WriteWORD("", buffLen)
|
| | | self.batBuffer += packBuff
|
| | | ObjPool.GetPoolMgr().release(clientPack)
|
| | | else:
|
| | | GameWorld.DebugLog("回合战斗过程封包: %s" % (headStr))
|
| | | # 有玩家的统一每个包单独发送,同样也支持战报统计
|
| | | if self.curPlayer:
|
| | | NetPackCommon.SendFakePack(self.curPlayer, clientPack)
|
| | | else:
|
| | | ObjPool.GetPoolMgr().release(clientPack)
|
| | | return
|
| | | |
| | | class TurnFightMgr():
|
| | | ## 回合战斗管理器
|
| | | |
| | | def __init__(self):
|
| | | self.turnFightDict = {} # {guid:TurnFight, ...}
|
| | | return
|
| | | |
| | | def addTurnFight(self, mapID, funcLineID=0, playerID=0, isNeedReport=False):
|
| | | tf = ObjPool.GetPoolMgr().acquire(TurnFight, mapID, funcLineID, playerID, isNeedReport)
|
| | | if not tf:
|
| | | tf = TurnFight(mapID, funcLineID, playerID, isNeedReport) # 一般是不可能,为了点出代码
|
| | | self.turnFightDict[tf.guid] = tf
|
| | | return tf
|
| | | |
| | | def delTurnFight(self, guid):
|
| | | turnFight = self.getTurnFight(guid)
|
| | | if not turnFight:
|
| | | return
|
| | | turnFight.exitFight()
|
| | | self.turnFightDict.pop(guid, None)
|
| | | ObjPool.GetPoolMgr().release(turnFight)
|
| | | return
|
| | | |
| | | def getTurnFight(self, guid):
|
| | | tf = None
|
| | | if guid in self.turnFightDict:
|
| | | tf = self.turnFightDict[guid]
|
| | | elif False:
|
| | | tf = TurnFight()
|
| | | return tf
|
| | | |
| | | def GetTurnFightMgr():
|
| | | tfMgr = None
|
| | | if PyGameData.g_turnFightMgr:
|
| | | tfMgr = PyGameData.g_turnFightMgr
|
| | | else:
|
| | | tfMgr = TurnFightMgr()
|
| | | PyGameData.g_turnFightMgr = tfMgr
|
| | | return tfMgr
|
| | | |
| | | class MainFight():
|
| | | ## 主线战斗管理
|
| | | |
| | | def __init__(self, playerID):
|
| | | self.playerID = playerID
|
| | | self.chapterID = 0 # 章节ID
|
| | | self.levelNum = 0 # 关卡编号
|
| | | self.waveMax = 6 # 本关最大波数,每波有多个小队,每个小队即为一张战斗 TurnFight
|
| | | self.wave = 0 # 当前刷怪波,注意不是玩家当前进度波,比如被击杀会回退一波
|
| | | self.turnFight = GetTurnFightMgr().addTurnFight(ChConfig.Def_FBMapID_Main, 0, playerID)
|
| | | return
|
| | | |
| | | def isLevelBoss(self):
|
| | | ## 当前战斗是否关卡boss
|
| | | return self.turnFight.mapID == ChConfig.Def_FBMapID_MainBoss
|
| | | |
| | | def GetMainFightMgr(curPlayer):
|
| | | ## 获取主线战斗管理
|
| | | olPlayer = PlayerOnline.GetOnlineMgr().GetOnlinePlayer(curPlayer)
|
| | | return olPlayer.mainFight
|
| | |
|
| | | def OnPlayerLogin(curPlayer):
|
| | | chapterID, levelNum, _ = PlayerControl.GetMainLevelPassInfo(curPlayer)
|
| | | nowChapterID, _, _ = PlayerControl.GetMainLevelNowInfo(curPlayer)
|
| | | if chapterID != nowChapterID:
|
| | | if IpyGameDataPY.GetIpyGameDataNotLog("MainChapter", chapterID) and IpyGameDataPY.GetIpyGameDataNotLog("MainLevel", chapterID, levelNum):
|
| | | fixNowValue = PlayerControl.SetMainLevelNowInfo(curPlayer, chapterID, levelNum, 1)
|
| | | GameWorld.Log("当前主线关卡章节与过关章节不一致时,且过关进度章节已经存在,强制修正当前刷怪进度为过关章节进度! passChapterID-LV=%s-%s,nowChapterID=%s,fixNowValue=%s" |
| | | % (chapterID, levelNum, nowChapterID, fixNowValue), curPlayer.GetPlayerID())
|
| | | return
|
| | |
|
| | |
|
| | | def GetCacheLineupFightPower(tagViewCache, lineupID):
|
| | | lineupInfo = GetCacheLineupInfo(tagViewCache, lineupID)
|
| | | return lineupInfo.get("FightPower", 0)
|
| | | def GetCacheLineupInfo(tagViewCache, lineupID):
|
| | | ## 根据查看缓存获取阵容信息,一般是 GetPlayerLineupInfo 返回的结果
|
| | | plusDict = tagViewCache.GetPlusDict()
|
| | | lineupDict = plusDict.get("Lineup", {})
|
| | | lineupInfo = lineupDict.get("%s" % lineupID, {})
|
| | | if not lineupInfo:
|
| | | lineupInfo = lineupDict.get("%s" % ShareDefine.Lineup_Main, {})
|
| | | return lineupInfo
|
| | |
|
| | | def GetPlayerLineupFightPower(curPlayer, lineupID):
|
| | | ## 获取玩家阵容战力,一般用于直接获取阵容战力记录用
|
| | | return GetPlayerLineup(curPlayer, lineupID).fightPower
|
| | | def GetPlayerLineup(curPlayer, lineupID):
|
| | | ## 获取玩家阵容
|
| | | olPlayer = PlayerOnline.GetOnlinePlayer(curPlayer)
|
| | | lineup = olPlayer.GetLineup(lineupID)
|
| | | if not lineup.lineupHeroDict:
|
| | | # 为空时默认取主阵容
|
| | | lineup = olPlayer.GetLineup(ShareDefine.Lineup_Main)
|
| | | return lineup
|
| | |
|
| | | def GetPlayerLineupInfo(curPlayer, lineupID):
|
| | | ## 获取玩家阵容信息,可用于战斗或查看缓存,因为可能取玩家的缓存进行对战,所以统一使用json格式,前端通用
|
| | | # @param lineupID: 阵容ID
|
| | | # @return: 阵容全部信息json字典,前端通用格式
|
| | | |
| | | playerID = curPlayer.GetPlayerID()
|
| | | lineup = GetPlayerLineup(curPlayer, lineupID)
|
| | | if not lineup.lineupHeroDict:
|
| | | return {}
|
| | | |
| | | heroDict = {}
|
| | | curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero)
|
| | | 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":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,
|
| | | }
|
| | | |
| | | if not heroDict:
|
| | | return {}
|
| | | |
| | | lineupInfo = {"PlayerID":playerID, "FightPower":lineup.fightPower, "ShapeType":lineup.shapeType, "Hero":heroDict}
|
| | | return lineupInfo
|
| | |
|
| | | 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:
|
| | | return {}
|
| | | |
| | | heroDict = {}
|
| | | for posNum in range(1, 1 + 10):
|
| | | if not hasattr(ipyData, "GetPosNPCID%s" % posNum):
|
| | | break
|
| | | npcID = getattr(ipyData, "GetPosNPCID%s" % posNum)()
|
| | | if not npcID:
|
| | | continue
|
| | | battleDict = GetNPCBattleDict(ipyData, npcID, strongerLV, difficulty)
|
| | | if not battleDict:
|
| | | continue
|
| | | heroDict[str(posNum)] = battleDict
|
| | | |
| | | lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict}
|
| | | return lineupInfo
|
| | |
|
| | | def GetNPCBattleDict(lineupIpyData, 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()
|
| | | |
| | | # boss额外随机技能
|
| | | bossID = lineupIpyData.GetBossID()
|
| | | if npcID == bossID:
|
| | | skillIDExList = lineupIpyData.GetSkillIDExList()
|
| | | if skillIDExList:
|
| | | randSkillIDExList = [] + list(skillIDExList)
|
| | | skillExCnt = lineupIpyData.GetSkillExCnt()
|
| | | if skillExCnt > 0 and len(randSkillIDExList) > skillExCnt:
|
| | | random.shuffle(randSkillIDExList)
|
| | | randSkillIDExList = randSkillIDExList[:skillExCnt]
|
| | | skillIDList += randSkillIDExList
|
| | | GameWorld.DebugLog("阵容boss技能: %s, 随机附加技能: %s" % (skillIDList, randSkillIDExList))
|
| | | |
| | | # 成长怪属性
|
| | | 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(), |
| | | 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())
|
| | | |
| | | 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.GetIpyGameDataListNotLog("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):
|
| | | '''召唤阵容战斗实例
|
| | | @param faction: 所属阵营,目前支持两个阵营,1或2
|
| | | @param num: 战斗阵容在该阵营上的编号,1V1时默认1,多对多时1~n
|
| | | @param lineupInfo: 阵容信息
|
| | | @param playerID: 发起的玩家ID,系统场次为0
|
| | | '''
|
| | | GameWorld.DebugLog("SummonLineupObjs faction:%s,num:%s,lineupInfo=%s" % (faction, num, lineupInfo), playerID)
|
| | | if playerID:
|
| | | curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
|
| | | if not curPlayer:
|
| | | return
|
| | | |
| | | tfGUID = batLineup.turnFight.guid
|
| | | lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
|
| | | heroDict = lineupInfo.get("Hero", {})
|
| | | |
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
|
| | | for posNumKey, heroInfo in heroDict.items():
|
| | | posNum = int(posNumKey)
|
| | | |
| | | fightPower = 0
|
| | | skillIDList = [] # 战斗对象可能改变属性或技能,重新创建,防止误修改来源值
|
| | | attrDict = {}
|
| | | skillIDList += heroInfo.get("SkillIDList", [])
|
| | | attrDict.update(heroInfo.get("AttrDict", {}))
|
| | | 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:
|
| | | specialty = heroIpyData.GetSpecialty()
|
| | | atkDistType = heroIpyData.GetAtkDistType()
|
| | | objName = heroIpyData.GetName()
|
| | | country = heroIpyData.GetCountry()
|
| | | sex = heroIpyData.GetSex()
|
| | | |
| | | if lineupPlayerID:
|
| | | fightPower = heroInfo.get("FightPower", 0)
|
| | | if not heroIpyData:
|
| | | continue
|
| | | |
| | | else:
|
| | | npcDataEx = NPCCommon.GetNPCDataPy(npcID)
|
| | | if not npcDataEx:
|
| | | continue
|
| | | if not heroIpyData:
|
| | | specialty = npcDataEx.GetSpecialty()
|
| | | 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)
|
| | | batObj.SetAtkDistType(atkDistType)
|
| | | batObj.SetSpecialty(specialty)
|
| | | batObj.SetCountry(country)
|
| | | batObj.SetSex(sex)
|
| | | batObj.SetHero(heroID, skinID)
|
| | | |
| | | skillManager = batObj.GetSkillManager()
|
| | | skillManager.SkillReset()
|
| | | for skillID in skillIDList:
|
| | | skillManager.LearnSkillByID(skillID)
|
| | | |
| | | batLineup.posObjIDDict[posNum] = objID
|
| | | GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillManager.GetSkillIDList()))
|
| | | batObj.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP)
|
| | | |
| | | return
|
| | |
|
| | | def ResetByNextTeam(turnFight):
|
| | | ## 切换下一小队时重置相关,目前设置仅保留血量、怒气、已被击杀的不复活,其他重置
|
| | | |
| | | batFaction = turnFight.getBatFaction(ChConfig.Def_FactionA)
|
| | | if not batFaction:
|
| | | return
|
| | | GameWorld.DebugLog("切换小队重置玩家阵容武将...")
|
| | | batLineup = batFaction.getBatlineup(1) # 只处理玩家阵容
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | if not batObj:
|
| | | continue
|
| | | objName = GetObjName(batObj)
|
| | | if not batObj.IsAlive():
|
| | | GameWorld.DebugLog(" 已被击杀不处理! %s" % (objName))
|
| | | continue
|
| | | GameWorld.DebugLog(" 重置武将: %s, HP:%s/%s, XP:%s" % (objName, batObj.GetHP(), batObj.GetMaxHP(), batObj.GetXP()))
|
| | | |
| | | batObj.TurnReset()
|
| | | |
| | | # 清除buff
|
| | | buffMgr = batObj.GetBuffManager()
|
| | | buffMgr.ClearBuff()
|
| | | |
| | | # 重置CD
|
| | | |
| | | # 重刷属性、被动
|
| | | TurnBuff.RefreshBuffAttr(batObj)
|
| | | TurnPassive.RefreshPassive(batObj)
|
| | | |
| | | return
|
| | |
|
| | | #// B4 10 回合制战斗 #tagCMTurnFight
|
| | | #
|
| | | #struct tagCMTurnFight
|
| | | #{
|
| | | # tagHead Head;
|
| | | # DWORD MapID; // 自定义地图ID,可用于绑定战斗场景功能(如野外关卡,爬塔功能,竞技场等)
|
| | | # WORD FuncLineID;
|
| | | # BYTE TagType; // 战斗目标类型,0-NPC,1-玩家,2-队伍
|
| | | # DWORD TagID; // 战斗目标类型对应的ID
|
| | | # DWORD MapID; // 自定义地图ID,可用于绑定战斗地图场景功能(如主线boss、爬塔、竞技场等)
|
| | | # DWORD FuncLineID; // MapID对应的扩展值,如具体某个关卡等
|
| | | # BYTE TagType; // 目标类型,0-NPC阵容,1-玩家
|
| | | # DWORD TagID; // 目标类型对应的ID,如玩家ID
|
| | | # BYTE ValueCount;
|
| | | # DWORD ValueList[ValueCount]; // 附加值列表,可选,具体含义由MapID决定
|
| | | #};
|
| | | def OnTurnFight(index, clientData, tick):
|
| | | ''' 本战斗会一次性处理完所有小队战斗,以战报的形式下发,目前除了主线小怪分段战斗外,均使用该战斗
|
| | | '''
|
| | | curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
| | | mapID = clientData.MapID
|
| | | funcLineID = clientData.FuncLineID
|
| | |
| | | tagID = clientData.TagID
|
| | | valueList = clientData.ValueList
|
| | |
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | if tagType == ChConfig.TurnBattle_TagType_Player:
|
| | | if tagID == playerID:
|
| | | GameWorld.DebugLog("不能打自己!", playerID)
|
| | | return
|
| | | |
| | | GameWorld.DebugLog("回合制战斗请求: mapID=%s,funcLineID=%s,tagType=%s,tagID=%s,valueList=%s" |
| | | % (mapID, funcLineID, tagType, tagID, valueList), curPlayer.GetPlayerID())
|
| | | |
| | | reqRet = FBLogic.OnTurnFightRequest(curPlayer, mapID, funcLineID, tagType, tagID, valueList)
|
| | | if not reqRet:
|
| | | return
|
| | |
|
| | | # 需要发送到GameServer验证
|
| | | if mapID in ChConfig.Def_TFMapID_SendToGameServer:
|
| | | SendToGameServer_TurnFight(curPlayer, "TurnFightRequest", [mapID, funcLineID, tagType, tagID, valueList])
|
| | | # 攻防方所使用的阵容ID
|
| | | atkLineupID, defLineupID = FBLogic.GetFBPlayerLineupID(curPlayer, mapID, funcLineID)
|
| | | if atkLineupID not in ShareDefine.LineupList or defLineupID not in ShareDefine.LineupList:
|
| | | return
|
| | |
|
| | | DoTurnFightProcess(curPlayer, mapID, funcLineID, tagType, tagID, valueList, tick)
|
| | | return
|
| | |
|
| | | def SendToGameServer_TurnFight(curPlayer, msgType, dataMsg=""):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | msgList = str([msgType, dataMsg])
|
| | | GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "TurnFight", msgList, len(msgList))
|
| | | GameWorld.Log("回合战斗发送GameServer: %s, %s" % (msgType, dataMsg), playerID)
|
| | | return
|
| | |
|
| | | def GameServer_TurnFight_DoResult(curPlayer, msgData, tick):
|
| | | |
| | | msgType, dataMsg, ret = msgData
|
| | | |
| | | if not ret:
|
| | | return
|
| | | |
| | | if msgType == "TurnFightRequest":
|
| | | mapID, funcLineID, tagType, tagID, valueList = dataMsg
|
| | | DoTurnFightProcess(curPlayer, mapID, funcLineID, tagType, tagID, valueList, tick)
|
| | | # 玩家
|
| | | if tagType == 1:
|
| | | OnTurnFightVSPlayer(curPlayer, mapID, funcLineID, atkLineupID, defLineupID, tagID)
|
| | |
|
| | | elif msgType == "TurnFightOver":
|
| | | mapID, funcLineID, tagType, tagID, valueList, fightRet, awardItemList = dataMsg
|
| | | FBLogic.OnTurnFightOver_GameServerRet(curPlayer, mapID, funcLineID, tagType, tagID, valueList, fightRet, awardItemList, ret)
|
| | | |
| | | elif msgType == "TurnFightTagPlayerInfo":
|
| | | mapID, funcLineID, tagType, tagID, valueList = dataMsg
|
| | | DoTrunFightVSPlayer(curPlayer, tagID, [mapID, funcLineID, valueList], ret)
|
| | | |
| | | return
|
| | |
|
| | | def DoTurnFightProcess(curPlayer, mapID, funcLineID, tagType, tagID, valueList, tick):
|
| | | ## 执行回合制战斗的完整流程
|
| | | |
| | | #if curPlayer.GetSightLevel() != curPlayer.GetID():
|
| | | # PlayerControl.SetPlayerSightLevel(curPlayer, curPlayer.GetID())
|
| | | |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Start)
|
| | | |
| | | tagPlayerInfo = {}
|
| | | if tagType == ChConfig.TurnBattle_TagType_Player and tagID >= 10000 :
|
| | | tagPlayer = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(tagID)
|
| | | if tagPlayer:
|
| | | tagPlayerInfo = __GetPlayerInfo(tagPlayer)
|
| | | else:
|
| | | SendToGameServer_TurnFight(curPlayer, "TurnFightTagPlayerInfo", [mapID, funcLineID, tagType, tagID, valueList])
|
| | | # NPC
|
| | | else:
|
| | | ret = FBLogic.GetFBNPCLineupInfo(curPlayer, mapID, funcLineID)
|
| | | if not ret:
|
| | | return
|
| | | npcLineupIDList, strongerLV, difficulty = ret
|
| | | OnTurnFightVSNPC(curPlayer, mapID, funcLineID, atkLineupID, npcLineupIDList, strongerLV, difficulty)
|
| | |
|
| | | DoTrunFight(curPlayer, mapID, funcLineID, tagType, tagID, valueList, tick, tagPlayerInfo)
|
| | | |
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Over)
|
| | | return
|
| | |
|
| | | def __GetPlayerInfo(curPlayer):
|
| | | infoDict = {
|
| | | "Name":curPlayer.GetPlayerName(),
|
| | | "Job":curPlayer.GetJob(),
|
| | | "LV":curPlayer.GetLV(),
|
| | | "RealmLV":curPlayer.GetOfficialRank(),
|
| | | "MaxHP":GameObj.GetMaxHP(curPlayer),
|
| | | "FightPower":PlayerControl.GetFightPower(curPlayer),
|
| | | }
|
| | | return infoDict
|
| | |
|
| | | def DoTrunFightVSPlayer(curPlayer, tagPlayerID, callData, tagPlayerInfo):
|
| | | tagType = ChConfig.TurnBattle_TagType_Player
|
| | | tagID = tagPlayerID
|
| | | mapID, funcLineID, valueList = callData
|
| | | if tagPlayerInfo and curPlayer.GetPlayerID() != tagPlayerID:
|
| | | tick = GameWorld.GetGameWorld().GetTick()
|
| | | DoTrunFight(curPlayer, mapID, funcLineID, tagType, tagID, valueList, tick, tagPlayerInfo)
|
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Over)
|
| | | return
|
| | |
|
| | | def DoTrunFight(curPlayer, mapID, funcLineID, tagType, tagID, valueList, tick, tagInfo=None):
|
| | | if not tagID:
|
| | | return
|
| | | if not tagInfo:
|
| | | tagInfo = {}
|
| | | def OnTurnFightVSNPC(curPlayer, mapID, funcLineID, atkLineupID, npcLineupIDList, strongerLV, difficulty):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | GameWorld.DebugLog("回合战斗: mapID=%s,funcLineID=%s,tagType=%s,tagID=%s,valueList=%s,tagInfo=%s" |
| | | % (mapID, funcLineID, tagType, tagID, valueList, tagInfo), playerID)
|
| | | GameWorld.DebugLog("OnTurnFightVSNPC: mapID=%s,funcLineID=%s,atkLineupID=%s,npcLineupIDList=%s,strongerLV=%s,difficulty=%s" |
| | | % (mapID, funcLineID, atkLineupID, npcLineupIDList, strongerLV, difficulty), playerID)
|
| | | if not npcLineupIDList:
|
| | | return
|
| | |
|
| | | factionSyncInfoA = __GetPlayerInfo(curPlayer)
|
| | | factionSyncInfoB = tagInfo
|
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_PrepareOK, msg=[factionSyncInfoA, factionSyncInfoB])
|
| | | lineupMainInfo = GetPlayerLineupInfo(curPlayer, atkLineupID)
|
| | | if not lineupMainInfo:
|
| | | GameWorld.DebugLog("玩家没有该阵容数据! atkLineupID=%s" % atkLineupID, playerID)
|
| | | return
|
| | |
|
| | | turnNum, turnMax = 1, 15
|
| | | turnMax = GetTurnMax(mapID)
|
| | | if mapID == ChConfig.Def_FBMapID_MainBoss:
|
| | | # 停止主线小怪战斗、清空
|
| | | mainFightMgr = GetMainFightMgr(curPlayer)
|
| | | mainTF = mainFightMgr.turnFight
|
| | | if mainTF.isInFight():
|
| | | mainTF.exitFight()
|
| | | |
| | | tfMgr = GetTurnFightMgr()
|
| | | turnFight = tfMgr.addTurnFight(mapID, funcLineID, playerID)
|
| | | guid = turnFight.guid
|
| | |
|
| | | curFightPower = PlayerControl.GetFightPower(curPlayer)
|
| | | tagFightPower = tagInfo.get("FightPower", 0)
|
| | | isWin = 1 if curFightPower >= tagFightPower else 0
|
| | | GameWorld.DebugLog(" 战斗结果: isWin=%s,curFightPower=%s,tagFightPower=%s" % (isWin, curFightPower, tagFightPower), playerID)
|
| | | turnFight.setTurnFight(mapID, funcLineID, turnMax, True)
|
| | | turnFight.setPVE(npcLineupIDList, strongerLV, difficulty)
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo})
|
| | |
|
| | | factionTotalHurtDict = {}
|
| | | |
| | | playbackID = 0 # 战斗回放ID,可根据该ID查看回放
|
| | | |
| | | # 战斗结束后处理
|
| | | fightRet = [isWin, turnNum, turnMax, factionTotalHurtDict, playbackID]
|
| | | |
| | | needSendGameServer, awardItemList, overInfoEx = False, [], {}
|
| | | overRet = FBLogic.OnTurnFightOver(curPlayer, mapID, funcLineID, tagType, tagID, valueList, fightRet)
|
| | | if overRet != None:
|
| | | needSendGameServer, awardItemList, overInfoEx = overRet
|
| | | for index, lineupID in enumerate(npcLineupIDList):
|
| | | turnFight.lineupIndex = index
|
| | | GameWorld.DebugLog("对战NPC阵容: index=%s, lineupID=%s" % (index, lineupID))
|
| | | if index > 0:
|
| | | turnFight.nextTurnFight(resetByNextTeam=True)
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
|
| | | turnFight.sortActionQueue()
|
| | | turnFight.startFight()
|
| | |
|
| | | if needSendGameServer or mapID in ChConfig.Def_TFMapID_SendToGameServer:
|
| | | SendToGameServer_TurnFight(curPlayer, "TurnFightOver", [mapID, funcLineID, tagType, tagID, valueList, fightRet, awardItemList])
|
| | | __processTurnFight(turnFight.guid)
|
| | |
|
| | | overMsg = {"isWin":isWin, FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList), "totalHurt":0}
|
| | | playbackID and overMsg.update({"playbackID":playbackID})
|
| | | overInfoEx and overMsg.update(overInfoEx)
|
| | | SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, FightState_Award, turnNum, turnMax, overMsg)
|
| | | if not turnFight.isWin:
|
| | | break
|
| | | |
| | | PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
|
| | | SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
|
| | | tfMgr.delTurnFight(guid)
|
| | | return
|
| | |
|
| | | def SyncTurnFightState(curPlayer, mapID, funcLineID, tagType, tagID, state, turnNum=0, turnMax=0, msg=""):
|
| | | if not curPlayer:
|
| | | def OnTurnFightVSPlayer(curPlayer, mapID, funcLineID, atkLineupID, defLineupID, tagPlayerID):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | GameWorld.DebugLog("OnTurnFightVSPlayer: mapID=%s,funcLineID=%s,atkLineupID=%s,defLineupID=%s,tagPlayerID=%s" |
| | | % (mapID, funcLineID, atkLineupID, defLineupID, tagPlayerID), playerID)
|
| | | atkLineupInfo = GetPlayerLineupInfo(curPlayer, atkLineupID)
|
| | | if not atkLineupInfo:
|
| | | GameWorld.DebugLog("玩家没有该阵容数据! atkLineupID=%s" % atkLineupID, playerID)
|
| | | return
|
| | | clientPack = ChPyNetSendPack.tagMCTurnFightState()
|
| | | clientPack.Clear()
|
| | | clientPack.MapID = mapID
|
| | | clientPack.FuncLineID = funcLineID
|
| | | clientPack.TagType = tagType
|
| | | clientPack.TagID = tagID
|
| | | clientPack.State = state
|
| | | clientPack.TurnNum = turnNum
|
| | | clientPack.TurnMax = turnMax
|
| | | clientPack.Msg = str(msg)
|
| | | clientPack.Len = len(clientPack.Msg) |
| | | |
| | | tagViewCache = PlayerViewCache.FindViewCache(tagPlayerID)
|
| | | if not tagViewCache:
|
| | | GameWorld.DebugLog("目标玩家没有缓存数据! tagPlayerID=%s" % tagPlayerID, playerID)
|
| | | return {}
|
| | | defLineupInfo = GetCacheLineupInfo(tagViewCache, defLineupID)
|
| | | if not defLineupInfo:
|
| | | GameWorld.DebugLog("目标玩家没有该阵容数据! tagPlayerID=%s,defLineupID=%s" % (tagPlayerID, defLineupID), playerID)
|
| | | return
|
| | | |
| | | turnMax = GetTurnMax(mapID)
|
| | | |
| | | tfMgr = GetTurnFightMgr()
|
| | | turnFight = tfMgr.addTurnFight(mapID, funcLineID, playerID)
|
| | | guid = turnFight.guid
|
| | | |
| | | turnFight.setTurnFight(mapID, funcLineID, turnMax, True)
|
| | | turnFight.setPVP(tagPlayerID, tagViewCache)
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:atkLineupInfo})
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:defLineupInfo})
|
| | | turnFight.sortActionQueue()
|
| | | turnFight.startFight()
|
| | | |
| | | __processTurnFight(turnFight.guid)
|
| | | |
| | | PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
|
| | | SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
|
| | | tfMgr.delTurnFight(guid)
|
| | | return
|
| | |
|
| | | def GetTurnMax(mapID):
|
| | | if mapID == ChConfig.Def_FBMapID_Main:
|
| | | return IpyGameDataPY.GetFuncCfg("TurnMax", 1)
|
| | | mapTurnMaxDict= IpyGameDataPY.GetFuncEvalCfg("TurnMax", 3, {})
|
| | | return mapTurnMaxDict.get(mapID, IpyGameDataPY.GetFuncCfg("TurnMax", 2))
|
| | |
|
| | | #// B4 13 主线战斗请求 #tagCSMainFightReq
|
| | | #
|
| | | #struct tagCSMainFightReq
|
| | | #{
|
| | | # tagHead Head;
|
| | | # BYTE ReqType; // 0-停止战斗回城;1-设置消耗倍值;2-挑战关卡小怪;4-继续战斗;
|
| | | # DWORD ReqValue; // 请求值,ReqType为1时发送消耗倍值
|
| | | #};
|
| | | def OnMainFightReq(index, clientData, tick):
|
| | | curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
| | | reqType = clientData.ReqType
|
| | | reqValue = clientData.ReqValue
|
| | | |
| | | if reqType == 0:
|
| | | __doExitMainFight(curPlayer)
|
| | | return
|
| | | elif reqType == 1:
|
| | | __doSetFightPoint(curPlayer, reqValue)
|
| | | return
|
| | | |
| | | GameWorld.DebugLog("主线战斗请求: reqType=%s" % reqType, curPlayer.GetPlayerID())
|
| | | clientPack = ChPyNetSendPack.tagSCTurnFightReportSign()
|
| | | clientPack.Sign = 0
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack) # 标记开始
|
| | | |
| | | if reqType == 2: # 前端主动请求开始关卡小怪的视为从休息中开始
|
| | | __doMainLevelWave(curPlayer, True)
|
| | | elif reqType == 4:
|
| | | __doMainFight(curPlayer, tick)
|
| | | else:
|
| | | pass
|
| | | |
| | | # 标记结束
|
| | | clientPack.Sign = 1
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|
| | |
|
| | | def __doExitMainFight(curPlayer):
|
| | | ## 主线退出战斗 - 回城休息
|
| | | mainFightMgr = GetMainFightMgr(curPlayer)
|
| | | turnFight = mainFightMgr.turnFight
|
| | | if turnFight:
|
| | | turnFight.exitFight(True)
|
| | | return
|
| | |
|
| | | def __doSetFightPoint(curPlayer, fightPoint):
|
| | | ## 设置消耗倍值
|
| | | GameWorld.DebugLog("设置战锤消耗倍值: %s" % fightPoint)
|
| | | if fightPoint == 1:
|
| | | pass
|
| | | elif fightPoint == 2:
|
| | | # 条件验证
|
| | | pass
|
| | | elif fightPoint == 3:
|
| | | # 条件验证
|
| | | pass
|
| | | else:
|
| | | return
|
| | | curPlayer.SetFightPoint(fightPoint)
|
| | | return
|
| | |
|
| | | def __doMainLevelWave(curPlayer, isRestStart=False):
|
| | | ## 开始新的关卡波
|
| | | # @param isRestStart: 是否从休息状态重新开始的
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | chapterID, levelNum, wave = PlayerControl.GetMainLevelNowInfo(curPlayer)
|
| | | GameWorld.DebugLog("请求关卡波战斗: chapterID=%s,levelNum=%s,wave=%s,isRestStart=%s" % (chapterID, levelNum, wave, isRestStart), playerID)
|
| | | fightPoint = max(curPlayer.GetFightPoint(), 1)
|
| | | if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint):
|
| | | GameWorld.DebugLog("战锤不足,无法开始!")
|
| | | return
|
| | | chapterIpyData = IpyGameDataPY.GetIpyGameData("MainChapter", chapterID)
|
| | | if not chapterIpyData:
|
| | | return
|
| | | levelIpyData = IpyGameDataPY.GetIpyGameData("MainLevel", chapterID, levelNum)
|
| | | if not levelIpyData:
|
| | | # 如上线后减少某个章节关卡数的情况,导致找不到,则从该章节回退到存在的关卡开始
|
| | | while levelNum > 1:
|
| | | levelNum -= 1 |
| | | levelIpyData = IpyGameDataPY.GetIpyGameDataNotLog("MainLevel", chapterID, levelNum)
|
| | | if levelIpyData:
|
| | | break
|
| | | if not levelIpyData:
|
| | | return
|
| | | |
| | | # 本关卡最大波数,暂时支持最大6波
|
| | | waveMax = 6
|
| | | while waveMax >= 1 and (not hasattr(levelIpyData, "GetWaveLineupIDList%s" % waveMax) or not getattr(levelIpyData, "GetWaveLineupIDList%s" % waveMax)()):
|
| | | waveMax -= 1
|
| | | if waveMax < 1:
|
| | | return
|
| | | if wave > waveMax:
|
| | | wave = waveMax
|
| | | |
| | | lineupIDList = getattr(levelIpyData, "GetWaveLineupIDList%s" % wave)() # 小队1阵容ID|小队2阵容ID|...
|
| | | if not lineupIDList:
|
| | | return
|
| | | lineupID = lineupIDList[0] # NPC阵容ID
|
| | | |
| | | lineupMainInfo = GetPlayerLineupInfo(curPlayer, ShareDefine.Lineup_Main)
|
| | | if not lineupMainInfo:
|
| | | GameWorld.DebugLog("没有设置主阵容!", playerID)
|
| | | return
|
| | | |
| | | strongerLV = levelIpyData.GetNPCLV()
|
| | | difficulty = levelIpyData.GetDifficulty()
|
| | | mainFightMgr = GetMainFightMgr(curPlayer)
|
| | | mainFightMgr.chapterID = chapterID
|
| | | mainFightMgr.levelNum = levelNum
|
| | | mainFightMgr.waveMax = waveMax
|
| | | mainFightMgr.wave = wave
|
| | | mapID, funcLineID = ChConfig.Def_FBMapID_Main, PlayerControl.ComMainLevelValue(chapterID, levelNum, wave)
|
| | | turnMax = GetTurnMax(mapID)
|
| | | GameWorld.DebugLog("设置起始关卡波: 关卡%s-%s,波=%s/%s,lineupIDList=%s,mapID=%s,funcLineID=%s,lineupID=%s,strongerLV=%s,difficulty=%s" |
| | | % (chapterID, levelNum, wave, waveMax, lineupIDList, mapID, funcLineID, lineupID, strongerLV, difficulty), playerID)
|
| | | |
| | | turnFight = mainFightMgr.turnFight
|
| | | turnFight.setTurnFight(mapID, funcLineID, turnMax, False)
|
| | | turnFight.setPVE(lineupIDList, strongerLV, difficulty)
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo})
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
|
| | | turnFight.sortActionQueue()
|
| | | turnFight.startFight()
|
| | | |
| | | __doMainFight(curPlayer)
|
| | | return
|
| | |
|
| | | def __doMainFight(curPlayer, tick=0):
|
| | | '''执行主线战斗,单场战斗断电式战斗,以前端玩家手动点击节点做为断点处
|
| | | 每场战斗的初始化、结束默认断点,由前端决定自动继续或者点击继续
|
| | | '''
|
| | | |
| | | # 限制请求CD
|
| | | if tick:
|
| | | key = "MainFightReqTick"
|
| | | lastTick = curPlayer.GetDictByKey(key)
|
| | | if lastTick and tick - lastTick <= 1000:
|
| | | GameWorld.DebugLog("主线战斗请求CD中")
|
| | | return
|
| | | curPlayer.SetDict(key, tick)
|
| | | |
| | | mainFightMgr = GetMainFightMgr(curPlayer)
|
| | | turnFight = mainFightMgr.turnFight
|
| | | |
| | | isLevelBoss = mainFightMgr.isLevelBoss()
|
| | | if isLevelBoss:
|
| | | ## 关卡boss是一次性处理完的,一般不可能走到这里,这边做下防范
|
| | | return
|
| | | |
| | | if not turnFight.isInFight():
|
| | | __doMainLevelWave(curPlayer, True)
|
| | | return
|
| | | |
| | | winFaction = turnFight.winFaction
|
| | | if winFaction:
|
| | | nextLineupID = turnFight.nextLineupID()
|
| | | if nextLineupID:
|
| | | GameWorld.DebugLog("---开始进入下一小队: lineupIndex=%s,nextLineupID=%s,%s" % (turnFight.lineupIndex, nextLineupID, turnFight.lineupIDList))
|
| | | |
| | | turnFight.nextTurnFight(resetByNextTeam=True)
|
| | | # 切换小队时,玩家阵容不需要处理,保留状态
|
| | | turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(nextLineupID, turnFight.strongerLV, turnFight.difficulty)})
|
| | | turnFight.sortActionQueue()
|
| | | turnFight.startFight()
|
| | | |
| | | __doMainFight(curPlayer)
|
| | | else:
|
| | | __doMainLevelWave(curPlayer, False)
|
| | | return
|
| | | |
| | | # 小怪战斗,每次消耗1个战锤
|
| | | fightPoint = max(curPlayer.GetFightPoint(), 1) # 主线战斗消耗倍值,默认1
|
| | | if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint):
|
| | | GameWorld.DebugLog("回合开始时战锤不足!")
|
| | | return
|
| | | |
| | | # 以下均是处理关卡小怪分段实时战斗
|
| | | isEntry = EntryLogic(turnFight)
|
| | | |
| | | # 是否开始检查断点,预判可断的点,方便前端点击体验,点下去就是玩家放的某个行动
|
| | | # 初始开始进场后,默认开始断点
|
| | | checkBreakpoint = True if isEntry else False
|
| | | |
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | turnNum = turnFight.turnNum
|
| | | turnMax = turnFight.turnMax
|
| | | for turnNum in range(turnNum, turnMax + 1):
|
| | | turnTimeline = turnFight.getTurnNumStartTimelin(turnNum) # 本回合起始时间节点
|
| | | curTimeline = turnFight.getTimeline()
|
| | | |
| | | # 回合开始
|
| | | turnTimeline += 1 # 每回合开始算一个时间节点
|
| | | if curTimeline < turnTimeline:
|
| | | curTimeline = turnFight.setTimeline(turnTimeline)
|
| | | GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】 curTimeline=%s" % (turnNum, curTimeline))
|
| | | turnFight.turnNum = turnNum
|
| | | if curPlayer:
|
| | | turnFight.syncState(FightState_Fighting)
|
| | | |
| | | for faction, num in turnFight.actionSortList:
|
| | | GameWorld.DebugLog("回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | batLineup.actionNum = 1
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightPerTurnBigStart(turnFight, batObj, turnNum)
|
| | | |
| | | # 红颜
|
| | | # 灵兽
|
| | | |
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | | |
| | | # 武将
|
| | | doMax = PosNumMax * len(turnFight.actionSortList)
|
| | | doCnt = 0
|
| | | while doCnt < doMax and turnFight.actionIndex < len(turnFight.actionSortList):
|
| | | doCnt += 1
|
| | | faction, num = turnFight.actionSortList[turnFight.actionIndex]
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | for posNum in range(batLineup.actionNum, PosNumMax + 1):
|
| | | # 每个武将位算一个时间节点
|
| | | #GameWorld.DebugLog("武将节点: faction=%s,posNum=%s,curTimeline=%s" % (faction, posNum, curTimeline))
|
| | | if posNum not in batLineup.posObjIDDict:
|
| | | batLineup.actionNum = posNum + 1
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1, True)
|
| | | #GameWorld.DebugLog("空位节点: faction=%s,posNum=%s,curTimeline=%s" % (faction, posNum, curTimeline))
|
| | | continue
|
| | | |
| | | objID = batLineup.posObjIDDict[posNum]
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | |
| | | # 玩家自己阵营,预判可否行动
|
| | | if checkBreakpoint and faction == ChConfig.Def_FactionA and batObj:
|
| | | if batObj.CanAction():
|
| | | GameWorld.DebugLog("玩家阵容下一个可行动的武将,断点: curTimeline=%s,nextPosNum=%s" % (curTimeline, posNum))
|
| | | return
|
| | | |
| | | batLineup.actionNum = posNum + 1
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1)
|
| | | TurnFightHeroTurnStart(turnFight, batObj, turnNum)
|
| | | if not OnObjAction(turnFight, batObj):
|
| | | continue
|
| | | |
| | | if not checkBreakpoint and faction == ChConfig.Def_FactionA:
|
| | | checkBreakpoint = True
|
| | | |
| | | break
|
| | | |
| | | if turnFight.actionIndex >= len(turnFight.actionSortList) - 1:
|
| | | turnFight.actionIndex = 0
|
| | | else:
|
| | | turnFight.actionIndex += 1
|
| | | |
| | | # 回合结束
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1) # 每回合结束算一个时间节点
|
| | | for faction, num in turnFight.actionSortList:
|
| | | GameWorld.DebugLog("回合结束逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightPerTurnBigEnd(turnFight, batObj, turnNum)
|
| | | |
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | | |
| | | if not turnFight.winFaction:
|
| | | OnTurnAllOver(turnFight.guid)
|
| | | |
| | | return
|
| | |
|
| | | def __processTurnFight(guid):
|
| | | ## 一次性处理完一个小队的战斗
|
| | | turnFight = GetTurnFightMgr().getTurnFight(guid)
|
| | | 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)
|
| | | curTimeline = turnFight.getTurnNumStartTimelin(turnNum) # 本回合起始时间节点
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1)
|
| | | if curPlayer:
|
| | | turnFight.syncState(FightState_Fighting)
|
| | | |
| | | # 回合开始
|
| | | for faction, num in turnFight.actionSortList:
|
| | | GameWorld.DebugLog("回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | batLineup.actionNum = 1
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightPerTurnBigStart(turnFight, batObj, turnNum)
|
| | | |
| | | |
| | | # 红颜
|
| | | # 灵兽
|
| | | |
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | | |
| | | # 武将
|
| | | doMax = PosNumMax * len(turnFight.actionSortList)
|
| | | doCnt = 0
|
| | | while doCnt < doMax and turnFight.actionIndex < len(turnFight.actionSortList):
|
| | | doCnt += 1
|
| | | faction, num = turnFight.actionSortList[turnFight.actionIndex]
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | for posNum in range(batLineup.actionNum, PosNumMax + 1):
|
| | | batLineup.actionNum = posNum + 1
|
| | | if posNum not in batLineup.posObjIDDict:
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1, True)
|
| | | continue
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1) # 每个武将位算一个时间节点
|
| | | objID = batLineup.posObjIDDict[posNum]
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightHeroTurnStart(turnFight, batObj, turnNum)
|
| | | if not OnObjAction(turnFight, batObj):
|
| | | continue
|
| | | |
| | | break
|
| | | |
| | | if turnFight.actionIndex >= len(turnFight.actionSortList) - 1:
|
| | | turnFight.actionIndex = 0
|
| | | else:
|
| | | turnFight.actionIndex += 1
|
| | | |
| | | # 回合结束
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1) # 每回合结束算一个时间节点
|
| | | for faction, num in turnFight.actionSortList:
|
| | | GameWorld.DebugLog("回合结束逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightPerTurnBigEnd(turnFight, batObj, turnNum)
|
| | | |
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | | |
| | | if not turnFight.winFaction:
|
| | | OnTurnAllOver(turnFight.guid)
|
| | | return
|
| | |
|
| | | def GetObjName(batObj):
|
| | | faction = batObj.faction
|
| | | num = batObj.lineupNum
|
| | | posNum = batObj.posNum
|
| | | heroID = batObj.heroID
|
| | | npcID = batObj.npcID
|
| | | objName = GameWorld.CodeToGbk(batObj.GetName())
|
| | | 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):
|
| | | ## 执行进场逻辑
|
| | | if turnFight.enterLogic:
|
| | | return
|
| | | GameWorld.DebugLog("执行进场逻辑...")
|
| | | |
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | for faction, num in turnFight.actionSortList:
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | batLineup.actionNum = ActionNumStart
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_FightStart)
|
| | | |
| | | turnFight.enterLogic = True
|
| | | return True
|
| | |
|
| | | def OnTimelineChange(turnFight):
|
| | | ## 每个时间节点变化时处理
|
| | | |
| | | nowTimeline = turnFight.getTimeline()
|
| | | |
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | for batFaction in turnFight.factionDict.values():
|
| | | for batLineup in batFaction.lineupDict.values():
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | #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()):
|
| | | curSkill = skillManager.GetSkillByIndex(index)
|
| | | if not curSkill:
|
| | | continue
|
| | | remainTime = curSkill.GetRemainTime()
|
| | | if not remainTime:
|
| | | continue
|
| | | calcTimeline = curSkill.GetCalcTime()
|
| | | passTurn = __calcPassturn(calcTimeline, nowTimeline, True)
|
| | | if passTurn <= 0:
|
| | | continue
|
| | | skillID = curSkill.GetSkillID()
|
| | | updRemainTime = max(0, remainTime - passTurn)
|
| | | curSkill.SetRemainTime(updRemainTime)
|
| | | curSkill.SetCalcTime(nowTimeline)
|
| | | GameWorld.DebugLog("更新技能剩余回合数: curID=%s,skillID=%s,updRemainTime=%s,calcTimeline=%s,passTurn=%s" |
| | | % (curID, skillID, updRemainTime, calcTimeline, passTurn))
|
| | | |
| | | 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)
|
| | | GameWorld.DebugLog("更新buff剩余回合数: curID=%s,buffID=%s,skillID=%s,updRemainTime=%s,calcTimeline=%s,passTurn=%s" |
| | | % (curID, buffID, skillID, updRemainTime, calcTimeline, passTurn))
|
| | | if updRemainTime > 0:
|
| | | buff.SetRemainTime(updRemainTime)
|
| | | buff.SetCalcTime(nowTimeline)
|
| | | TurnBuff.SyncBuffRefresh(turnFight, batObj, buff)
|
| | | else:
|
| | | TurnBuff.DoBuffDel(turnFight, batObj, buff)
|
| | | |
| | | return
|
| | |
|
| | | def __calcPassturn(calcTimeline, nowTimeline, equalOK):
|
| | | ## 计算已经过了的回合数
|
| | | # @param equalOK: 时间节点相同时是否算1回合,一般技能可以算,buff不算
|
| | | calcTurnNum = calcTimeline / TimelineSet
|
| | | calcTimeNode = calcTimeline % TimelineSet
|
| | | nowTurnNum = nowTimeline / TimelineSet
|
| | | nowTimeNode = nowTimeline % TimelineSet
|
| | | if equalOK:
|
| | | if nowTimeNode >= calcTimeNode:
|
| | | return max(0, nowTurnNum - calcTurnNum)
|
| | | return max(0, nowTurnNum - calcTurnNum - 1)
|
| | | else:
|
| | | if nowTimeNode > calcTimeNode:
|
| | | return max(0, nowTurnNum - calcTurnNum)
|
| | | return max(0, nowTurnNum - calcTurnNum - 1)
|
| | | return 0
|
| | |
|
| | | def TurnFightPerTurnBigStart(turnFight, batObj, turnNum):
|
| | | ## 大回合开始时
|
| | | if not batObj:
|
| | | return
|
| | | |
| | | if batObj.GetHP() <= 0:
|
| | | return
|
| | | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
|
| | | return
|
| | |
|
| | | def TurnFightPerTurnBigEnd(turnFight, batObj, turnNum):
|
| | | ## 大回合结束时
|
| | | if not batObj:
|
| | | return
|
| | | |
| | | if batObj.GetHP() <= 0:
|
| | | return
|
| | | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnEnd)
|
| | | return
|
| | |
|
| | | def TurnFightHeroTurnStart(turnFight, batObj, turnNum):
|
| | | ## 武将回合开始时,不能行动也要触发
|
| | | if not batObj:
|
| | | return
|
| | | |
| | | if batObj.GetHP() <= 0:
|
| | | return
|
| | | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_HeroTurnStart)
|
| | | return
|
| | |
|
| | | def AddTurnObjCureHP(curObj, srcObj, addValue, cureHP, skillID=0):
|
| | | ## 回合对象添加治疗值
|
| | | # @param curObj: 获得治疗的对象
|
| | | # @param srcObj: 来自谁的治疗
|
| | | # @param addValue: 治疗值
|
| | | # @param cureHP: 实际回血量
|
| | | if not srcObj:
|
| | | return
|
| | | curID = curObj.GetID()
|
| | | srcID = srcObj.GetID()
|
| | | 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(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, isBounce=False):
|
| | | ## 回合对象添加伤害值
|
| | | # @param isBounce: 是否反弹伤害
|
| | | if hurtValue <= 0:
|
| | | return
|
| | | curID = curBatObj.GetID()
|
| | | tagID = tagBatObj.GetID()
|
| | | if curID != tagID:
|
| | | 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))
|
| | | |
| | | if tagBatObj:
|
| | | 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))
|
| | | |
| | | else:
|
| | | # 如换血类技能,自残的伤害不算输出
|
| | | GameWorld.DebugLog(" 自残: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,curHP=%s" |
| | | % (curID, tagID, skillID, hurtValue, lostHP, curBatObj.GetHP()))
|
| | | return
|
| | |
|
| | | def OnObjAction(turnFight, curBatObj):
|
| | | ## 战斗单位行动
|
| | | if not curBatObj:
|
| | | return
|
| | | |
| | | curHP = curBatObj.GetHP()
|
| | | objID = curBatObj.GetID()
|
| | | if curHP <= 0:
|
| | | return
|
| | | |
| | | turnNum = turnFight.turnNum
|
| | | objName = GetObjName(curBatObj)
|
| | | |
| | | # 是否可行动状态判断
|
| | | 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))
|
| | | turnFight.syncObjAction(turnNum, objID)
|
| | | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, curBatObj, ChConfig.TriggerWay_HeroActionStart)
|
| | | |
| | | 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() not in [ChConfig.Def_SkillFuncType_TurnNormaSkill, ChConfig.Def_SkillFuncType_AngerSkill]:
|
| | | #只能主动释放普攻或怒技
|
| | | continue
|
| | | #被动技能无法使用
|
| | | if SkillCommon.isPassiveSkill(useSkill):
|
| | | continue
|
| | | #还在冷却时间内无法释放
|
| | | if useSkill.GetRemainTime():
|
| | | continue
|
| | | skillID = useSkill.GetSkillID()
|
| | | # 常规攻击优先xp
|
| | | 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)
|
| | | 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):
|
| | | break
|
| | | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, curBatObj, ChConfig.TriggerWay_HeroActionEnd)
|
| | | return True
|
| | |
|
| | | def SetObjKilled(turnFight, gameObj, killer=None, useSkill=None):
|
| | | objID = gameObj.GetID()
|
| | | 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)
|
| | | |
| | | 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):
|
| | | ## 所有回合已经全部执行完毕
|
| | | GameWorld.DebugLog("所有回合结束")
|
| | | turnFight = GetTurnFightMgr().getTurnFight(guid)
|
| | | if not turnFight:
|
| | | return
|
| | | |
| | | if turnFight.winFaction:
|
| | | return
|
| | | |
| | | if turnFight.playerID:
|
| | | # 玩家发起的,未击杀对方,算玩家输
|
| | | turnFight.winFaction = ChConfig.Def_FactionB
|
| | | else:
|
| | | # 系统场次,按一定规则来,这里先随机
|
| | | turnFight.winFaction = random.choice([ChConfig.Def_FactionA, ChConfig.Def_FactionB])
|
| | | |
| | | DoTurnFightOver(guid)
|
| | | return
|
| | |
|
| | | def DoTurnFightOver(guid):
|
| | | ## 执行回合战斗结算逻辑
|
| | | tfMgr = GetTurnFightMgr()
|
| | | turnFight = tfMgr.getTurnFight(guid)
|
| | | if not turnFight:
|
| | | return
|
| | | |
| | | turnFight.costTime = time.time() - turnFight.startTime
|
| | | winFaction = turnFight.winFaction
|
| | | turnFight.isWin = (winFaction == ChConfig.Def_FactionA)
|
| | | GameWorld.DebugLog("--- 战斗结束处理 ---, winFaction=%s, costTime=%ss, %s" % (winFaction, turnFight.costTime, guid))
|
| | | |
| | | # 统计明细
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | statInfo = {}
|
| | | for faction in turnFight.factionDict.keys():
|
| | | if str(faction) not in statInfo:
|
| | | statInfo[str(faction)] = {}
|
| | | facStatInfo = statInfo[str(faction)]
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | for num in batFaction.lineupDict.keys():
|
| | | if str(num) not in facStatInfo:
|
| | | facStatInfo[str(num)] = {}
|
| | | lineupStatInfo = facStatInfo[str(num)]
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | GameWorld.DebugLog("阵容明细: faction=%s,num=%s" % (faction, num))
|
| | | 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,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}
|
| | | |
| | | overMsg = {"winFaction":winFaction, "statInfo":statInfo}
|
| | | curPlayer = turnFight.curPlayer
|
| | | mapID = turnFight.mapID
|
| | | funcLineID = turnFight.funcLineID
|
| | | |
| | | FBLogic.OnTurnFightOver(curPlayer, turnFight, mapID, funcLineID, overMsg)
|
| | | |
| | | turnFight.syncState(FightState_Award, overMsg)
|
| | | return
|
| | |
|
| | | #// B4 14 查看战报 #tagCSTurnFightReportView
|
| | | #
|
| | | #struct tagCSTurnFightReportView
|
| | | #{
|
| | | # tagHead Head;
|
| | | # char GUID[40]; //战报guid
|
| | | #};
|
| | | def OnTurnFightReportView(index, clientData, tick):
|
| | | curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
| | | guid = clientData.GUID
|
| | | |
| | | lastBatBufferInfo = PlayerOnline.GetOnlinePlayer(curPlayer).GetLastBatBuffer()
|
| | | if lastBatBufferInfo and len(lastBatBufferInfo) == 2 and guid == lastBatBufferInfo[0]:
|
| | | guid, reprot = lastBatBufferInfo
|
| | | SyncTurnFightReport(curPlayer, guid, reprot)
|
| | | return
|
| | | |
| | | # 其他战报,一般是入库存储的,待扩展
|
| | | |
| | | # 战报已过期
|
| | | PlayerControl.NotifyCode(curPlayer, "FightReportExpired")
|
| | | return
|
| | |
|
| | | def SyncTurnFightReport(curPlayer, guid, reprot):
|
| | | ## 通知完整战报
|
| | | clientPack = ChPyNetSendPack.tagSCTurnFightReport()
|
| | | clientPack.GUID = guid
|
| | | clientPack.Report = reprot
|
| | | clientPack.Len = len(clientPack.Report)
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|
| | | |