From afea2d9d4b9cb6d0982c02a775e8198fc2421c53 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 08 十二月 2023 18:21:28 +0800
Subject: [PATCH] 10019 【砍树】回合战斗(增加抗连击、反击、抗反击、吸血、抗吸血属性,玩家及NPC属性接口通用;连击、反击属性效果支持;)
---
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py | 207 +++++++++++++++++++++++++++++++++------------------
1 files changed, 132 insertions(+), 75 deletions(-)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
index 390ae32..ddaceb7 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
@@ -20,7 +20,7 @@
import IpyGameDataPY
import ChPyNetSendPack
import CrossRealmPlayer
-import DataRecordPack
+#import DataRecordPack
import PlayerControl
import NetPackCommon
import CrossRealmMsg
@@ -52,21 +52,21 @@
g_bossRecDataDict = {} # boss对应rec记录缓存 {(zoneID, bossID):recData, ...}
-def GetCrossBossZoneID(realMapID, dataMapID, copyMapID):
+def GetCrossBossZoneID(mapID, realMapID, copyMapID):
## 获取地图跨服boss所属分区
- if dataMapID not in ChConfig.Def_CrossMapIDList:
+ if mapID not in ChConfig.Def_CrossMapIDList:
return 0
# 固定线路分配的
- if dataMapID in ChConfig.Def_CrossZoneMapTableName:
- tableName = ChConfig.Def_CrossZoneMapTableName[dataMapID]
- zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID)
+ if mapID in ChConfig.Def_CrossZoneMapTableName:
+ tableName = ChConfig.Def_CrossZoneMapTableName[mapID]
+ zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, mapID, copyMapID)
if not zoneIpyData:
return 0
return zoneIpyData.GetZoneID()
# 动态线路分配的
- elif dataMapID in ChConfig.Def_CrossDynamicLineMap:
- return PlayerFB.GetCrossDynamicLineZoneID(dataMapID, realMapID, copyMapID)
+ elif mapID in ChConfig.Def_CrossDynamicLineMap:
+ return PlayerFB.GetCrossDynamicLineZoneID(mapID, realMapID, copyMapID)
return 0
def __GetCrossBossRecData(zoneID, bossID):
@@ -112,44 +112,58 @@
@param serverGroupID: 为0时同步所有子服
'''
- GameWorld.Log("同步给子服跨服boss信息: syncServerGroupID=%s" % (serverGroupID))
- zoneIpyDataList = CrossRealmPlayer.GetCrossCommZoneIpyDataListByServerGroupID(serverGroupID)
- if not zoneIpyDataList:
- GameWorld.Log(" 没有跨服boss分区信息!")
- return
-
+ crossMapBossIDListDict = {}
ipyDataMgr = IpyGameDataPY.IPY_Data()
- for zoneIpyData in zoneIpyDataList:
- zoneID = zoneIpyData.GetZoneID()
- bossInfoList = []
- for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
- ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
- mapID = ipyData.GetMapID()
- if mapID not in ChConfig.Def_CrossMapIDList:
- continue
- bossID = ipyData.GetNPCID()
- bossRecData = __GetCrossBossRecData(zoneID, bossID)
- killedTime = GetRecKilledTime(bossRecData)
- refreshTime = GetRecRefreshTime(bossRecData)
- killedRecord = GetRecKilledRecord(bossRecData)
- isAlive = __GetCrossBossIsAlive(zoneID, bossID)
- killerExInfo = [] # 重连成功的信息同步不发送击杀者信息
- bossInfoList.append([zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo])
-
- if bossInfoList:
+ for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
+ ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
+ mapID = ipyData.GetMapID()
+ bossID = ipyData.GetNPCID()
+ if mapID not in ChConfig.Def_CrossZoneTypeName:
+ continue
+ if mapID not in crossMapBossIDListDict:
+ crossMapBossIDListDict[mapID] = []
+ bossIDList = crossMapBossIDListDict[mapID]
+ bossIDList.append(bossID)
+
+ crossZoneName = GameWorld.GetCrossZoneName()
+ GameWorld.Log("同步给子服跨服boss信息: crossZoneName=%s,syncServerGroupID=%s" % (crossZoneName, serverGroupID))
+
+ # 由于不同功能的跨服boss分区可能不一样,同步子服就需要按分区分步同步,所以需先发送一条初始化的信息类型先清空子服保存的跨服boss数据,再根据功能所属分区推送
+ serverGroupIDList = [serverGroupID] if serverGroupID else []
+ bossInfoDict = {"BossInfoType":"InitOK"}
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
+
+ for mapID, bossIDList in crossMapBossIDListDict.items():
+ GameWorld.Log(" mapID=%s, bossIDList=%s" % (mapID, bossIDList))
+ zoneIpyDataList = CrossRealmPlayer.GetCrossZoneIpyDataListByServerGroupID(mapID, serverGroupID)
+ if not zoneIpyDataList:
+ continue
+ for zoneIpyData in zoneIpyDataList:
+ zoneID = zoneIpyData.GetZoneID()
serverGroupIDList = [serverGroupID] if serverGroupID else zoneIpyData.GetServerGroupIDList()
- bossInfoDict = {"BossInfoType":"InitOK", "BossInfoList":bossInfoList}
- CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
- else:
- GameWorld.Log("没有跨服boss信息! zoneID=%s" % zoneID)
-
+ bossInfoList = []
+ for bossID in bossIDList:
+ bossRecData = __GetCrossBossRecData(zoneID, bossID)
+ killedTime = GetRecKilledTime(bossRecData)
+ refreshTime = GetRecRefreshTime(bossRecData)
+ killedRecord = GetRecKilledRecord(bossRecData)
+ isAlive = __GetCrossBossIsAlive(zoneID, bossID)
+ killerExInfo = [] # 重连成功的信息同步不发送击杀者信息
+ bossInfoList.append([zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo])
+
+ if bossInfoList:
+ bossInfoDict = {"BossInfoList":bossInfoList}
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
+ else:
+ GameWorld.Log("没有跨服boss信息! mapID=%s,zoneID=%s" % (mapID, zoneID))
+
return
-def DoCrossBossOnKilled(bossID, killPlayerName, realMapID, dataMapID, copyMapID, killerIDList):
+def DoCrossBossOnKilled(bossID, killPlayerName, mapID, realMapID, copyMapID, killerIDList):
## 跨服boss被杀
- zoneID = GetCrossBossZoneID(realMapID, dataMapID, copyMapID)
- GameWorld.Log("击杀跨服boss: zoneID=%s,bossID=%s,realMapID=%s,dataMapID=%s,copyMapID=%s,killerIDList=%s"
- % (zoneID, bossID, realMapID, dataMapID, copyMapID, killerIDList))
+ zoneID = GetCrossBossZoneID(mapID, realMapID, copyMapID)
+ GameWorld.Log("击杀跨服boss: zoneID=%s,bossID=%s,mapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s"
+ % (zoneID, bossID, mapID, realMapID, copyMapID, killerIDList))
if not zoneID:
return
@@ -164,35 +178,39 @@
refreshTime = SetBossRefreshTime(zoneID, bossID, killedTime, bossRecData)
# 广播子服跨服boss被击杀
- zoneIpyData = CrossRealmPlayer.GetCrossCommZoneIpyDataByZoneID(zoneID)
+ zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByZoneID(mapID, zoneID)
if zoneIpyData == None:
return
serverGroupIDList = zoneIpyData.GetServerGroupIDList()
killedRecord = GetRecKilledRecord(bossRecData)
- killerExInfo = [killerIDList, dataMapID]
+ killerExInfo = [killerIDList, mapID]
bossInfoList = [[zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo]]
bossInfoDict = {"BossInfoType":"OnKilled", "BossInfoList":bossInfoList}
CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossInfo, bossInfoDict, serverGroupIDList)
return
-def DoCrossBossStateChange(bossID, isAlive, dataMapID, realMapID, copyMapID):
+def DoCrossBossStateChange(bossID, isAlive, mapID, realMapID, copyMapID):
## 跨服boss状态变更
- zoneID = GetCrossBossZoneID(realMapID, dataMapID, copyMapID)
- GameWorld.Log("跨服boss状态变更: zoneID=%s,bossID=%s,isAlive=%s,realMapID=%s,dataMapID=%s,copyMapID=%s"
- % (zoneID, bossID, isAlive, realMapID, dataMapID, copyMapID))
+ zoneID = GetCrossBossZoneID(mapID, realMapID, copyMapID)
+ GameWorld.Log("跨服boss状态变更: zoneID=%s,bossID=%s,isAlive=%s,mapID=%s,realMapID=%s,copyMapID=%s"
+ % (zoneID, bossID, isAlive, mapID, realMapID, copyMapID))
if not zoneID:
return
- __SetCrossBossIsAlive(zoneID, bossID, isAlive)
-
- if isAlive:
- # 广播子服跨服boss复活
- zoneIpyData = CrossRealmPlayer.GetCrossCommZoneIpyDataByZoneID(zoneID)
- if zoneIpyData != None:
- serverGroupIDList = zoneIpyData.GetServerGroupIDList()
- stateInfo = [zoneID, bossID, isAlive]
- CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossState, stateInfo, serverGroupIDList)
-
+ if __GetCrossBossIsAlive(zoneID, bossID) != isAlive:
+ __SetCrossBossIsAlive(zoneID, bossID, isAlive)
+ if isAlive:
+ # 广播子服跨服boss复活
+ SendClientServerCrossBossState(mapID, zoneID, {bossID:isAlive})
+ return
+
+def SendClientServerCrossBossState(mapID, zoneID, bossStateDict={}):
+ # 广播子服跨服boss复活
+ zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByZoneID(mapID, zoneID)
+ if zoneIpyData != None:
+ serverGroupIDList = zoneIpyData.GetServerGroupIDList()
+ stateInfo = [zoneID, bossStateDict]
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossBossState, stateInfo, serverGroupIDList)
return
def __SetKilledRecord(bossRecData, killedTime, playerName):
@@ -247,6 +265,9 @@
mapID = ipyData.GetMapID()
if mapID not in ChConfig.Def_CrossZoneTypeName:
continue
+ refreshTimeStr = ipyData.GetRefreshTime()
+ if not refreshTimeStr or refreshTimeStr == "0":
+ continue
zoneTypeName = ChConfig.Def_CrossZoneTypeName[mapID]
if not hasattr(ipyDataMgr, "Get%sCount" % zoneTypeName):
continue
@@ -258,13 +279,13 @@
bossRecData = __GetCrossBossRecData(zoneID, bossID)
killedTime = GetRecKilledTime(bossRecData)
refreshTime = GetRecRefreshTime(bossRecData)
- PyGameData.g_sortBOSSRefreshList.append([bossID, killedTime, refreshTime, zoneID])
+ PyGameData.g_sortBOSSRefreshList.append([bossID, killedTime, refreshTime, zoneID, mapID])
PyGameData.g_sortBOSSRefreshList.sort(key=lambda asd:max(0, asd[2] - (curTime - asd[1])))
#GameWorld.DebugLog("检查boss复活: PyGameData.g_sortBOSSRefreshList=%s" % PyGameData.g_sortBOSSRefreshList)
- syncBOSSIDList = []
+ zoneMapBossStateDict = {}
for bossInfo in PyGameData.g_sortBOSSRefreshList:
- bossID, killedTime, refreshTime, zoneID = bossInfo
+ bossID, killedTime, refreshTime, zoneID, mapID = bossInfo
isAlive = __GetCrossBossIsAlive(zoneID, bossID)
if isAlive:
#GameWorld.DebugLog(" zoneID=%s,bossID=%s,未被击杀!" % (zoneID, bossID))
@@ -275,12 +296,21 @@
#GameWorld.DebugLog(" zoneID=%s,bossID=%s,refreshTime=%s,curTime=%s,killedTime=%s,重生倒计时秒(%s)!" % (zoneID, bossID, refreshTime, curTime, killedTime, rebornSecond))
break
- __SetCrossBossIsAlive(zoneID, bossID, 1)
- syncBOSSIDList.append(bossID)
+ isAlive = 1
+ __SetCrossBossIsAlive(zoneID, bossID, isAlive)
+
+ key = (mapID, zoneID)
+ if key not in zoneMapBossStateDict:
+ zoneMapBossStateDict[key] = {}
+ bossStateDict = zoneMapBossStateDict[key]
+ bossStateDict[bossID] = isAlive
GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 1)
GameWorld.DebugLog(" 通知MapServer重生: zoneID=%s,bossID=%s,killedTime=%s,rebornSecond=%s" % (zoneID, bossID, killedTime, rebornSecond))
+ for key, bossStateDict in zoneMapBossStateDict.items():
+ mapID, zoneID = key
+ SendClientServerCrossBossState(mapID, zoneID, bossStateDict)
return
def GetCrossBossIsAliveOrCanReborn(zoneID, bossID):
@@ -327,14 +357,15 @@
def OnPlayerLogin(curPlayer):
Sync_CrossBossInfo(curPlayer)
+ __LoginNotifyKillCrossBoss(curPlayer)
return
def CrossServerMsg_CrossBossInfo(bossInfoDict):
## 收到跨服服务器同步的跨服boss信息 {"BossInfoType":"InitOK", "BossInfoList":bossInfoList}
global g_bossRecDataDict
- bossInfoType = bossInfoDict["BossInfoType"]
- bossInfoList = bossInfoDict["BossInfoList"]
+ bossInfoType = bossInfoDict.get("BossInfoType", "")
+ bossInfoList = bossInfoDict.get("BossInfoList", [])
GameWorld.DebugLog("收到跨服同步的跨服boss信息: bossInfoType=%s" % (bossInfoType))
@@ -343,7 +374,8 @@
recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
recTypeListData.Clear()
g_bossRecDataDict = {}
-
+ return
+
syncBOSSIDList = []
for bossInfo in bossInfoList:
zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo = bossInfo
@@ -357,29 +389,51 @@
if not killerExInfo:
continue
- killerIDList, dataMapID = killerExInfo
+ killerIDList, mapID = killerExInfo
for playerID in killerIDList:
killer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
if not killer:
- GameWorld.ErrLog("击杀跨服boss时主服玩家不在线, playerID=%s,dataMapID=%s,bossID=%s" % (playerID, dataMapID, bossID))
- DataRecordPack.SendEventPack("CrossBoss_Error", {"PlayerID":playerID, "Error":"MainServerOffline"})
+ #GameWorld.ErrLog("击杀跨服boss时主服玩家不在线, playerID=%s,mapID=%s,bossID=%s" % (playerID, mapID, bossID))
+ #DataRecordPack.SendEventPack("CrossBoss_Error", {"PlayerID":playerID, "Error":"MainServerOffline"})
+ killTime = int(time.time())
+ PyGameData.g_unNotifyKillCrossBossDict[playerID] = [killTime, mapID, bossID]
continue
- msgInfo = str([dataMapID, bossID])
+ msgInfo = str([mapID, bossID])
killer.MapServer_QueryPlayerResult(0, 0, "CrossKillBoss", msgInfo, len(msgInfo))
Sync_CrossBossInfo(None, syncBOSSIDList)
return
+def __LoginNotifyKillCrossBoss(curPlayer):
+ ## 登录时通知未通知到的击杀跨服boss
+ playerID = curPlayer.GetPlayerID()
+ if playerID not in PyGameData.g_unNotifyKillCrossBossDict:
+ return
+ killTime, mapID, bossID = PyGameData.g_unNotifyKillCrossBossDict.pop(playerID)
+ curTime = int(time.time())
+ passSeconds = curTime - killTime
+ if passSeconds >= 120:
+ GameWorld.DebugLog("超过120秒上线不处理,主要为了防刷上线捡物品!", playerID)
+ return
+ msgInfo = str([mapID, bossID])
+ curPlayer.MapServer_QueryPlayerResult(0, 0, "CrossKillBoss", msgInfo, len(msgInfo))
+ GameWorld.Log("上线补通知击杀跨服boss: passSeconds=%s, mapID=%s, bossID=%s" % (passSeconds, mapID, bossID), playerID)
+ return
+
def CrossServerMsg_CrossBossState(msgInfo):
## 收到跨服服务器同步的跨服boss状态
- zoneID, bossID, isAlive = msgInfo
- GameWorld.DebugLog("收到跨服服务器同步的跨服boss状态: zoneID=%s, bossID=%s, isAlive=%s" % (zoneID, bossID, isAlive))
+ zoneID, bossStateDict = msgInfo
+ GameWorld.DebugLog("收到跨服服务器同步的跨服boss状态: zoneID=%s, bossStateDict=%s" % (zoneID, bossStateDict))
- __SetCrossBossIsAlive(zoneID, bossID, isAlive)
+ aliveBossIDList = []
+ for bossID, isAlive in bossStateDict.items():
+ __SetCrossBossIsAlive(zoneID, bossID, isAlive)
+ if isAlive:
+ aliveBossIDList.append(bossID)
- if isAlive:
- Sync_CrossBossInfo(None, [bossID])
+ if aliveBossIDList:
+ Sync_CrossBossInfo(None, aliveBossIDList)
return
@@ -387,7 +441,7 @@
def Sync_CrossBossInfo(curPlayer=None, syncBOSSIDList=[]):
## 同步boss相关信息
- curTime = int(time.time())
+ curTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCrossServerTimeStr())
recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
@@ -412,6 +466,9 @@
bossInfoObj.RefreshCD = refreshTime
bossInfo.BossInfoList.append(bossInfoObj)
+ if not bossInfo.BossInfoList:
+ return
+
bossInfo.BossCnt = len(bossInfo.BossInfoList)
if not curPlayer:
# 全服广播在线玩家
--
Gitblit v1.8.0