From a410c052ad4992ca846e3e30f0ccf9ab0b85a1d7 Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期三, 17 九月 2025 17:14:32 +0800 Subject: [PATCH] 129 【战斗】战斗系统-服务端(甄姬、曹操技能;增加本次技能万分比效果ID6004;) --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 215 ++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 170 insertions(+), 45 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 98b9907..e5a4564 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py @@ -21,6 +21,7 @@ import ChConfig import PlayerTask +import PlayerViewCache import ChPyNetSendPack import NetPackCommon import PlayerControl @@ -35,6 +36,7 @@ import TurnPassive import TurnSkill import TurnBuff +import CommFunc import ObjPool import FBLogic @@ -161,28 +163,45 @@ self.startTime = 0 # 开始时间戳,支持毫秒小数 self.costTime = 0 # 单场战斗总耗时,支持毫秒小数 - # 多小队 - 一般只有PVE用到 + # 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={}, lineupIDList=[], strongerLV=0, difficulty=0): + def setTurnFight(self, mapID, funcLineID, turnMax, isNeedReport=False, msgDict={}): ## 设置本场回合战斗设定 self.mapID = mapID self.funcLineID = funcLineID self.turnMax = turnMax # 最大回合数 self.isNeedReport = isNeedReport - self.lineupIndex = 0 - self.lineupIDList = lineupIDList - self.strongerLV = strongerLV - self.difficulty = difficulty + self.setPVE() + self.setPVP() self.msgDict = {} self.nextTurnFight(msgDict) return - def nextTurnFight(self, msgDict={}): + 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 @@ -192,6 +211,8 @@ self.timeline = 0 self.startTime = time.time() self.costTime = 0 + if resetByNextTeam: + ResetByNextTeam(self) return def haveNextLineup(self): @@ -244,7 +265,7 @@ @param turnNum: 第x回合 ''' self.timeline = timeline - GameWorld.DebugLog("时间节点更新: %s" % self.timeline) + GameWorld.DebugLog("[时间节点更新]: %s" % self.timeline) if isEmpty: # 空位置的节点可直接跳过 return timeline @@ -393,7 +414,9 @@ headStr = "%02x%02x" % (clientPack.Cmd, clientPack.SubCmd) if self.isNeedReport: packBuff = clientPack.GetBuffer() - GameWorld.DebugLog("回合战斗过程封包: %s" % (headStr)) + buffLen = len(packBuff) + GameWorld.DebugLog("回合战斗过程封包: %s, len:%s" % (headStr, buffLen)) + self.batBuffer += CommFunc.WriteWORD("", buffLen) self.batBuffer += packBuff ObjPool.GetPoolMgr().release(clientPack) else: @@ -476,10 +499,30 @@ % (chapterID, levelNum, nowChapterID, fixNowValue), curPlayer.GetPlayerID()) return -def GetPlayerLineupInfoByCache(playerID, lineupID): - ## 获取玩家阵容信息 - 根据玩家查看缓存 - lineupInfo = {} + +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格式,前端通用 @@ -487,11 +530,10 @@ # @return: 阵容全部信息json字典,前端通用格式 playerID = curPlayer.GetPlayerID() - lineup = PlayerOnline.GetOnlinePlayer(curPlayer).GetLineup(lineupID) + lineup = GetPlayerLineup(curPlayer, lineupID) if not lineup.lineupHeroDict: return {} - lineupInfo = {"PlayerID":playerID, "FightPower":lineup.fightPower, "ShapeType":lineup.shapeType} heroDict = {} curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero) for posNum in lineup.lineupHeroDict.keys(): @@ -517,8 +559,11 @@ "AttrDict":{str(k):v for k, v in hero.heroBatAttrDict.items() if v > 0}, "SkillIDList":skillIDlist, } - lineupInfo.update({"Hero":heroDict}) + + if not heroDict: + return {} + lineupInfo = {"PlayerID":playerID, "FightPower":lineup.fightPower, "ShapeType":lineup.shapeType, "Hero":heroDict} return lineupInfo def GetNPCLineupInfo(lineupID, strongerLV=0, difficulty=0): @@ -573,7 +618,7 @@ else: heroID = 0 skinID = 0 - skillIDList = [] + npcData.GetSkillIDList() + skillIDList = []# + npcData.GetSkillIDList() # boss额外随机技能 bossID = lineupIpyData.GetBossID() @@ -619,7 +664,7 @@ angerSkillID = heroIpyData.GetAngerSkillID() skillIDList = [normalSkillID, angerSkillID] - breakIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroBreak", heroID) + breakIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("HeroBreak", heroID) if breakIpyDataList: for breakIpyData in breakIpyDataList: if breakIpyData.GetBreakLV() > breakLV: @@ -628,7 +673,7 @@ if skillID: skillIDList.append(skillID) - awakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroAwake", heroID) + awakeIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("HeroAwake", heroID) if awakeIpyDataList: for awakeIpyData in awakeIpyDataList: if awakeIpyData.GetAwakeLV() > awakeLV: @@ -683,11 +728,9 @@ batObjMgr = BattleObj.GetBatObjMgr() initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1) - atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 2) for posNumKey, heroInfo in heroDict.items(): posNum = int(posNumKey) - atkBackSkillID = 0 # 反击技能ID fightPower = 0 skillIDList = [] # 战斗对象可能改变属性或技能,重新创建,防止误修改来源值 attrDict = {} @@ -697,10 +740,12 @@ heroID = heroInfo.get("HeroID", 0) skinID = heroInfo.get("SkinID", 0) lv = heroInfo.get("LV", 1) + specialty, atkDistType, country, sex = 0, 1, 0, 1 heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) if heroID else None if heroIpyData: - atkDistType = heroIpyData.GetAtkDistType() objName = heroIpyData.GetName() + specialty = heroIpyData.GetSpecialty() + atkDistType = heroIpyData.GetAtkDistType() country = heroIpyData.GetCountry() sex = heroIpyData.GetSex() @@ -714,10 +759,7 @@ if not npcDataEx: continue if not heroIpyData: - atkDistType = npcDataEx.GetAtkDistType() objName = npcDataEx.GetNPCName() - country = npcDataEx.GetCountry() - sex = npcDataEx.GetSex() batObj = batObjMgr.addBatObj() if not batObj: @@ -734,16 +776,11 @@ batObj.SetFightPower(fightPower) batObj.SetLV(lv) batObj.SetAtkDistType(atkDistType) + batObj.SetSpecialty(specialty) batObj.SetCountry(country) batObj.SetSex(sex) batObj.SetHero(heroID, skinID) - if atkDistType == ChConfig.AtkDistType_Short: - atkBackSkillID = atkBackSkillIDList[0] if len(atkBackSkillIDList) > 0 else 0 - elif atkDistType == ChConfig.AtkDistType_Long: - atkBackSkillID = atkBackSkillIDList[1] if len(atkBackSkillIDList) > 1 else 0 - if atkBackSkillID: - skillIDList.append(atkBackSkillID) skillManager = batObj.GetSkillManager() skillManager.SkillReset() for skillID in skillIDList: @@ -752,6 +789,39 @@ 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 @@ -788,12 +858,11 @@ atkLineupID, defLineupID = FBLogic.GetFBPlayerLineupID(curPlayer, mapID, funcLineID) if atkLineupID not in ShareDefine.LineupList or defLineupID not in ShareDefine.LineupList: return - + # 玩家 if tagType == 1: - # OnTurnFightVSPlayer - pass - + OnTurnFightVSPlayer(curPlayer, mapID, funcLineID, atkLineupID, defLineupID, tagID) + # NPC else: ret = FBLogic.GetFBNPCLineupInfo(curPlayer, mapID, funcLineID) @@ -816,9 +885,8 @@ GameWorld.DebugLog("玩家没有该阵容数据! atkLineupID=%s" % atkLineupID, playerID) return - turnMax = 15 + turnMax = GetTurnMax(mapID) if mapID == ChConfig.Def_FBMapID_MainBoss: - turnMax = IpyGameDataPY.GetFuncCfg("Mainline", 3) # 停止主线小怪战斗、清空 mainFightMgr = GetMainFightMgr(curPlayer) mainTF = mainFightMgr.turnFight @@ -829,14 +897,15 @@ turnFight = tfMgr.addTurnFight(mapID, funcLineID, playerID) guid = turnFight.guid - turnFight.setTurnFight(mapID, funcLineID, turnMax, True, lineupIDList=npcLineupIDList, strongerLV=strongerLV, difficulty=difficulty) + turnFight.setTurnFight(mapID, funcLineID, turnMax, True) + turnFight.setPVE(npcLineupIDList, strongerLV, difficulty) turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo}) for index, lineupID in enumerate(npcLineupIDList): turnFight.lineupIndex = index GameWorld.DebugLog("对战NPC阵容: index=%s, lineupID=%s" % (index, lineupID)) if index > 0: - turnFight.nextTurnFight() + turnFight.nextTurnFight(resetByNextTeam=True) turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)}) turnFight.sortActionQueue() turnFight.startFight() @@ -846,9 +915,54 @@ if not turnFight.isWin: break + PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer) SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer) tfMgr.delTurnFight(guid) return + +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 + + 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 # @@ -961,13 +1075,14 @@ mainFightMgr.levelNum = levelNum mainFightMgr.waveMax = waveMax mainFightMgr.wave = wave - turnMax = IpyGameDataPY.GetFuncCfg("Mainline", 2) 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, lineupIDList=lineupIDList, strongerLV=strongerLV, difficulty=difficulty) + 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() @@ -1008,7 +1123,7 @@ if nextLineupID: GameWorld.DebugLog("---开始进入下一小队: lineupIndex=%s,nextLineupID=%s,%s" % (turnFight.lineupIndex, nextLineupID, turnFight.lineupIDList)) - turnFight.nextTurnFight() + turnFight.nextTurnFight(resetByNextTeam=True) # 切换小队时,玩家阵容不需要处理,保留状态 turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(nextLineupID, turnFight.strongerLV, turnFight.difficulty)}) turnFight.sortActionQueue() @@ -1049,7 +1164,7 @@ turnFight.syncState(FightState_Fighting) for faction, num in turnFight.actionSortList: - GameWorld.DebugLog("回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num)) + GameWorld.DebugLog("大回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num)) batFaction = turnFight.getBatFaction(faction) batLineup = batFaction.getBatlineup(num) batLineup.actionNum = 1 @@ -1140,7 +1255,7 @@ # 回合开始 for faction, num in turnFight.actionSortList: - GameWorld.DebugLog("回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num)) + GameWorld.DebugLog("大回合开始逻辑: turnNum=%s,faction=%s, num=%s" % (turnNum, faction, num)) batFaction = turnFight.getBatFaction(faction) batLineup = batFaction.getBatlineup(num) batLineup.actionNum = 1 @@ -1347,6 +1462,7 @@ if batObj.GetHP() <= 0: return + GameWorld.DebugLog("---[武将回合开始时] : curID=%s,curHP=%s/%s" % (batObj.GetID(), batObj.GetHP(), batObj.GetMaxHP())) TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_HeroTurnStart) return @@ -1553,10 +1669,19 @@ # 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 - #SyncTurnFightReport(curPlayer, guid, reprot) + # 其他战报,一般是入库存储的,待扩展 + + # 战报已过期 + PlayerControl.NotifyCode(curPlayer, "FightReportExpired") return def SyncTurnFightReport(curPlayer, guid, reprot): -- Gitblit v1.8.0