From e926fc46837c5fb26c537ecb15945a78e2f3423f Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 17 十一月 2025 19:53:58 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(完善战斗相关公式参数;竞技增减伤属性、战力系数改为PVP增减伤;)
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 210 insertions(+), 24 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 1a0144f..814a105 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -27,6 +27,8 @@
import NetPackCommon
import PlayerControl
import GameWorld
+import PlayerLLMJ
+import PlayerPrestigeSys
import IpyGameDataPY
import PlayerOnline
import NPCCommon
@@ -45,6 +47,8 @@
import random
import time
import json
+
+g_gmTestFightReq = []
PosNumMax = 7 # 最大站位编号
ActionNumStart = -1 # 起始行动位置编号,一般是从1开始,如果有加主公、红颜等则扣除相应位置值,如从0或-1开始
@@ -71,6 +75,7 @@
self.shapeType = 0 # 阵型
self.fightPower = 0 # 阵容总战力
self.posObjIDDict = {} # 站位对应战斗实体 {站位编号:batObjID, ...}, 站位编号小于0为非主战单位,如主公、红颜等
+ self.heroObjIDDict = {} # 武将ID对应ObjID {heroID:batObjID, ...}
self.lingshouObjIDDict = {} # 灵兽战斗单位 {位置编号:batObjID, ...}
self.beautyObjIDDict = {} # 红颜战斗单位 {位置编号:batObjID, ...}
self.actionNum = ActionNumStart # 行动位置,从1开始
@@ -107,6 +112,7 @@
for objID in self.beautyObjIDDict.values():
batObjMgr.delBatObj(objID)
self.posObjIDDict = {}
+ self.heroObjIDDict = {}
self.lingshouObjIDDict = {}
self.beautyObjIDDict = {}
self.fightPower = 0
@@ -182,6 +188,7 @@
self.isNeedReport = isNeedReport # 是否需要战报
self.msgDict = {} # 扩展信息字典,一般由MapID绑定的功能决定信息内容 {k:v, ...}
self._kvDict = {} # 自定义信息字典,不会被重置 {k:v, ...}
+ self.awardData = None # 战斗奖励设置的数据,可以是任意数据格式,由功能自行决定,会传递给 OnTurnFightAward 处理
self.factionDict = {} # 战斗阵营 {faction:BatFaction, ...},一般是只有两个阵营,faction为1或2,每个阵营支持多个阵容
self.actionSortList = [] # 阵容行动顺序 [[faction, num], ...]
@@ -211,6 +218,7 @@
self.setPVP()
self.msgDict = {}
self._kvDict = {}
+ self.awardData = None
self.nextTurnFight(msgDict)
return
@@ -225,6 +233,8 @@
self.tagPlayerID = tagPlayerID
self.tagViewCache = tagViewCache
return
+
+ def getPVPPlayerID(self): return self.tagPlayerID # 获取PVP目标玩家ID,也可用于判断是否PVP
def isFBMap(self):
## 是否副本地图中,非主线的均视为副本
@@ -512,6 +522,18 @@
self.waveMax = 6 # 本关最大波数,每波有多个小队,每个小队即为一张战斗 TurnFight
self.wave = 0 # 当前刷怪波,注意不是玩家当前进度波,比如被击杀会回退一波
self.turnFight = GetTurnFightMgr().addTurnFight(ChConfig.Def_FBMapID_Main, 0, playerID)
+
+ # 主线小怪战斗额外数据,一般用于分割与主线战斗表现无关的附加功能内容
+ self.useZhanchui = 0
+ self.mjExp = 0 # 历练秘笈额外经验
+ self.killNPCCnt = 0
+ return
+
+ def resetMainFightExDataRec(self):
+ ## 重置主线战斗相关的额外数据记录,每次前端请求主线小怪战斗处理后需要重置
+ self.useZhanchui = 0
+ self.mjExp = 0
+ self.killNPCCnt = 0
return
def isLevelBoss(self):
@@ -605,7 +627,10 @@
# @param lineupID: 阵容ID
# @param npcLV: 成长NPC等级
# @param difficulty: 成长NPC难度系数
- # @return: 阵容全部信息json字典,前端通用格式
+ # @return: 阵容全部信息json字典,前端通用格式
+ lineupInfo = GetGMTestNPCLineupInfo(lineupID, strongerLV, difficulty)
+ if lineupInfo:
+ return lineupInfo
ipyData = IpyGameDataPY.GetIpyGameData("NPCLineup", lineupID)
if not ipyData:
return {}
@@ -627,6 +652,93 @@
lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict, "BossID":bossID, "BossPosView":bossPosView}
return lineupInfo
+def GMTestFight(curPlayer, heroIDList, isAllSkill):
+ ## GM测试战斗,指定武将
+ global g_gmTestFightReq
+ g_gmTestFightReq = [heroIDList, isAllSkill]
+ __doMainLevelWave(curPlayer, True)
+ g_gmTestFightReq = []
+ return
+
+def GetGMTestNPCLineupInfo(lineupID, strongerLV=0, difficulty=0):
+ ## 获取GM测试战斗阵容信息
+ if not g_gmTestFightReq:
+ return
+ heroIDList, isAllSkill = g_gmTestFightReq
+
+ lineupIpyData = IpyGameDataPY.GetIpyGameData("NPCLineup", lineupID)
+ if not lineupIpyData:
+ return
+
+ npcDict = {}
+ heroNPCIDDict = {}
+ for posNum in range(1, 1 + 6):
+ if not hasattr(lineupIpyData, "GetPosNPCID%s" % posNum):
+ break
+ npcID = getattr(lineupIpyData, "GetPosNPCID%s" % posNum)()
+ if not npcID:
+ continue
+ battleDict = GetNPCBattleDict(lineupIpyData, npcID, strongerLV, difficulty)
+ if not battleDict:
+ continue
+ npcDict[npcID] = battleDict
+ heroID = battleDict["HeroID"]
+ heroNPCIDDict[heroID] = npcID
+
+ if not npcDict:
+ return
+
+ heroDict = {}
+ # 原先阵容刚好有的直接用
+ for posNum, heroID in enumerate(heroIDList, 1):
+ if heroID not in heroNPCIDDict:
+ continue
+ npcID = heroNPCIDDict[heroID]
+ heroDict[str(posNum)] = npcDict[npcID]
+ heroIDList[posNum - 1] = 0
+
+ lineupNPCID = npcDict.keys()[0]
+ ipyNPCIDList = []
+ ipyHeroIDList = []
+ ipyDataMgr = IpyGameDataPY.IPY_Data()
+ for index in xrange(ipyDataMgr.GetNPCCount()):
+ ipyData = ipyDataMgr.GetNPCByIndex(index)
+ heroID = ipyData.GetRelatedHeroID()
+ npcID = ipyData.GetNPCID()
+ ipyNPCIDList.append(npcID)
+ ipyHeroIDList.append(heroID)
+
+ lineupNPCIndex = ipyNPCIDList.index(lineupNPCID)
+ # 从参考阵容先往前检索,再往后检索,还没有对应武将的NPC
+ loopIndexList = range(lineupNPCIndex + 1)[::-1] + range(lineupNPCIndex + 1, ipyDataMgr.GetNPCCount())
+ for index in loopIndexList:
+ npcID = ipyNPCIDList[index]
+ heroID = ipyHeroIDList[index]
+ if heroID not in heroIDList:
+ continue
+ battleDict = GetNPCBattleDict(lineupIpyData, npcID, strongerLV, difficulty)
+ if not battleDict:
+ continue
+
+ for posNum, posHeroID in enumerate(heroIDList, 1):
+ if not posHeroID or heroID != posHeroID:
+ continue
+ heroIDList[posNum - 1] = 0
+ heroDict[str(posNum)] = battleDict
+
+ if heroIDList.count(0) == len(heroIDList):
+ break
+
+ if isAllSkill:
+ for battleDict in heroDict.values():
+ heroID = battleDict["HeroID"]
+ heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) if heroID else None
+ skillIDList = GetNPCHeroSkillIDList(heroID, heroIpyData, 99999, 99999) # 默认取突破、觉醒都满级时的技能
+ battleDict["SkillIDList"] = skillIDList
+
+ lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict, "BossID":0, "BossPosView":0}
+ return lineupInfo
+
def GetNPCBattleDict(lineupIpyData, npcID, strongerLV=0, difficulty=0):
## 获取NPC战斗相关字典,支持成长NPC
# @param strongerLV: 成长等级
@@ -755,7 +867,9 @@
@param lineupInfo: 阵容信息
@param playerID: 发起的玩家ID,系统场次为0
'''
- GameWorld.DebugLog("SummonLineupObjs faction:%s,num:%s,lineupInfo=%s" % (faction, num, lineupInfo), playerID)
+ lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
+ npcLineupID = lineupInfo.get("NPCLineupID", 0)
+ GameWorld.DebugLog("SummonLineupObjs faction:%s,num:%s,npcLineupID=%s,lineupPlayerID=%s" % (faction, num, npcLineupID, lineupPlayerID), playerID)
if playerID:
curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
if not curPlayer:
@@ -763,7 +877,6 @@
turnFight = batLineup.turnFight
tfGUID = turnFight.guid
- lineupPlayerID = lineupInfo.get("PlayerID", 0) # 阵容所属玩家ID
heroDict = lineupInfo.get("Hero", {})
batObjMgr = BattleObj.GetBatObjMgr()
@@ -829,6 +942,7 @@
skillManager.LearnSkillByID(skillID)
batLineup.posObjIDDict[posNum] = objID
+ batLineup.heroObjIDDict[heroID] = objID
GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillManager.GetSkillIDList()))
ResetObjSkill(batObj)
@@ -1011,7 +1125,9 @@
break
PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
- SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
+ SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer) # 同步战报
+ #在同步战报后再处理结算奖励,与战斗表现分离
+ FBLogic.OnTurnFightAward(curPlayer, turnFight, mapID, funcLineID, turnFight.awardData)
tfMgr.delTurnFight(guid)
return True
@@ -1050,6 +1166,7 @@
PlayerOnline.GetOnlinePlayer(curPlayer).SetLastBatBuffer(guid, turnFight.batBuffer)
SyncTurnFightReport(curPlayer, guid, turnFight.batBuffer)
+ FBLogic.OnTurnFightAward(curPlayer, turnFight, mapID, funcLineID, turnFight.awardData)
tfMgr.delTurnFight(guid)
return True
@@ -1080,6 +1197,9 @@
return
GameWorld.DebugLog("------------------- 主线战斗请求: reqType=%s" % reqType, curPlayer.GetPlayerID())
+ mainFightMgr = GetMainFightMgr(curPlayer)
+ mainFightMgr.resetMainFightExDataRec() # 请求时补重置,防止异常时重复结算逻辑
+
clientPack = ChPyNetSendPack.tagSCTurnFightReportSign()
clientPack.Sign = 0
NetPackCommon.SendFakePack(curPlayer, clientPack) # 标记开始
@@ -1094,6 +1214,34 @@
# 标记结束
clientPack.Sign = 1
NetPackCommon.SendFakePack(curPlayer, clientPack)
+
+ __doMainFightExDataFunc(curPlayer)
+ return
+
+def __doMainFightExDataFunc(curPlayer):
+ mainFightMgr = GetMainFightMgr(curPlayer)
+
+ # 本次消耗战锤数
+ useZhanchui = mainFightMgr.useZhanchui
+ if useZhanchui > 0:
+ PlayerLLMJ.AddUseZhanchui(curPlayer, useZhanchui)
+ PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_UseXiantao, useZhanchui)
+ PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_CutTree, useZhanchui)
+ PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_CutTree, useZhanchui)
+
+ # 历练秘境额外经验
+ mjExp = mainFightMgr.mjExp
+ if mjExp > 0:
+ PlayerLLMJ.AddExpEx(curPlayer, mjExp)
+
+ # 击杀怪物
+ killNPCCnt = mainFightMgr.killNPCCnt
+ if killNPCCnt > 0:
+ PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_KillNPC, killNPCCnt)
+ PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_KillNPC, killNPCCnt)
+
+ # 结算逻辑最后重置数据
+ mainFightMgr.resetMainFightExDataRec()
return
def __doExitMainFight(curPlayer):
@@ -1412,7 +1560,7 @@
batObjMgr = BattleObj.GetBatObjMgr()
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
@@ -1426,8 +1574,9 @@
turnFight.ResetOneActionUseSkillCnt()
batObj.SetTiming(ChConfig.TurnTiming_Before) # 重置时机到回合前
if turnNum > 1: # 第1回合不用刷新技能
- RefreshObjSkillByTurn(batObj)
-
+ RefreshObjSkillByBigTurn(batObj)
+ RefreshObjByBigTurn(turnFight, batObj)
+ batObj.ResetBigTurn() # 每大回合重置
TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
return
@@ -1498,9 +1647,11 @@
GameWorld.DebugLog("技能初始CD: curID=%s,skillID=%s,initCD=%s" % (curID, skillID, initCD))
elif curSkill.GetRemainTime():
curSkill.SetRemainTime(0)
+ curSkill.SetEnergy(0)
+
return
-def RefreshObjSkillByTurn(batObj):
+def RefreshObjSkillByBigTurn(batObj):
'''按回合刷新技能:默认以大回合统一减1回合
'''
curID = batObj.GetID()
@@ -1520,8 +1671,31 @@
remainTime -= 1
curSkill.SetRemainTime(remainTime)
GameWorld.DebugLog(" 更新技能CD: curID=%s,skillID=%s,remainTime=%s" % (curID, skillID, remainTime))
-
- batObj.ResetSkillTurnUseCnt() # 重置回合使用次数,放刷新CD后重置
+ return
+
+def RefreshObjByBigTurn(turnFight, batObj):
+ ## 根据大回合开始刷新buff持续时间,每个大回合-1,第1回合不处理
+ curID = batObj.GetID()
+ 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.GetLastTimeType() != ChConfig.BuffLastTimeType_BigTurn:
+ continue
+ if skillData.GetSkillType() in ChConfig.Def_LstBuff_List:
+ #GameWorld.DebugLog(" 持续类buff由触发时机决定剩余时间! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
+ continue
+ if skillData.GetSkillType() == ChConfig.Def_SkillType_Halo and buff.GetOwnerID() != curID:
+ GameWorld.DebugLog(" 光环buff非光源不处理! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
+ continue
+ remainTime = buff.GetRemainTime()
+ if remainTime <= 0:
+ continue
+ remainTime -= 1
+ GameWorld.DebugLog(" 更新buff回合: curID=%s,buffID=%s,skillID=%s,remainTime=%s" % (curID, buffID, skillID, remainTime))
+ TurnBuff.SetBuffRemainTime(turnFight, batObj, buff, remainTime)
return
def RefreshObjBuffTime(turnFight, batObj):
@@ -1536,8 +1710,13 @@
buffID = buff.GetBuffID()
skillID = buff.GetSkillID()
skillData = buff.GetSkillData()
+ if skillData.GetLastTimeType() != ChConfig.BuffLastTimeType_Default:
+ continue
if skillData.GetSkillType() in ChConfig.Def_LstBuff_List:
#GameWorld.DebugLog(" 持续类buff由触发时机决定剩余时间! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
+ continue
+ if skillData.GetSkillType() == ChConfig.Def_SkillType_Halo and buff.GetOwnerID() != curID:
+ GameWorld.DebugLog(" 光环buff非光源不处理! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
continue
remainTime = buff.GetRemainTime()
if remainTime <= 0:
@@ -1554,13 +1733,9 @@
continue
remainTime -= 1
GameWorld.DebugLog(" 更新buff回合: curID=%s,buffID=%s,skillID=%s,remainTime=%s,addTiming=%s" % (curID, buffID, skillID, remainTime, addTiming))
- if remainTime > 0:
- buff.SetRemainTime(remainTime)
- TurnBuff.SyncBuffRefresh(turnFight, batObj, buff)
- else:
- TurnBuff.DoBuffDel(turnFight, batObj, buff)
+ TurnBuff.SetBuffRemainTime(turnFight, batObj, buff, remainTime)
return
-
+
def AddTurnObjCureHP(curObj, srcObj, addValue, cureHP, skillID=0):
## 回合对象添加治疗值
# @param curObj: 获得治疗的对象
@@ -1577,22 +1752,21 @@
return
-def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, isBounce=False):
+def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, lostType=""):
## 回合对象添加伤害值
- # @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))
+ GameWorld.DebugLog(" 统计输出: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,tagHP=%s,lostType=%s"
+ % (curID, tagID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), lostType))
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))
+ GameWorld.DebugLog(" 统计承伤: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,curHP=%s,lostType=%s"
+ % (tagID, curID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), lostType))
else:
# 如换血类技能,自残的伤害不算输出
@@ -1695,8 +1869,20 @@
# 暂时只算主线小怪
if curPlayer and turnFight.mapID == ChConfig.Def_FBMapID_Main and gameObj.GetFaction() != ChConfig.Def_FactionA:
- PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_KillNPC, 1)
- PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_KillNPC, 1)
+ GetMainFightMgr(curPlayer).killNPCCnt += 1
+
+ # 清除光源buff
+ buffMgr = gameObj.GetBuffManager()
+ for index in range(buffMgr.GetBuffCount())[::-1]:
+ buff = buffMgr.GetBuffByIndex(index)
+ skillID = buff.GetSkillID()
+ skillData = buff.GetSkillData()
+ if skillData.GetSkillType() != ChConfig.Def_SkillType_Halo:
+ continue
+ if buff.GetOwnerID() != objID:
+ continue
+ GameWorld.DebugLog("删除光环buff: objID=%s,skillID=%s" % (objID, skillID))
+ TurnBuff.DoBuffDel(turnFight, gameObj, buff)
return True
def OnTurnAllOver(guid):
--
Gitblit v1.8.0