From 1890f0643483194e41668032aa75eb755c8a1aad Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期二, 12 八月 2025 17:23:43 +0800 Subject: [PATCH] 129 【战斗】战斗系统-服务端(主阵容变更时重新开始战斗;主阵容属性变化时实时更新主线战斗;主线战斗请求CD限制1秒;计算buff属性、buff添加删除通用逻辑;4012效果状态逻辑;) --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 121 ++++++++++++++++------------------------ 1 files changed, 49 insertions(+), 72 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 1bc7528..4e600cb 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py @@ -43,7 +43,6 @@ import time import json -FighterNPCID = 100 # 战斗NPCID,仅后端用,除怪物外,所有玩家武将均使用该NPCID PosNumMax = 10 # 最大站位编号 ActionNumStart = -1 # 起始行动位置编号,一般是从1开始,如果有加主公、红颜等则扣除相应位置值,如从0或-1开始 @@ -85,16 +84,6 @@ SummonLineupObjs(self, self.faction, self.num, lineupInfo, self.getPlayerID()) return - def resetLineup(self, isReborn=True): - ## 重置阵容 - batObjMgr = BattleObj.GetBatObjMgr() - for objID in self.posObjIDDict.values(): - batObj = batObjMgr.getBatObj(objID) - if not batObj: - continue - batObj.ResetBatObj(isReborn) - return - def clearLineup(self): ## 清除阵容 if not self.posObjIDDict: @@ -125,12 +114,6 @@ self.lineupDict[num] = lineup return lineup - def resetLineups(self): - ## 重置所有战斗阵容 - for lineup in self.lineupDict.values(): - lineup.resetLineup() - return - def clearLineups(self): ## 清除所有战斗阵容 for lineup in self.lineupDict.values(): @@ -154,6 +137,7 @@ 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 # 是否已执行进场逻辑 @@ -195,21 +179,15 @@ self.costTime = 0 return - def setFactionLineup(self, faction, lineupDict, onlyReset=False): + def setFactionLineup(self, faction, lineupDict): ## 设置阵营阵容 # @param lineupDict: {阵容编号:阵容信息, ...} 每个阵营支持多个阵容,即支持多V多 - # @param onlyReset: 是否仅重置,一般用于玩家的阵容,重复利用阵容实例, batFaction = self.getBatFaction(faction) - if onlyReset: - batFaction.resetLineups() - else: - batFaction.clearLineups() + batFaction.clearLineups() for num, lineupInfo in lineupDict.items(): - batLineup = batFaction.getBatlineup(num) - if onlyReset and not batLineup.isEmpty(): - continue if not lineupInfo: continue + batLineup = batFaction.getBatlineup(num) batLineup.setLineup(lineupInfo) return @@ -274,16 +252,21 @@ return 0 - def clearBatFaction(self, faction): - batFaction = self.getBatFaction(faction) - batFaction.clearLineups() - return - - def clearFight(self): + def exitFight(self): + ## 退出战斗 self.syncState(FightState_Over) for batFaction in self.factionDict.values(): batFaction.clearLineups() + self.state = -1 return + + def startFight(self): + ## 准备就绪,开始战斗 + self.state = FightState_Start + self.syncInit() + return + + def isInFight(self): return self.state != -1 def syncInit(self): ## 初始化通知 @@ -336,6 +319,7 @@ return def syncState(self, state, msgDict={}): + self.state = state msg = json.dumps(msgDict, ensure_ascii=False) msg = msg.replace(" ", "") clientPack = ChPyNetSendPack.tagMCTurnFightState() @@ -390,7 +374,7 @@ turnFight = self.getTurnFight(guid) if not turnFight: return - turnFight.clearFight() + turnFight.exitFight() self.turnFightDict.pop(guid, None) return @@ -590,8 +574,7 @@ batObj.SetNPCID(npcID) elif lineupPlayerID: batObj.SetOwnerHero(lineupPlayerID, heroID, skinID) - batObj.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP) - + if atkDistType == ChConfig.AtkDistType_Short: atkBackSkillID = atkBackSkillIDList[0] if len(atkBackSkillIDList) > 0 else 0 elif atkDistType == ChConfig.AtkDistType_Long: @@ -604,8 +587,8 @@ skillManager.LearnSkillByID(skillID) batLineup.posObjIDDict[posNum] = objID - GameWorld.DebugLog("AddBatObj ID:%s,faction:%s,num=%s,posNum=%s,skill=%s,atk=%s,def=%s,hp=%s" - % (objID, faction, num, posNum, skillIDList, batObj.GetAtk(), batObj.GetDef(), batObj.GetHP())) + GameWorld.DebugLog("AddBatObj ID:%s,faction:%s,num=%s,posNum=%s,skill=%s" % (objID, faction, num, posNum, skillIDList)) + batObj.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP) return @@ -636,7 +619,7 @@ if reqType == 2: # 前端主动请求开始关卡小怪的视为从休息中开始 __doMainLevelWave(curPlayer, True) elif reqType == 3: - __doMainBossStart(curPlayer, tick) + __doMainBossStart(curPlayer) elif reqType == 4: __doMainFight(curPlayer, tick) else: @@ -652,7 +635,7 @@ mainFightMgr = GetMainFightMgr(curPlayer) turnFight = mainFightMgr.turnFight if turnFight: - turnFight.clearFight() + turnFight.exitFight() return def __doSetFightPoint(curPlayer, fightPoint): @@ -735,13 +718,13 @@ turnFight = mainFightMgr.turnFight turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax}) - turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}, True) + turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}) turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)}) turnFight.sortActionQueue() - turnFight.syncInit() + turnFight.startFight() return -def __doMainBossStart(curPlayer, tick): +def __doMainBossStart(curPlayer): ## 开始挑战关卡boss playerID = curPlayer.GetPlayerID() chapterID, levelNum, wave = PlayerControl.GetMainLevelPassInfo(curPlayer) @@ -809,17 +792,27 @@ turnFight = mainFightMgr.turnFight turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax}) - turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}, True) + turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}) turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)}) turnFight.sortActionQueue() - turnFight.syncInit() + turnFight.startFight() # 挑战boss无中间过程,每次执行直接挑战一队结果 - __processTurnFight(turnFight.guid, tick) + __processTurnFight(turnFight.guid) return def __doMainFight(curPlayer, tick): ## 主线执行战斗 + + # 限制请求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) + mainFightMgr = GetMainFightMgr(curPlayer) turnFight = mainFightMgr.turnFight @@ -840,11 +833,11 @@ # 切换小队时,玩家阵容不需要处理,保留状态 turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)}) turnFight.sortActionQueue() - turnFight.syncInit() + turnFight.startFight() if mainFightMgr.isLevelBoss(): # 每次处理一小队的完整战斗,相当于一次完整战报 - __processTurnFight(turnFight.guid, tick) + __processTurnFight(turnFight.guid) return else: __doMainLevelWave(curPlayer, False) @@ -975,7 +968,7 @@ return -def __processTurnFight(guid, tick): +def __processTurnFight(guid): ## 一次性处理完一个小队的战斗 turnFight = GetTurnFightMgr().getTurnFight(guid) curPlayer = turnFight.curPlayer @@ -1052,24 +1045,6 @@ OnTurnAllOver(turnFight.guid) return -#// B4 10 回合制战斗 #tagCMTurnFight -# -#struct tagCMTurnFight -#{ -# tagHead Head; -# DWORD MapID; // 自定义地图ID,可用于绑定战斗地图场景功能(如主线关卡、主线boss、爬塔、竞技场等) -# DWORD FuncLineID; // MapID对应的扩展值,如具体某个关卡等 -# BYTE TagType; // 目标类型,0-NPC阵容,1-玩家 -# DWORD TagID; // 目标类型对应的ID,如阵容ID或玩家ID -# BYTE ValueCount; -# DWORD ValueList[ValueCount]; // 附加值列表,可选,具体含义由MapID决定 -#}; -def OnTurnFight(index, clientData, tick): - #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) - #mapID = clientData.MapID - #funcLineID = clientData.FuncLineID - return - def GetObjName(batObj): faction = batObj.faction num = batObj.lineupNum @@ -1100,20 +1075,21 @@ curID = batObj.GetID() buffMgr = batObj.GetBuffManager() GameWorld.DebugLog("更新buff: curID=%s,buffCount=%s" % (curID, buffMgr.GetBuffCount())) - for index in range(buffMgr.GetBuffCount()): + for index in range(buffMgr.GetBuffCount())[::-1]: buff = buffMgr.GetBuffByIndex(index) curRemainTime = buff.GetRemainTime() if not curRemainTime: # 永久buff不处理 continue buffID = buff.GetBuffID() + skillID = buff.GetSkillID() updRemainTime = curRemainTime - 1 - GameWorld.DebugLog(" 更新buff剩余回合数: buffID=%s,updRemainTime=%s" % (buffID, updRemainTime)) + GameWorld.DebugLog(" 更新buff剩余回合数: buffID=%s,skillID=%s,updRemainTime=%s" % (buffID, skillID, updRemainTime)) if updRemainTime > 0: - buff.SetRemainTime(curRemainTime - 1) + buff.SetRemainTime(updRemainTime) TurnBuff.SyncBuffRefresh(turnFight, batObj, buff) else: - TurnBuff.SyncBuffDel(turnFight, batObj, buffID) + TurnBuff.DoBuffDel(turnFight, batObj, buff) # SetTimeline(gameObj, turnNum, 0) # # 重置连击、反击数 @@ -1208,10 +1184,11 @@ GameWorld.DebugLog("★回合%s %s 当前状态不可行动!" % (turnNum, objName)) return - GameWorld.DebugLog("★回合%s %s 行动 : curHP=%s" % (turnNum, objName, curHP)) + 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) - curXP = curBatObj.GetXP() xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2) skillManager = curBatObj.GetSkillManager() useSkillList = [] -- Gitblit v1.8.0