From 206203b4ccec9426178e12b8d67c815c4743df54 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 01 九月 2025 15:45:06 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(优化主线战斗片段断点逻辑;)
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 233 ++++++++++++++++++++++++++--------------------------------
1 files changed, 105 insertions(+), 128 deletions(-)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index dab5601..0b40ce3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -148,8 +148,6 @@
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 # 是否需要战报
@@ -157,9 +155,8 @@
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
@@ -178,11 +175,10 @@
## 一般用于玩家发起的战斗,在需要保留玩家阵容属性及状态的情况下,重置回合进入下一场战斗
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
@@ -220,21 +216,20 @@
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
@@ -288,7 +283,8 @@
def startFight(self):
## 准备就绪,开始战斗
self.state = FightState_Start
- self.setTimeline(1)
+ self.turnNum = 1
+ self.timeline = self.getTurnNumStartTimelin(self.turnNum)
self.syncInit()
return
@@ -742,6 +738,7 @@
__doSetFightPoint(curPlayer, reqValue)
return
+ GameWorld.DebugLog("主线战斗请求: reqType=%s" % reqType, curPlayer.GetPlayerID())
clientPack = ChPyNetSendPack.tagSCTurnFightReportSign()
clientPack.Sign = 0
NetPackCommon.SendFakePack(curPlayer, clientPack) # 标记开始
@@ -856,6 +853,8 @@
turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
turnFight.sortActionQueue()
turnFight.startFight()
+
+ __doMainFight(curPlayer)
return
def __doMainBossStart(curPlayer):
@@ -939,18 +938,20 @@
__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
@@ -977,6 +978,8 @@
# 每次处理一小队的完整战斗,相当于一次完整战报
__processTurnFight(turnFight.guid)
return
+ else:
+ __doMainFight(curPlayer)
else:
__doMainLevelWave(curPlayer, False)
return
@@ -987,128 +990,109 @@
# 小怪战斗,每次消耗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):
@@ -1121,12 +1105,12 @@
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)
@@ -1136,17 +1120,9 @@
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
@@ -1160,10 +1136,11 @@
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)
@@ -1178,7 +1155,7 @@
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)
@@ -1223,7 +1200,7 @@
TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_FightStart)
turnFight.enterLogic = True
- return
+ return True
def OnTimelineChange(turnFight):
## 每个时间节点变化时处理
@@ -1335,7 +1312,7 @@
return
def TurnFightHeroTurnStart(turnFight, batObj, turnNum):
- ## 武将回合开始时
+ ## 武将回合开始时,不能行动也要触发
if not batObj:
return
--
Gitblit v1.8.0