#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#-------------------------------------------------------------------------------
|
#
|
##@package CrossBoss
|
#
|
# @todo:¿ç·þboss
|
# @author hxp
|
# @date 2019-01-09
|
# @version 1.0
|
#
|
# ÏêϸÃèÊö: ¿ç·þboss
|
#
|
#-------------------------------------------------------------------------------
|
#"""Version = 2019-01-09 15:30"""
|
#-------------------------------------------------------------------------------
|
|
import ChConfig
|
import GameWorld
|
import IpyGameDataPY
|
import ChPyNetSendPack
|
import CrossRealmPlayer
|
import DataRecordPack
|
import PlayerControl
|
import NetPackCommon
|
import CrossRealmMsg
|
import ShareDefine
|
import PyGameData
|
|
import time
|
|
'''
|
ShareDefine.Def_UniversalGameRecType_CrossBossInfo
|
value1:bossID
|
value2:killedTime
|
value4:refreshTime
|
value5:zoneID
|
StrValue3:"ʱ¼ä_Íæ¼ÒÃû|..."
|
'''
|
|
def GetRecBossID(recData): return recData.GetValue1()
|
def SetRecBossID(recData, value): return recData.SetValue1(value)
|
def GetRecKilledTime(recData): return recData.GetValue2()
|
def SetRecKilledTime(recData, value): return recData.SetValue2(value)
|
def GetRecRefreshTime(recData): return recData.GetValue4()
|
def SetRecRefreshTime(recData, value): return recData.SetValue4(value)
|
def GetRecZoneID(recData): return recData.GetValue5()
|
def SetRecZoneID(recData, value): return recData.SetValue5(value)
|
def GetRecKilledRecord(recData): return recData.GetStrValue3()
|
def SetRecKilledRecord(recData, value): return recData.SetStrValue3(value)
|
|
g_bossRecDataDict = {} # boss¶ÔÓ¦rec¼Ç¼»º´æ {(zoneID, bossID):recData, ...}
|
|
def GetCrossBossZoneID(realMapID, dataMapID, copyMapID):
|
## »ñÈ¡µØÍ¼¿ç·þbossËùÊô·ÖÇø
|
if dataMapID not in ChConfig.Def_CrossMapIDList:
|
return 0
|
if dataMapID not in ChConfig.Def_CrossZoneMapTableName:
|
GameWorld.ErrLog("¿ç·þbossûÓзÖÇø±í!dataMapID=%s" % dataMapID)
|
return 0
|
tableName = ChConfig.Def_CrossZoneMapTableName[dataMapID]
|
zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID)
|
if not zoneIpyData:
|
return 0
|
return zoneIpyData.GetZoneID()
|
|
def __GetCrossBossRecData(zoneID, bossID):
|
## »ñÈ¡¿ç·þBoss RecÊý¾Ý
|
# @param zoneID: ·ÖÇøID
|
# @param bossID: bossID
|
|
global g_bossRecDataDict
|
key = (zoneID, bossID)
|
if key in g_bossRecDataDict:
|
return g_bossRecDataDict[key]
|
|
recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
|
|
# ²éÕÒÊÇ·ñÒÑÓмǼ
|
bossRec = None
|
for index in xrange(recTypeListData.Count()):
|
recData = recTypeListData.At(index)
|
if GetRecBossID(recData) == bossID and GetRecZoneID(recData) == zoneID:
|
bossRec = recData
|
break
|
|
if bossRec == None:
|
#»¹Î´¼Ç¼£¬ÔòÌí¼ÓÒ»¸ö¼Ç¼¶ÔÏó
|
bossRec = recTypeListData.AddRec()
|
SetRecBossID(bossRec, bossID)
|
SetRecZoneID(bossRec, zoneID)
|
|
g_bossRecDataDict[key] = bossRec
|
return bossRec
|
|
def __SetCrossBossIsAlive(zoneID, bossID, isAlive):
|
## ÉèÖÿç·þÊÀ½çbossÊÇ·ñ»î×Å
|
GameWorld.GetGameWorld().SetDict(ChConfig.Def_WorldKey_CrossBossIsAlive % (zoneID, bossID), isAlive)
|
return
|
|
def __GetCrossBossIsAlive(zoneID, bossID):
|
## »ñÈ¡¿ç·þÊÀ½çbossÊÇ·ñ»î×Å
|
return GameWorld.GetGameWorld().GetDictByKey(ChConfig.Def_WorldKey_CrossBossIsAlive % (zoneID, bossID))
|
|
def Sync_CrossBossInitDataToClientServer(serverGroupID=0):
|
''' ͬ²½¿ç·þBoss»î¶¯Êý¾Ýµ½×Ó·þÎñÆ÷
|
@param serverGroupID: Ϊ0ʱͬ²½ËùÓÐ×Ó·þ
|
'''
|
|
GameWorld.Log("ͬ²½¸ø×Ó·þ¿ç·þbossÐÅÏ¢: syncServerGroupID=%s" % (serverGroupID))
|
zoneIpyDataList = CrossRealmPlayer.GetCrossCommZoneIpyDataListByServerGroupID(serverGroupID)
|
if not zoneIpyDataList:
|
GameWorld.Log(" ûÓпç·þboss·ÖÇøÐÅÏ¢!")
|
return
|
|
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:
|
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)
|
|
return
|
|
def DoCrossBossOnKilled(bossID, killPlayerName, realMapID, dataMapID, 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))
|
if not zoneID:
|
return
|
|
isAlive = 0
|
killedTime = int(time.time())
|
# ²éÕҼǼ
|
bossRecData = __GetCrossBossRecData(zoneID, bossID)
|
|
__SetKilledRecord(bossRecData, killedTime, killPlayerName)
|
|
__SetCrossBossIsAlive(zoneID, bossID, isAlive)
|
refreshTime = SetBossRefreshTime(zoneID, bossID, killedTime, bossRecData)
|
|
# ¹ã²¥×Ó·þ¿ç·þboss±»»÷ɱ
|
zoneIpyData = CrossRealmPlayer.GetCrossCommZoneIpyDataByZoneID(zoneID)
|
if zoneIpyData == None:
|
return
|
serverGroupIDList = zoneIpyData.GetServerGroupIDList()
|
killedRecord = GetRecKilledRecord(bossRecData)
|
killerExInfo = [killerIDList, dataMapID]
|
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):
|
## ¿ç·þ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))
|
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)
|
|
return
|
|
def __SetKilledRecord(bossRecData, killedTime, playerName):
|
## ÉèÖÃÊÀ½çbossÉÏÒ»´Î»÷ɱ¼Ç¼
|
killedRecord = GetRecKilledRecord(bossRecData)
|
killedRecordList = killedRecord.split('|') if killedRecord else []
|
killedRecordList.append("%s_%s" % (killedTime, playerName))
|
#¼Ç¼×î½ü5´Î
|
if len(killedRecordList) > 5:
|
del killedRecordList[0]
|
killedRecord = '|'.join(killedRecordList)
|
SetRecKilledRecord(bossRecData, killedRecord)
|
SetRecKilledTime(bossRecData, killedTime)
|
return
|
|
def SetBossRefreshTime(zoneID, bossID, killedTime, bossRecData):
|
'''ÉèÖÃbossË¢ÐÂʱ¼ä'''
|
ipyData = IpyGameDataPY.GetIpyGameData('BOSSInfo', bossID)
|
if not ipyData:
|
return 0
|
#onlineCnt = 0
|
#yesterdayCnt = 0
|
refreshTime = eval(ipyData.GetRefreshTime())
|
SetRecRefreshTime(bossRecData, refreshTime)
|
__UpdateBossRefreshList(zoneID, bossID, killedTime, refreshTime)
|
GameWorld.DebugLog(' ÉèÖÃbossË¢ÐÂʱ¼ä: zoneID=%s,bossID=%s,refreshTime=%s' % (zoneID, bossID, refreshTime))
|
return refreshTime
|
|
def __UpdateBossRefreshList(zoneID, bossID, killedTime=0, refreshTime=0):
|
for bossInfo in PyGameData.g_sortBOSSRefreshList:
|
if bossID == bossInfo[0] and zoneID == bossInfo[3]:
|
if killedTime:
|
bossInfo[1] = killedTime
|
if refreshTime:
|
bossInfo[2] = refreshTime
|
break
|
curTime = int(time.time())
|
PyGameData.g_sortBOSSRefreshList.sort(key=lambda asd:max(0, asd[2] - (curTime - asd[1])))
|
GameWorld.DebugLog(' PyGameData.g_sortBOSSRefreshList=%s' % PyGameData.g_sortBOSSRefreshList)
|
return
|
|
def DoCheckCrossBossReborn(tick):
|
## ¿ç·þboss¸´»î¼ì²é
|
|
curTime = int(time.time())
|
if not PyGameData.g_sortBOSSRefreshList:
|
ipyDataMgr = IpyGameDataPY.IPY_Data()
|
for i in xrange(ipyDataMgr.GetBOSSInfoCount()):
|
ipyData = ipyDataMgr.GetBOSSInfoByIndex(i)
|
bossID = ipyData.GetNPCID()
|
mapID = ipyData.GetMapID()
|
if mapID not in ChConfig.Def_CrossZoneMapTableName:
|
continue
|
tableName = ChConfig.Def_CrossZoneMapTableName[mapID]
|
if not hasattr(ipyDataMgr, "Get%sCount" % tableName):
|
continue
|
for i in xrange(getattr(ipyDataMgr, "Get%sCount" % tableName)()):
|
zoneIpyData = getattr(ipyDataMgr, "Get%sByIndex" % tableName)(i)
|
zoneID = zoneIpyData.GetZoneID()
|
bossRecData = __GetCrossBossRecData(zoneID, bossID)
|
killedTime = GetRecKilledTime(bossRecData)
|
refreshTime = GetRecRefreshTime(bossRecData)
|
PyGameData.g_sortBOSSRefreshList.append([bossID, killedTime, refreshTime, zoneID])
|
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 = []
|
for bossInfo in PyGameData.g_sortBOSSRefreshList:
|
bossID, killedTime, refreshTime, zoneID = bossInfo
|
isAlive = __GetCrossBossIsAlive(zoneID, bossID)
|
if isAlive:
|
#GameWorld.DebugLog(" zoneID=%s,bossID=%s,δ±»»÷ɱ£¡" % (zoneID, bossID))
|
continue
|
rebornSecond = max(0, refreshTime - (curTime - killedTime))
|
|
if rebornSecond > 0:
|
#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)
|
|
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))
|
|
return
|
|
def OnCrossMapServerInitOK():
|
__SendMapServerAliveCrossBoss()
|
return
|
|
def __SendMapServerAliveCrossBoss():
|
## ͬ²½µ±Ç°»¹»î×ŵÄboss£¬·ÀÖ¹µØÍ¼ÖØÆôºóÒѾˢеÄboss²»Ë¢ÐÂ
|
ipyDataMgr = IpyGameDataPY.IPY_Data()
|
for i in xrange(IpyGameDataPY.IPY_Data().GetBOSSInfoCount()):
|
ipyData = IpyGameDataPY.IPY_Data().GetBOSSInfoByIndex(i)
|
bossID = ipyData.GetNPCID()
|
mapID = ipyData.GetMapID()
|
if mapID not in ChConfig.Def_CrossZoneMapTableName:
|
continue
|
tableName = ChConfig.Def_CrossZoneMapTableName[mapID]
|
if not hasattr(ipyDataMgr, "Get%sCount" % tableName):
|
continue
|
for i in xrange(getattr(ipyDataMgr, "Get%sCount" % tableName)()):
|
zoneIpyData = getattr(ipyDataMgr, "Get%sByIndex" % tableName)(i)
|
zoneID = zoneIpyData.GetZoneID()
|
isAlive = __GetCrossBossIsAlive(zoneID, bossID)
|
if not isAlive:
|
continue
|
GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 1)
|
|
return
|
|
##------------------------------------- ÒÔÏÂÊDZ¾·þ´¦Àí -------------------------------------------
|
|
def OnPlayerLogin(curPlayer):
|
Sync_CrossBossInfo(curPlayer)
|
return
|
|
def CrossServerMsg_CrossBossInfo(bossInfoDict):
|
## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¿ç·þbossÐÅÏ¢ {"BossInfoType":"InitOK", "BossInfoList":bossInfoList}
|
global g_bossRecDataDict
|
|
bossInfoType = bossInfoDict["BossInfoType"]
|
bossInfoList = bossInfoDict["BossInfoList"]
|
|
GameWorld.DebugLog("ÊÕµ½¿ç·þͬ²½µÄ¿ç·þbossÐÅÏ¢: bossInfoType=%s" % (bossInfoType))
|
|
if bossInfoType == "InitOK":
|
# ×Ó·þÊÕµ½³õʼ»¯Êý¾ÝµÄ£¬¸²¸Ç¸üÐÂ
|
recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
|
recTypeListData.Clear()
|
g_bossRecDataDict = {}
|
|
syncBOSSIDList = []
|
for bossInfo in bossInfoList:
|
zoneID, bossID, killedTime, refreshTime, killedRecord, isAlive, killerExInfo = bossInfo
|
bossRecData = __GetCrossBossRecData(zoneID, bossID)
|
SetRecKilledTime(bossRecData, killedTime)
|
SetRecRefreshTime(bossRecData, refreshTime)
|
SetRecKilledRecord(bossRecData, killedRecord)
|
__SetCrossBossIsAlive(zoneID, bossID, isAlive)
|
syncBOSSIDList.append(bossID)
|
|
if not killerExInfo:
|
continue
|
|
killerIDList, dataMapID = 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"})
|
continue
|
msgInfo = str([dataMapID, bossID])
|
killer.MapServer_QueryPlayerResult(0, 0, "CrossKillBoss", msgInfo, len(msgInfo))
|
|
Sync_CrossBossInfo(None, syncBOSSIDList)
|
return
|
|
def CrossServerMsg_CrossBossState(msgInfo):
|
## ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¿ç·þboss״̬
|
|
zoneID, bossID, isAlive = msgInfo
|
GameWorld.DebugLog("ÊÕµ½¿ç·þ·þÎñÆ÷ͬ²½µÄ¿ç·þboss״̬: zoneID=%s, bossID=%s, isAlive=%s" % (zoneID, bossID, isAlive))
|
|
__SetCrossBossIsAlive(zoneID, bossID, isAlive)
|
|
if isAlive:
|
Sync_CrossBossInfo(None, [bossID])
|
|
return
|
|
|
def Sync_CrossBossInfo(curPlayer=None, syncBOSSIDList=[]):
|
## ͬ²½bossÏà¹ØÐÅÏ¢
|
|
curTime = int(time.time())
|
|
recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
|
|
bossInfo = ChPyNetSendPack.tagGCGameWorldBossInfo()
|
bossInfo.BossInfoList = []
|
for index in xrange(recTypeListData.Count()):
|
recData = recTypeListData.At(index)
|
bossID = GetRecBossID(recData)
|
if not bossID:
|
continue
|
if syncBOSSIDList and bossID not in syncBOSSIDList:
|
continue
|
zoneID = GetRecZoneID(recData)
|
killedTime = GetRecKilledTime(recData)
|
refreshTime = GetRecRefreshTime(recData)
|
bossInfoObj = ChPyNetSendPack.tagBossInfoObj()
|
bossInfoObj.BossID = bossID
|
bossInfoObj.IsAlive = __GetCrossBossIsAlive(zoneID, bossID)
|
bossInfoObj.KillRecord = GetRecKilledRecord(recData)
|
bossInfoObj.RecordLen = len(bossInfoObj.KillRecord)
|
bossInfoObj.RefreshSecond = max(0, refreshTime - (curTime - killedTime))
|
bossInfoObj.RefreshCD = refreshTime
|
bossInfo.BossInfoList.append(bossInfoObj)
|
|
bossInfo.BossCnt = len(bossInfo.BossInfoList)
|
if not curPlayer:
|
# È«·þ¹ã²¥ÔÚÏßÍæ¼Ò
|
playerManager = GameWorld.GetPlayerManager()
|
for i in xrange(playerManager.GetActivePlayerCount()):
|
curPlayer = playerManager.GetActivePlayerAt(i)
|
if curPlayer == None:
|
continue
|
if PlayerControl.GetIsTJG(curPlayer):
|
continue
|
NetPackCommon.SendFakePack(curPlayer, bossInfo)
|
else:
|
if PlayerControl.GetIsTJG(curPlayer):
|
return
|
NetPackCommon.SendFakePack(curPlayer, bossInfo)
|
return
|
|
|