| | |
| | | self.turnNum = 1 # 当前第x回合,默认第1回合开始
|
| | | self.turnMax = 15 # 最大回合数
|
| | | self.enterLogic = False # 是否已执行进场逻辑
|
| | | self.turnStart = 0 # 已执行回合开始值,如第1回合开始已执行则为1,第2回合为2
|
| | | self.turnEnd = 0 # 已执行回合结束值,如第1回合结束已执行则为1,第2回合为2
|
| | | self.winFaction = 0 # 本场战斗结束标记,获胜阵营,为0时代表未结束,所有小队打完或失败才有结果,0-未结束,>0-获胜的阵营
|
| | | self.batBuffer = "" # 战报buffer,战报暂时只保留最后一个小队的
|
| | | self.isNeedReport = isNeedReport # 是否需要战报
|
| | |
| | |
|
| | | self.factionDict = {} # 战斗阵营 {faction:BatFaction, ...},一般是只有两个阵营,faction为1或2,每个阵营支持多个阵容
|
| | | self.actionSortList = [] # 阵容行动顺序 [[faction, num], ...]
|
| | | self.actionIndex = 0 # 行动顺序索引
|
| | | self.actionIndex = 0 # 行动顺序索引 |
| | | self.timeline = 0 # 时间轴节点 turnNum*1000+actionIndex*100++actionNum
|
| | | |
| | | self.startTime = 0 # 开始时间戳,支持毫秒小数
|
| | | self.costTime = 0 # 单场战斗总耗时,支持毫秒小数
|
| | | return
|
| | |
| | | ## 一般用于玩家发起的战斗,在需要保留玩家阵容属性及状态的情况下,重置回合进入下一场战斗
|
| | | self.turnNum = 1
|
| | | self.enterLogic = False
|
| | | self.turnStart = 0
|
| | | self.turnEnd = 0
|
| | | self.winFaction = 0
|
| | | self.batBuffer = "" # 战报buffer
|
| | | self.msgDict.update(msgDict)
|
| | | self.timeline = 0
|
| | | self.startTime = time.time()
|
| | | self.costTime = 0
|
| | | return
|
| | |
| | | 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, turnNum):
|
| | | def setTimeline(self, timeline, isEmpty=False):
|
| | | '''回合战斗的时间轴节点 ,即第几回合开始,每个回合支持9999个行动节点
|
| | | @param turnNum: 第x回合
|
| | | '''
|
| | | self.timeline = turnNum * TimelineSet + 0
|
| | | self.timeline = timeline
|
| | | GameWorld.DebugLog("时间节点更新: %s" % self.timeline)
|
| | | if isEmpty:
|
| | | # 空位置的节点可直接跳过
|
| | | return timeline
|
| | | |
| | | OnTimelineChange(self)
|
| | | return
|
| | | def addTimeline(self):
|
| | | ## 每切换一个行动单位可视为一个行动节点,即代表单回合战斗中的某一个时间节点
|
| | | self.timeline += 1
|
| | | GameWorld.DebugLog("时间节点更新: %s" % self.timeline)
|
| | | OnTimelineChange(self)
|
| | | return
|
| | | return timeline
|
| | |
|
| | | def getBatFaction(self, faction=ChConfig.Def_FactionA):
|
| | | ## 默认阵营1
|
| | |
| | | def startFight(self):
|
| | | ## 准备就绪,开始战斗
|
| | | self.state = FightState_Start
|
| | | self.setTimeline(1)
|
| | | self.turnNum = 1
|
| | | self.timeline = self.getTurnNumStartTimelin(self.turnNum)
|
| | | self.syncInit()
|
| | | return
|
| | |
|
| | |
| | | npcID = getattr(ipyData, "GetPosNPCID%s" % posNum)()
|
| | | if not npcID:
|
| | | continue
|
| | | battleDict = GetNPCBattleDict(npcID, strongerLV, difficulty)
|
| | | battleDict = GetNPCBattleDict(ipyData, npcID, strongerLV, difficulty)
|
| | | if not battleDict:
|
| | | continue
|
| | | heroDict[str(posNum)] = battleDict
|
| | |
| | | lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict}
|
| | | return lineupInfo
|
| | |
|
| | | def GetNPCBattleDict(npcID, strongerLV=0, difficulty=0):
|
| | | def GetNPCBattleDict(lineupIpyData, npcID, strongerLV=0, difficulty=0):
|
| | | ## 获取NPC战斗相关字典,支持成长NPC
|
| | | # @param strongerLV: 成长等级
|
| | | # @param difficulty: 难度系数
|
| | |
| | | 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:
|
| | |
| | | skillManager.LearnSkillByID(skillID)
|
| | |
|
| | | batLineup.posObjIDDict[posNum] = objID
|
| | | GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillIDList))
|
| | | GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillManager.GetSkillIDList()))
|
| | | batObj.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP)
|
| | |
|
| | | return
|
| | |
| | | __doSetFightPoint(curPlayer, reqValue)
|
| | | return
|
| | |
|
| | | GameWorld.DebugLog("主线战斗请求: reqType=%s" % reqType, curPlayer.GetPlayerID())
|
| | | clientPack = ChPyNetSendPack.tagSCTurnFightReportSign()
|
| | | clientPack.Sign = 0
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack) # 标记开始
|
| | |
| | | turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
|
| | | turnFight.sortActionQueue()
|
| | | turnFight.startFight()
|
| | | |
| | | __doMainFight(curPlayer)
|
| | | return
|
| | |
|
| | | def __doMainBossStart(curPlayer):
|
| | |
| | | __processTurnFight(turnFight.guid)
|
| | | return
|
| | |
|
| | | def __doMainFight(curPlayer, tick):
|
| | | ## 主线执行战斗
|
| | | def __doMainFight(curPlayer, tick=0):
|
| | | '''执行主线战斗,单场战斗断电式战斗,以前端玩家手动点击节点做为断点处
|
| | | 每场战斗的初始化、结束默认断点,由前端决定自动继续或者点击继续
|
| | | '''
|
| | |
|
| | | # 限制请求CD
|
| | | #if not GameWorld.GetGameWorld().GetDebugLevel():
|
| | | key = "MainFightReqTick"
|
| | | lastTick = curPlayer.GetDictByKey(key)
|
| | | if lastTick and tick - lastTick <= 1000:
|
| | | GameWorld.DebugLog("主线战斗请求CD中")
|
| | | return
|
| | | curPlayer.SetDict(key, tick)
|
| | | |
| | | 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
|
| | |
|
| | |
| | | # 每次处理一小队的完整战斗,相当于一次完整战报
|
| | | __processTurnFight(turnFight.guid)
|
| | | return
|
| | | else:
|
| | | __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
|
| | |
|
| | | # 以下均是处理关卡小怪分段实时战斗
|
| | | EntryLogic(turnFight)
|
| | | isEntry = EntryLogic(turnFight)
|
| | |
|
| | | # 按阵营阵容执行顺序,逐个遍历
|
| | | doCnt = 0
|
| | | doMax = (PosNumMax + 2) * len(turnFight.actionSortList) # 防止死循环,做最大循环次数限制 = (最大位置数 + 主公、红颜位置)*行动阵容数
|
| | | overLineupList = [] # 本回合已经结束行动的阵容列表 [(faction, num), ...], 所有阵容全部结束代表本回合结束
|
| | | # 是否开始检查断点,预判可断的点,方便前端点击体验,点下去就是玩家放的某个行动
|
| | | # 初始开始进场后,默认开始断点
|
| | | checkBreakpoint = True if isEntry else False
|
| | |
|
| | | 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):
|
| | | doCnt += 1
|
| | | turnNum = turnFight.turnNum
|
| | | # 执行回合开始逻辑
|
| | | if turnFight.turnStart < turnNum:
|
| | | GameWorld.DebugLog("执行行动: turnNum=%s, 回合开始" % (turnFight.turnNum))
|
| | | turnFight.syncState(FightState_Fighting)
|
| | | #if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint):
|
| | | # GameWorld.DebugLog("回合开始时战锤不足!")
|
| | | # return
|
| | | turnFight.turnStart = turnNum
|
| | | turnFight.actionIndex = 0
|
| | | turnFight.addTimeline() # 每回合开始算一个时间节点
|
| | | 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 = ActionNumStart
|
| | | batLineup.actionNum = 1
|
| | | for objID in batLineup.posObjIDDict.values():
|
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightPerTurnBigStart(turnFight, batObj, turnNum)
|
| | |
|
| | | if turnFight.actionIndex >= len(turnFight.actionSortList):
|
| | | turnFight.actionIndex = 0
|
| | | |
| | | playerHeroAtk = False # 玩家阵容行动标记
|
| | | faction, num = turnFight.actionSortList[turnFight.actionIndex]
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | if batLineup.actionNum > max(batLineup.posObjIDDict):
|
| | | if (faction, num) not in overLineupList:
|
| | | overLineupList.append((faction, num))
|
| | | |
| | | turnFight.actionIndex += 1
|
| | | continue
|
| | | |
| | | GameWorld.DebugLog("执行行动: turnNum=%s,faction=%s,num=%s,actionNum=%s" % (turnFight.turnNum, faction, num, batLineup.actionNum))
|
| | | |
| | | # 主公
|
| | | if batLineup.actionNum == -1:
|
| | | pass
|
| | | |
| | | # 红颜
|
| | | elif batLineup.actionNum == 0:
|
| | | pass
|
| | | # 灵兽
|
| | | |
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | |
|
| | | # 武将
|
| | | elif batLineup.actionNum > 0:
|
| | | 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):
|
| | | turnFight.addTimeline() # 每个武将位算一个时间节点
|
| | | batLineup.actionNum = posNum
|
| | | if posNum not in batLineup.posObjIDDict:
|
| | | turnTimeline += 1 # 每个武将位算一个时间节点
|
| | | if turnTimeline <= curTimeline:
|
| | | # 该时间节点已经处理过了
|
| | | GameWorld.DebugLog("该时间节点已经处理过了! turnTimeline=%s <= %s" % (turnTimeline, curTimeline))
|
| | | continue
|
| | | |
| | | if posNum not in batLineup.posObjIDDict:
|
| | | batLineup.actionNum = posNum + 1
|
| | | curTimeline = turnFight.setTimeline(turnTimeline, True)
|
| | | 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(turnTimeline)
|
| | | TurnFightHeroTurnStart(turnFight, batObj, turnNum)
|
| | | if not OnObjAction(turnFight, batObj):
|
| | | continue
|
| | |
|
| | | if faction == ChConfig.Def_FactionA:
|
| | | playerHeroAtk = True
|
| | | if not checkBreakpoint and faction == ChConfig.Def_FactionA:
|
| | | checkBreakpoint = True
|
| | |
|
| | | break
|
| | | |
| | | turnFight.actionIndex += 1
|
| | | batLineup.actionNum += 1
|
| | | 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))
|
| | | if turnFight.actionIndex >= len(turnFight.actionSortList) - 1:
|
| | | turnFight.actionIndex = 0
|
| | | else:
|
| | | turnFight.actionIndex += 1
|
| | |
|
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | | |
| | | if playerHeroAtk:
|
| | | # 玩家武将有行动则停止,一段段执行
|
| | | GameWorld.DebugLog("玩家武将有行动则停止!")
|
| | | break
|
| | | |
| | | if turnFight.winFaction:
|
| | | return
|
| | | |
| | | GameWorld.DebugLog("turnNum=%s,doCnt=%s,overLineupList=%s" % (turnNum, doCnt, overLineupList))
|
| | | if len(overLineupList) >= len(turnFight.actionSortList):
|
| | | GameWorld.DebugLog("执行行动: turnNum=%s, 回合结束" % (turnFight.turnNum))
|
| | | if turnFight.turnEnd < turnNum:
|
| | | #if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_Xiantao, fightPoint):
|
| | | # GameWorld.DebugLog("回合结束时战锤不足!")
|
| | | # return
|
| | | turnFight.turnEnd = turnNum
|
| | | turnFight.addTimeline() # 每回合结束算一个时间节点
|
| | | # 回合结束
|
| | | turnTimeline += 1 # 每回合结束算一个时间节点
|
| | | if curTimeline < turnTimeline:
|
| | | curTimeline = turnFight.setTimeline(turnTimeline)
|
| | | 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():
|
| | | return
|
| | | |
| | | if turnNum < turnFight.turnMax:
|
| | | turnFight.turnNum += 1
|
| | | turnFight.setTimeline(turnFight.turnNum) # 回合变更,直接设置新回合时间节点
|
| | | else:
|
| | | OnTurnAllOver(turnFight.guid)
|
| | | |
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | | |
| | | if not turnFight.winFaction:
|
| | | OnTurnAllOver(turnFight.guid)
|
| | | |
| | | return
|
| | |
|
| | | def __processTurnFight(guid):
|
| | |
| | | for turnNum in range(1, turnMax + 1):
|
| | | turnFight.turnNum = turnNum
|
| | | GameWorld.DebugLog("【----- 回合制战斗轮次: %s -----】" % turnNum)
|
| | | turnFight.setTimeline(turnNum)
|
| | | curTimeline = turnFight.getTurnNumStartTimelin(turnNum) # 本回合起始时间节点
|
| | | curTimeline = turnFight.setTimeline(curTimeline + 1)
|
| | | if curPlayer:
|
| | | turnFight.syncState(FightState_Fighting)
|
| | |
|
| | | # 回合开始
|
| | | turnFight.addTimeline() # 每回合开始算一个时间节点
|
| | | for faction, num in turnFight.actionSortList:
|
| | | GameWorld.DebugLog("回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
|
| | | batFaction = turnFight.getBatFaction(faction)
|
| | |
| | | batObj = batObjMgr.getBatObj(objID)
|
| | | TurnFightPerTurnBigStart(turnFight, batObj, turnNum)
|
| | |
|
| | | # 主公
|
| | | #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 faction, num in turnFight.actionSortList:
|
| | | # GameWorld.DebugLog("红颜逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num))
|
| | | # batFaction = turnFight.getBatFaction(faction)
|
| | | # batLineup = batFaction.getBatlineup(num)
|
| | | # 灵兽
|
| | |
|
| | | if turnFight.checkOverByKilled():
|
| | | break
|
| | |
| | | batFaction = turnFight.getBatFaction(faction)
|
| | | batLineup = batFaction.getBatlineup(num)
|
| | | for posNum in range(batLineup.actionNum, PosNumMax + 1):
|
| | | turnFight.addTimeline() # 每个武将位算一个时间节点
|
| | | 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)
|
| | |
| | | turnFight.actionIndex += 1
|
| | |
|
| | | # 回合结束
|
| | | turnFight.addTimeline() # 每回合结束算一个时间节点
|
| | | 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)
|
| | |
| | | TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_FightStart)
|
| | |
|
| | | turnFight.enterLogic = True
|
| | | return
|
| | | return True
|
| | |
|
| | | def OnTimelineChange(turnFight):
|
| | | ## 每个时间节点变化时处理
|
| | |
| | | return
|
| | |
|
| | | def TurnFightHeroTurnStart(turnFight, batObj, turnNum):
|
| | | ## 武将回合开始时
|
| | | ## 武将回合开始时,不能行动也要触发
|
| | | if not batObj:
|
| | | return
|
| | |
|