| | |
| | |
|
| | | class tagGCBossShuntLineState(Structure):
|
| | | BossID = 0 #(DWORD BossID)// bossID
|
| | | DeadLineCount = 0 #(BYTE DeadLineCount)
|
| | | DeadLineList = list() #(vector<BYTE> DeadLineList)// 已死亡的线路列表
|
| | | LineCount = 0 #(BYTE LineCount)
|
| | | LineIDList = list() #(vector<BYTE> LineIDList)// 线路ID列表
|
| | | StateList = list() #(vector<BYTE> StateList)// 对应状态列表, 0-被击杀,1-活着
|
| | | data = None
|
| | |
|
| | | def __init__(self):
|
| | |
| | | def ReadData(self, _lpData, _pos=0, _Len=0):
|
| | | self.Clear()
|
| | | self.BossID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
|
| | | self.DeadLineCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
|
| | | for i in range(self.DeadLineCount):
|
| | | self.LineCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
|
| | | for i in range(self.LineCount):
|
| | | value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
|
| | | self.DeadLineList.append(value)
|
| | | self.LineIDList.append(value)
|
| | | for i in range(self.LineCount):
|
| | | value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
|
| | | self.StateList.append(value)
|
| | | return _pos
|
| | |
|
| | | def Clear(self):
|
| | | self.BossID = 0
|
| | | self.DeadLineCount = 0
|
| | | self.DeadLineList = list()
|
| | | self.LineCount = 0
|
| | | self.LineIDList = list()
|
| | | self.StateList = list()
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | length = 0
|
| | | length += 4
|
| | | length += 1
|
| | | length += 1 * self.DeadLineCount
|
| | | length += 1 * self.LineCount
|
| | | length += 1 * self.LineCount
|
| | |
|
| | | return length
|
| | |
|
| | | def GetBuffer(self):
|
| | | data = ''
|
| | | data = CommFunc.WriteDWORD(data, self.BossID)
|
| | | data = CommFunc.WriteBYTE(data, self.DeadLineCount)
|
| | | for i in range(self.DeadLineCount):
|
| | | data = CommFunc.WriteBYTE(data, self.DeadLineList[i])
|
| | | data = CommFunc.WriteBYTE(data, self.LineCount)
|
| | | for i in range(self.LineCount):
|
| | | data = CommFunc.WriteBYTE(data, self.LineIDList[i])
|
| | | for i in range(self.LineCount):
|
| | | data = CommFunc.WriteBYTE(data, self.StateList[i])
|
| | | return data
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''
|
| | | BossID:%d,
|
| | | DeadLineCount:%d,
|
| | | DeadLineList:%s
|
| | | LineCount:%d,
|
| | | LineIDList:%s,
|
| | | StateList:%s
|
| | | '''\
|
| | | %(
|
| | | self.BossID,
|
| | | self.DeadLineCount,
|
| | | self.LineCount,
|
| | | "...",
|
| | | "..."
|
| | | )
|
| | | return DumpString
|
| | |
| | | RecordLen = 0 #(WORD RecordLen)// 长度
|
| | | KillRecord = "" #(String KillRecord)// 最近击杀记录时间玩家名size = RecordLen
|
| | | RefreshSecond = 0 #(DWORD RefreshSecond)// 刷新倒计时, 秒
|
| | | RefreshCD = 0 #(DWORD RefreshCD)// 刷新总CD时, 秒 |
| | | data = None
|
| | |
|
| | | def __init__(self):
|
| | |
| | | self.RecordLen,_pos = CommFunc.ReadWORD(_lpData, _pos)
|
| | | self.KillRecord,_pos = CommFunc.ReadString(_lpData, _pos,self.RecordLen)
|
| | | self.RefreshSecond,_pos = CommFunc.ReadDWORD(_lpData, _pos)
|
| | | self.RefreshCD,_pos = CommFunc.ReadDWORD(_lpData, _pos)
|
| | | return _pos
|
| | |
|
| | | def Clear(self):
|
| | |
| | | self.RecordLen = 0
|
| | | self.KillRecord = ""
|
| | | self.RefreshSecond = 0
|
| | | self.RefreshCD = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | |
| | | length += 1
|
| | | length += 2
|
| | | length += len(self.KillRecord)
|
| | | length += 4
|
| | | length += 4
|
| | |
|
| | | return length
|
| | |
| | | data = CommFunc.WriteWORD(data, self.RecordLen)
|
| | | data = CommFunc.WriteString(data, self.RecordLen, self.KillRecord)
|
| | | data = CommFunc.WriteDWORD(data, self.RefreshSecond)
|
| | | data = CommFunc.WriteDWORD(data, self.RefreshCD)
|
| | | return data
|
| | |
|
| | | def OutputString(self):
|
| | |
| | | IsAlive:%d,
|
| | | RecordLen:%d,
|
| | | KillRecord:%s,
|
| | | RefreshSecond:%d
|
| | | RefreshSecond:%d,
|
| | | RefreshCD:%d
|
| | | '''\
|
| | | %(
|
| | | self.BossID,
|
| | | self.IsAlive,
|
| | | self.RecordLen,
|
| | | self.KillRecord,
|
| | | self.RefreshSecond
|
| | | self.RefreshSecond,
|
| | | self.RefreshCD
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # B1 06 通知玩家向目标点移动 #tagMCNotifyPlayerMove
|
| | |
|
| | | class tagMCNotifyPlayerMove(Structure):
|
| | | _pack_ = 1
|
| | | _fields_ = [
|
| | | ("Cmd", c_ubyte),
|
| | | ("SubCmd", c_ubyte),
|
| | | ("PosX", c_int), |
| | | ("PosY", c_int), |
| | | ("NPCID", c_int), #目标点寻路NPCID, 可能为0
|
| | | ]
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | self.Cmd = 0xB1
|
| | | self.SubCmd = 0x06
|
| | | return
|
| | |
|
| | | def ReadData(self, stringData, _pos=0, _len=0):
|
| | | self.Clear()
|
| | | memmove(addressof(self), stringData[_pos:], self.GetLength())
|
| | | return _pos + self.GetLength()
|
| | |
|
| | | def Clear(self):
|
| | | self.Cmd = 0xB1
|
| | | self.SubCmd = 0x06
|
| | | self.PosX = 0
|
| | | self.PosY = 0
|
| | | self.NPCID = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | return sizeof(tagMCNotifyPlayerMove)
|
| | |
|
| | | def GetBuffer(self):
|
| | | return string_at(addressof(self), self.GetLength())
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''// B1 06 通知玩家向目标点移动 //tagMCNotifyPlayerMove:
|
| | | Cmd:%s,
|
| | | SubCmd:%s,
|
| | | PosX:%d,
|
| | | PosY:%d,
|
| | | NPCID:%d
|
| | | '''\
|
| | | %(
|
| | | self.Cmd,
|
| | | self.SubCmd,
|
| | | self.PosX,
|
| | | self.PosY,
|
| | | self.NPCID
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
|
| | | m_NAtagMCNotifyPlayerMove=tagMCNotifyPlayerMove()
|
| | | ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCNotifyPlayerMove.Cmd,m_NAtagMCNotifyPlayerMove.SubCmd))] = m_NAtagMCNotifyPlayerMove
|
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # B1 03 通知玩家死亡时间 #tagMCPlayerDeadTime
|
| | |
|
| | | class tagMCPlayerDeadTime(Structure):
|
| | |
| | | import PlayerUniversalGameRec
|
| | | import GameWorldActionTeHui
|
| | | import GameWorldProcess
|
| | | import GameWorldBoss
|
| | | import GMCommon
|
| | |
|
| | | import time
|
| | |
| | | tick = GameWorld.GetGameWorld().GetTick()
|
| | | GMCommon.ActionControlRefresh(tick)
|
| | |
|
| | | # 广播分流boss状态
|
| | | GameWorldBoss.Sync_BossShuntLineInfo()
|
| | | |
| | | if curPlayer:
|
| | | PlayerEventCounter.Sync_OpenServerDay(curPlayer)
|
| | | GameWorld.DebugAnswer(curPlayer, '开服星期%s, 天数:%s 是否合服:%s, 合服天数:%s'%\
|
| | |
| | | GameWorld.DebugLog(' PyGameData.g_sortBOSSRefreshList=%s'%PyGameData.g_sortBOSSRefreshList)
|
| | | return
|
| | |
|
| | | ## 世界boss重生
|
| | | # @param msgList 信息列表
|
| | | # @param tick 时间戳
|
| | | # @return None
|
| | | def DoGameWorldBossOnReborn(msgList, tick):
|
| | | def OnGameWorldBossStateChange(msgList, tick):
|
| | | ## 世界boss状态变更
|
| | | if len(msgList) <= 0:
|
| | | return
|
| | |
|
| | |
| | | isAlive = msgList[1]
|
| | | mapID = msgList[2] if len(msgList) > 2 else None
|
| | | lineID = msgList[3] if len(msgList) > 3 else None
|
| | | GameWorld.DebugLog("世界boss DoGameWorldBossOnReborn...mapID=%s,lineID=%s,bossID=%s,state=%s,tick=%s" % (mapID, lineID, bossID, isAlive, tick))
|
| | | GameWorld.Log("世界boss状态变更: mapID=%s,lineID=%s,bossID=%s,state=%s,tick=%s" % (mapID, lineID, bossID, isAlive, tick))
|
| | |
|
| | | if bossID <= 0:
|
| | | return
|
| | |
|
| | | bossShuntMapIDList = IpyGameDataPY.GetFuncEvalCfg("BossShunt")
|
| | | isBossShuntMap = mapID in bossShuntMapIDList
|
| | | isMapNeedShunt = IsMapNeedBossShunt(mapID)
|
| | | if not isAlive:
|
| | | DoRemoveBossShuntPlayerByNPCID(mapID, lineID, bossID)
|
| | |
|
| | | if isMapNeedShunt:
|
| | | __UpdBossLineState(bossID, lineID, isAlive)
|
| | | if isBossShuntMap:
|
| | | __UpdBossLineState(bossID, lineID, isAlive, isMapNeedShunt)
|
| | |
|
| | | #__GetBossRecDataByID(bossID) # 检查是否有该boss记录,没有的话创建新纪录
|
| | | if isAlive != __GetIsAlive(bossID):
|
| | |
| | | PyGameData.g_familyOwnerBossInfo.pop(bossID)
|
| | | return
|
| | |
|
| | |
|
| | | def __UpdBossLineState(bossID, lineID, isAlive):
|
| | | def __UpdBossLineState(bossID, lineID, isAlive, isMapNeedShunt):
|
| | | if lineID == None:
|
| | | return
|
| | | bossDeadLineList = PyGameData.g_bossShuntDeadLine.get(bossID, [])
|
| | | if isAlive and lineID in bossDeadLineList:
|
| | | bossDeadLineList.remove(lineID)
|
| | | elif not isAlive and lineID not in bossDeadLineList:
|
| | | bossDeadLineList.append(lineID)
|
| | | else:
|
| | | bossLineStateDict = PyGameData.g_bossShuntLineState.get(bossID, {})
|
| | | if bossLineStateDict.get(lineID) == isAlive:
|
| | | return
|
| | | bossLineStateDict[lineID] = isAlive
|
| | | PyGameData.g_bossShuntLineState[bossID] = bossLineStateDict
|
| | | # 为方便内网清除开服天测试,状态都更新
|
| | | |
| | | if not isMapNeedShunt:
|
| | | return
|
| | |
|
| | | PyGameData.g_bossShuntDeadLine[bossID] = bossDeadLineList
|
| | | if not bossDeadLineList:
|
| | | PyGameData.g_bossShuntDeadLine.pop(bossID)
|
| | | |
| | | if bossID not in PyGameData.g_bossShuntDeadLineChangeBoss:
|
| | | PyGameData.g_bossShuntDeadLineChangeBoss.append(bossID)
|
| | | #GameWorld.SendCommMapServerMsg(ShareDefine.Def_Notify_WorldKey_BossShuntDeadLine, PyGameData.g_bossShuntDeadLine)
|
| | | GameWorld.DebugLog(" boss已死亡线路变更: %s" % PyGameData.g_bossShuntDeadLine)
|
| | | if bossID not in PyGameData.g_bossShuntStateChangeBoss:
|
| | | PyGameData.g_bossShuntStateChangeBoss.append(bossID)
|
| | | GameWorld.Log(" 分流Boss线路状态变更: %s" % PyGameData.g_bossShuntLineState)
|
| | | return
|
| | |
|
| | |
|
| | |
| | | killedTime = universalRecData.GetValue2()
|
| | | refreshTime = __GetBossRefreshTime(bossInfoObj.BossID)
|
| | | bossInfoObj.RefreshSecond = max(0, refreshTime - (curTime - killedTime))
|
| | | bossInfoObj.RefreshCD = refreshTime
|
| | | #bossInfoObj.KilledCnt = __GetKilledCnt(universalRecData)
|
| | |
|
| | | bossInfo.BossInfoList.append(bossInfoObj)
|
| | |
| | | __SendMapServerAliveBoss()
|
| | | if IsMapNeedBossShunt(0):
|
| | | GameWorld.SendCommMapServerMsg(ShareDefine.Def_Notify_WorldKey_BossShuntPlayer, PyGameData.g_bossShuntPlayerInfo)
|
| | | GameWorld.SendCommMapServerMsg(ShareDefine.Def_Notify_WorldKey_BossShuntDeadLine, PyGameData.g_bossShuntDeadLine)
|
| | | GameWorld.SendCommMapServerMsg(ShareDefine.Def_Notify_WorldKey_BossShuntLineState, PyGameData.g_bossShuntLineState)
|
| | | #通知一个参数
|
| | | bossID = IpyGameDataPY.GetFuncCfg('DogzFBRefreshCfg', 2)
|
| | | onlineCnt = __GetBossOnlineHeroCnt(bossID)[0]
|
| | |
| | |
|
| | | def DoCheckWorldBossShuntInfo(curTime, tick):
|
| | | ## 定时检查boss分流信息数据
|
| | | if PyGameData.g_bossShuntDeadLineChangeBoss and curTime % 2 == 0:
|
| | | GameWorld.SendCommMapServerMsg(ShareDefine.Def_Notify_WorldKey_BossShuntDeadLine, PyGameData.g_bossShuntDeadLine)
|
| | | Sync_BossShuntLineInfo(None, PyGameData.g_bossShuntDeadLineChangeBoss)
|
| | | PyGameData.g_bossShuntDeadLineChangeBoss = []
|
| | | if PyGameData.g_bossShuntStateChangeBoss and curTime % 5 == 0:
|
| | | GameWorld.SendCommMapServerMsg(ShareDefine.Def_Notify_WorldKey_BossShuntLineState, PyGameData.g_bossShuntLineState)
|
| | | Sync_BossShuntLineInfo(None, PyGameData.g_bossShuntStateChangeBoss)
|
| | | PyGameData.g_bossShuntStateChangeBoss = []
|
| | |
|
| | | if curTime % 10 != 0:
|
| | | return
|
| | |
| | | def Sync_BossShuntLineInfo(curPlayer=None, syncBOSSIDList=[]):
|
| | |
|
| | | if not syncBOSSIDList:
|
| | | syncBOSSIDList = PyGameData.g_bossShuntDeadLine.keys()
|
| | | syncBOSSIDList = PyGameData.g_bossShuntLineState.keys()
|
| | |
|
| | | bossShuntLineInfo = ChPyNetSendPack.tagGCBossShuntLineStateInfo()
|
| | | bossShuntLineInfo.Clear()
|
| | | bossShuntLineInfo.BossLineStateInfo = []
|
| | | for bossID in syncBOSSIDList:
|
| | | bossLineStateDict = PyGameData.g_bossShuntLineState.get(bossID, {})
|
| | | lineIDList = []
|
| | | stateList = []
|
| | | for lineID, state in bossLineStateDict.items():
|
| | | lineIDList.append(lineID)
|
| | | stateList.append(state)
|
| | | bossLineState = ChPyNetSendPack.tagGCBossShuntLineState()
|
| | | bossLineState.BossID = bossID
|
| | | bossLineState.DeadLineList = PyGameData.g_bossShuntDeadLine.get(bossID, [])
|
| | | bossLineState.DeadLineCount = len(bossLineState.DeadLineList)
|
| | | bossLineState.LineIDList = lineIDList
|
| | | bossLineState.StateList = stateList
|
| | | bossLineState.LineCount = len(bossLineState.LineIDList)
|
| | | bossShuntLineInfo.BossLineStateInfo.append(bossLineState)
|
| | |
|
| | | bossShuntLineInfo.Count = len(bossShuntLineInfo.BossLineStateInfo)
|
| | |
| | |
|
| | | # 世界boss状态
|
| | | if callName =="GameWorldBossState":
|
| | | GameWorldBoss.DoGameWorldBossOnReborn(eval(resultName), tick)
|
| | | GameWorldBoss.OnGameWorldBossStateChange(eval(resultName), tick)
|
| | | return
|
| | |
|
| | | # 仙盟归属boss信息同步
|
| | |
| | | g_swrhJoinRecord = [] #守护人皇家族今日参加记录(已正常结算)[familyID]
|
| | |
|
| | | g_bossShuntPlayerInfo = {} # boss分流玩家信息{(mapID, lineID):{playerID:[bossID, teamID, relatedTick], ...}, ...}
|
| | | g_bossShuntDeadLine = {} # boss分流线路boss已死亡的线路 {bossID:[lineID, ...], ...}
|
| | | g_bossShuntDeadLineChangeBoss = [] # boss分流已死亡线路有变更的boss列表
|
| | | g_bossShuntLineState = {} # boss分流线路对应boss状态 {bossID:{lineID:isAlive, ...}, ...}
|
| | | g_bossShuntStateChangeBoss = [] # boss分流Boss线路状态有变更的boss列表
|
| | |
|
| | | g_familyOwnerBossInfo = {} # 地图同步上来的仙盟归属boss信息 {bossID:[curHp, maxHP, ownerFamilyID, ownerFamilyName], ...}
|
| | | g_horsePetRobBossHurtPlayerIDInfo = {} # 骑宠争夺有对boss伤血过的玩家ID信息 {bossID:{familyID:[playerID, ...], ...}, ...}
|
| | |
| | | Def_Notify_WorldKey_BossKilledCnt = 'BossKilledCnt_%s' # boss击杀次数, 参数为NPCID
|
| | | Def_Notify_WorldKey_GameWorldBossOnlineCnt = "GameWorldBossOnlineCnt_%s" #世界boss重生时间计算 在线人数统计 %s为bossid
|
| | | Def_Notify_WorldKey_BossShuntPlayer = 'BossShuntPlayer' # boss分流玩家信息
|
| | | Def_Notify_WorldKey_BossShuntDeadLine = 'BossShuntDeadLine' # boss分流线路已死亡的线路
|
| | | Def_Notify_WorldKey_BossShuntLineState = 'BossShuntLineState' # boss分流线路对应boss状态
|
| | | Def_Notify_WorldKey_BossOnlineHeroCnt = 'BossOnlineHeroCnt_%s' # boss刷新时间用的在线人数, 参数为NPCID
|
| | | Def_Notify_WorldKey_FamilyKillHorsePetRobBossCnt = 'FamilyKillHorsePetRobBossCnt' # 仙盟击杀骑宠boss数统计
|
| | | Def_Notify_WorldKey_HorsePetRobBossPlayerCount = 'HorsePetRobBossPlayerCount' # 骑宠争夺活动有效参考人数
|
| | |
| | |
|
| | | class tagGCBossShuntLineState(Structure):
|
| | | BossID = 0 #(DWORD BossID)// bossID
|
| | | DeadLineCount = 0 #(BYTE DeadLineCount)
|
| | | DeadLineList = list() #(vector<BYTE> DeadLineList)// 已死亡的线路列表
|
| | | LineCount = 0 #(BYTE LineCount)
|
| | | LineIDList = list() #(vector<BYTE> LineIDList)// 线路ID列表
|
| | | StateList = list() #(vector<BYTE> StateList)// 对应状态列表, 0-被击杀,1-活着
|
| | | data = None
|
| | |
|
| | | def __init__(self):
|
| | |
| | | def ReadData(self, _lpData, _pos=0, _Len=0):
|
| | | self.Clear()
|
| | | self.BossID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
|
| | | self.DeadLineCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
|
| | | for i in range(self.DeadLineCount):
|
| | | self.LineCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
|
| | | for i in range(self.LineCount):
|
| | | value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
|
| | | self.DeadLineList.append(value)
|
| | | self.LineIDList.append(value)
|
| | | for i in range(self.LineCount):
|
| | | value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
|
| | | self.StateList.append(value)
|
| | | return _pos
|
| | |
|
| | | def Clear(self):
|
| | | self.BossID = 0
|
| | | self.DeadLineCount = 0
|
| | | self.DeadLineList = list()
|
| | | self.LineCount = 0
|
| | | self.LineIDList = list()
|
| | | self.StateList = list()
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | length = 0
|
| | | length += 4
|
| | | length += 1
|
| | | length += 1 * self.DeadLineCount
|
| | | length += 1 * self.LineCount
|
| | | length += 1 * self.LineCount
|
| | |
|
| | | return length
|
| | |
|
| | | def GetBuffer(self):
|
| | | data = ''
|
| | | data = CommFunc.WriteDWORD(data, self.BossID)
|
| | | data = CommFunc.WriteBYTE(data, self.DeadLineCount)
|
| | | for i in range(self.DeadLineCount):
|
| | | data = CommFunc.WriteBYTE(data, self.DeadLineList[i])
|
| | | data = CommFunc.WriteBYTE(data, self.LineCount)
|
| | | for i in range(self.LineCount):
|
| | | data = CommFunc.WriteBYTE(data, self.LineIDList[i])
|
| | | for i in range(self.LineCount):
|
| | | data = CommFunc.WriteBYTE(data, self.StateList[i])
|
| | | return data
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''
|
| | | BossID:%d,
|
| | | DeadLineCount:%d,
|
| | | DeadLineList:%s
|
| | | LineCount:%d,
|
| | | LineIDList:%s,
|
| | | StateList:%s
|
| | | '''\
|
| | | %(
|
| | | self.BossID,
|
| | | self.DeadLineCount,
|
| | | self.LineCount,
|
| | | "...",
|
| | | "..."
|
| | | )
|
| | | return DumpString
|
| | |
| | | RecordLen = 0 #(WORD RecordLen)// 长度
|
| | | KillRecord = "" #(String KillRecord)// 最近击杀记录时间玩家名size = RecordLen
|
| | | RefreshSecond = 0 #(DWORD RefreshSecond)// 刷新倒计时, 秒
|
| | | RefreshCD = 0 #(DWORD RefreshCD)// 刷新总CD时, 秒 |
| | | data = None
|
| | |
|
| | | def __init__(self):
|
| | |
| | | self.RecordLen,_pos = CommFunc.ReadWORD(_lpData, _pos)
|
| | | self.KillRecord,_pos = CommFunc.ReadString(_lpData, _pos,self.RecordLen)
|
| | | self.RefreshSecond,_pos = CommFunc.ReadDWORD(_lpData, _pos)
|
| | | self.RefreshCD,_pos = CommFunc.ReadDWORD(_lpData, _pos)
|
| | | return _pos
|
| | |
|
| | | def Clear(self):
|
| | |
| | | self.RecordLen = 0
|
| | | self.KillRecord = ""
|
| | | self.RefreshSecond = 0
|
| | | self.RefreshCD = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | |
| | | length += 1
|
| | | length += 2
|
| | | length += len(self.KillRecord)
|
| | | length += 4
|
| | | length += 4
|
| | |
|
| | | return length
|
| | |
| | | data = CommFunc.WriteWORD(data, self.RecordLen)
|
| | | data = CommFunc.WriteString(data, self.RecordLen, self.KillRecord)
|
| | | data = CommFunc.WriteDWORD(data, self.RefreshSecond)
|
| | | data = CommFunc.WriteDWORD(data, self.RefreshCD)
|
| | | return data
|
| | |
|
| | | def OutputString(self):
|
| | |
| | | IsAlive:%d,
|
| | | RecordLen:%d,
|
| | | KillRecord:%s,
|
| | | RefreshSecond:%d
|
| | | RefreshSecond:%d,
|
| | | RefreshCD:%d
|
| | | '''\
|
| | | %(
|
| | | self.BossID,
|
| | | self.IsAlive,
|
| | | self.RecordLen,
|
| | | self.KillRecord,
|
| | | self.RefreshSecond
|
| | | self.RefreshSecond,
|
| | | self.RefreshCD
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # B1 06 通知玩家向目标点移动 #tagMCNotifyPlayerMove
|
| | |
|
| | | class tagMCNotifyPlayerMove(Structure):
|
| | | _pack_ = 1
|
| | | _fields_ = [
|
| | | ("Cmd", c_ubyte),
|
| | | ("SubCmd", c_ubyte),
|
| | | ("PosX", c_int), |
| | | ("PosY", c_int), |
| | | ("NPCID", c_int), #目标点寻路NPCID, 可能为0
|
| | | ]
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | self.Cmd = 0xB1
|
| | | self.SubCmd = 0x06
|
| | | return
|
| | |
|
| | | def ReadData(self, stringData, _pos=0, _len=0):
|
| | | self.Clear()
|
| | | memmove(addressof(self), stringData[_pos:], self.GetLength())
|
| | | return _pos + self.GetLength()
|
| | |
|
| | | def Clear(self):
|
| | | self.Cmd = 0xB1
|
| | | self.SubCmd = 0x06
|
| | | self.PosX = 0
|
| | | self.PosY = 0
|
| | | self.NPCID = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | return sizeof(tagMCNotifyPlayerMove)
|
| | |
|
| | | def GetBuffer(self):
|
| | | return string_at(addressof(self), self.GetLength())
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''// B1 06 通知玩家向目标点移动 //tagMCNotifyPlayerMove:
|
| | | Cmd:%s,
|
| | | SubCmd:%s,
|
| | | PosX:%d,
|
| | | PosY:%d,
|
| | | NPCID:%d
|
| | | '''\
|
| | | %(
|
| | | self.Cmd,
|
| | | self.SubCmd,
|
| | | self.PosX,
|
| | | self.PosY,
|
| | | self.NPCID
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
|
| | | m_NAtagMCNotifyPlayerMove=tagMCNotifyPlayerMove()
|
| | | ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCNotifyPlayerMove.Cmd,m_NAtagMCNotifyPlayerMove.SubCmd))] = m_NAtagMCNotifyPlayerMove
|
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # B1 03 通知玩家死亡时间 #tagMCPlayerDeadTime
|
| | |
|
| | | class tagMCPlayerDeadTime(Structure):
|
| | |
| | |
|
| | | gameFB = GameWorld.GetGameFB()
|
| | | gameWorldMgr = GameWorld.GetGameWorld()
|
| | | isActivityBoss = False
|
| | | isActivityBoss = False # 是否活动boss
|
| | | # 关联日常活动
|
| | | if relatedType == 1:
|
| | | actionKey = ShareDefine.Def_Notify_WorldKey_DailyActionState % relatedID
|
| | |
| | | '''分流boss是否需要处理
|
| | | 无伤血、仇恨、没人看到他、他没看到别人
|
| | | '''
|
| | | if curNPC.GetPlayerHurtList().GetHurtCount():
|
| | | #GameWorld.DebugLog("分流boss有伤血,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
|
| | | return True
|
| | | |
| | | if curNPC.GetAttentionPlayersCount() or curNPC.GetInSightObjCount():
|
| | | #GameWorld.DebugLog("分流boss有人看到,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
|
| | | return True
|
| | | |
| | | GameWorld.DebugLog("分流boss不需要处理了,可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
|
| | | return False
|
| | | # 策划暂时修改分流boss不同步死亡
|
| | | return True
|
| | | # if curNPC.GetPlayerHurtList().GetHurtCount():
|
| | | # #GameWorld.DebugLog("分流boss有伤血,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
|
| | | # return True
|
| | | # |
| | | # if curNPC.GetAttentionPlayersCount() or curNPC.GetInSightObjCount():
|
| | | # #GameWorld.DebugLog("分流boss有人看到,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
|
| | | # return True
|
| | | # |
| | | # GameWorld.DebugLog("分流boss不需要处理了,可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
|
| | | # return False
|
| | |
|
| | | #===================================================================================================
|
| | |
|
| | |
| | | sendPack.Clear()
|
| | | sendPack.Record = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_DownloadAwardState)
|
| | | NetPackCommon.SendFakePack(curPlayer, sendPack)
|
| | | return |
| | | return
|
| | |
|
| | | def NotifyPlayerMove(curPlayer, posX, posY, npcID=0):
|
| | | '''通知前端向某个点移动
|
| | | 这里前端可能需要针对某次移动做额外处理,比如移动到某个点后需要自动战斗等
|
| | | 所以这里只做通知前端可以向某个点移动,最终移动由前端发起
|
| | | '''
|
| | | sendPack = ChPyNetSendPack.tagMCNotifyPlayerMove()
|
| | | sendPack.Clear()
|
| | | sendPack.PosX = posX
|
| | | sendPack.PosY = posY
|
| | | sendPack.NPCID = npcID
|
| | | NetPackCommon.SendFakePack(curPlayer, sendPack)
|
| | | return
|
| | |
| | | import PlayerState
|
| | | import QuestCommon
|
| | | import PlayerDogz
|
| | | import ChPlayer
|
| | | import GMShell
|
| | |
|
| | | import random
|
| | |
| | | #---同地图ID, 同分线, 仅切换坐标---
|
| | | #lingID = -1, 代表默认当前线, 如主城2传送剑宗, 到达剑宗2
|
| | | if gameWorld.GetMapID() == mapID and (shuntLineID == -1 or gameWorld.GetLineID() == shuntLineID):
|
| | | #重置坐标
|
| | | GameWorld.ResetPlayerPos(curPlayer, posX, posY)
|
| | | if exData1:
|
| | | #boss的用move,通知前端,由前端发起move
|
| | | ChPlayer.NotifyPlayerMove(curPlayer, posX, posY, exData1)
|
| | | else:
|
| | | #重置坐标
|
| | | GameWorld.ResetPlayerPos(curPlayer, posX, posY)
|
| | | #@bug: 在摆摊区快速传送至非摆摊区, 可以摆摊, 这里刷新一下场景Buff
|
| | | SkillShell.ProcessMapBuff(curPlayer, GameWorld.GetGameWorld().GetTick())
|
| | | return
|
| | |
| | | # 非常规地图之间的切换不处理
|
| | | if curMapID not in PyGameData.g_commMapLinePlayerCountDict or tagMapID not in PyGameData.g_commMapLinePlayerCountDict:
|
| | | return tagLineID
|
| | | tagLinePlayerCountDict = PyGameData.g_commMapLinePlayerCountDict[tagMapID]
|
| | | tagLinePlayerCountDict = PyGameData.g_commMapLinePlayerCountDict[tagMapID] # 此分线包含所有分线,含未开放的及活动分线
|
| | |
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | playChangeLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_PlayChangeLineID)
|
| | |
| | | GameWorld.DebugLog("功能指定切换目标线路,记录当前线路后续切线备用! curLineID=%s,tagLineID=%s" % (curLineID, tagLineID), playerID)
|
| | |
|
| | | if bossID and NPCCommon.IsMapNeedBossShunt(tagMapID):
|
| | | bossShuntLineID = __GetBossShuntLineID(curPlayer, tagMapID, bossID, tagLinePlayerCountDict.keys())
|
| | | bossShuntLineID = __GetBossShuntLineID(curPlayer, curMapID, curLineID, tagMapID, bossID, tagLinePlayerCountDict.keys())
|
| | | if bossShuntLineID != -1:
|
| | | tick = GameWorld.GetGameWorld().GetTick()
|
| | | GameWorld.DebugLog("分流boss, bossID=%s,bossShuntLineID=%s" % (bossID, bossShuntLineID), playerID)
|
| | |
| | | GameWorld.DebugLog("分流到人数较少的线路,tagMapID=%s,linePlayerList[count,lineID]=%s" % (tagMapID, linePlayerList), playerID)
|
| | | return shuntLineID
|
| | |
|
| | | def __GetBossShuntLineID(curPlayer, mapID, npcID, lineIDList):
|
| | | def __GetBossShuntLineID(curPlayer, curMapID, curLineID, tagMapID, npcID, lineIDList):
|
| | | '''获取目标地图boss分流线路
|
| | | 根据人数分流玩家,boss死亡状态,只能分流到已死亡线路
|
| | | 队伍无视任何规则,默认分配到队伍队员多的那条线
|
| | | 根据人数分流玩家,优先分配到活着的线路
|
| | | 队伍无视任何规则,默认分配到队伍队员多的那条线
|
| | | |
| | | 前端:
|
| | | 1.在中立地图的时候,显示当前线路BOSS的状态
|
| | | 2.在常规地图的时候,显示玩家击杀BOSS的CD时间
|
| | | 3.本地图不换线,60秒规则保持不变
|
| | | 4.进入BOSS区域里,刷新BOSS状态
|
| | | |
| | | 玩家在非中立地图:
|
| | | 本地图不换线,60秒规则保持不变()
|
| | | |
| | | 玩家在中立地图
|
| | | 没有60秒规则
|
| | | 直接发传送包,由后端决定(有队员在不同线路打同一只boss,则传送,否则move)
|
| | | '''
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | playerTeamID = curPlayer.GetTeamID()
|
| | |
| | | hurtTeamLineID = -1
|
| | | hurtTeamMemCount = -1
|
| | |
|
| | | emptyLineID = -1
|
| | | bossLinePlayerCntList = []
|
| | | bossLinePlayerDict = {1:[-1, []], 0:[-1, []]} # {是否被击杀:[该状态人数空的线路, [[玩家数, 线路], ...]], ...}
|
| | |
|
| | | deadLineList = PyGameData.g_bossShuntDeadLine.get(npcID, [])
|
| | | bossState = not deadLineList # boss公共状态, 只要有一条线路是死亡的就是死亡
|
| | | bossLineStateDict = PyGameData.g_bossShuntLineState.get(npcID, {})
|
| | |
|
| | | GameWorld.DebugLog("玩家boss分流: playerTeamID=%s,mapID=%s,npcID=%s,lineIDList=%s,bossState=%s,deadLineList=%s,g_bossShuntPlayerInfo=%s" |
| | | % (playerTeamID, mapID, npcID, lineIDList, bossState, deadLineList, PyGameData.g_bossShuntPlayerInfo), playerID)
|
| | | haveAliveLine = False # 是否有活着的线路
|
| | | activityMapLineDict = IpyGameDataPY.GetFuncEvalCfg("MapLine", 2, {})
|
| | |
|
| | | GameWorld.DebugLog("玩家boss分流: playerTeamID=%s,tagMapID=%s,npcID=%s,lineIDList=%s,bossLineStateDict=%s,g_bossShuntPlayerInfo=%s" |
| | | % (playerTeamID, tagMapID, npcID, lineIDList, bossLineStateDict, PyGameData.g_bossShuntPlayerInfo), playerID)
|
| | | if tagMapID in activityMapLineDict:
|
| | | activityLineID = max(0, activityMapLineDict[tagMapID] - 1)
|
| | | # 非1线的活动线路不参与分流
|
| | | if activityLineID != 0 and activityLineID in lineIDList:
|
| | | lineIDList.remove(activityLineID)
|
| | | GameWorld.DebugLog(" 非1线的活动线路不参与分流: activityLineID=%s,lineIDList=%s" % (activityLineID, lineIDList), playerID)
|
| | | |
| | | for lineID in lineIDList:
|
| | | key = (mapID, lineID)
|
| | | key = (tagMapID, lineID)
|
| | | # boss分流玩家信息{(mapID, lineID):{playerID:[bossID, teamID, relatedTick], ...}, ...}
|
| | | shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})
|
| | | playerCount = 0
|
| | | teamPlayerCount = 0
|
| | | for shuntInfo in shuntPlayerDict.values():
|
| | | for shuntPlayerID, shuntInfo in shuntPlayerDict.items():
|
| | | bossID = shuntInfo[0]
|
| | | if npcID != bossID:
|
| | | continue
|
| | | playerCount += 1
|
| | | shuntTeamID = shuntInfo[1]
|
| | | if playerTeamID and playerTeamID == shuntTeamID:
|
| | | if playerTeamID and playerTeamID == shuntTeamID and shuntPlayerID != playerID:
|
| | | teamPlayerCount += 1
|
| | |
|
| | | if teamPlayerCount and teamPlayerCount > hurtTeamMemCount:
|
| | | hurtTeamMemCount = teamPlayerCount
|
| | | hurtTeamLineID = lineID
|
| | |
|
| | | lineBossState = lineID not in deadLineList # 当前线路boss状态
|
| | | if bossState != lineBossState:
|
| | | GameWorld.DebugLog(" lineID=%s,lineBossState=%s != bossState=%s,teamPlayerCount=%s,hurtTeamMemCount=%s,hurtTeamLineID=%s" |
| | | % (lineID, lineBossState, bossState, teamPlayerCount, hurtTeamMemCount, hurtTeamLineID), playerID)
|
| | | continue
|
| | | lineIsAlive = bossLineStateDict.get(lineID, 0)
|
| | | lineBossIsDead = 1 if not lineIsAlive else 0 # 当前线路boss是否死亡
|
| | | emptyLineID, linePlayerCountList = bossLinePlayerDict[lineBossIsDead]
|
| | | if not playerCount and emptyLineID == -1:
|
| | | emptyLineID = lineID
|
| | | linePlayerCountList.append([playerCount, lineID])
|
| | | bossLinePlayerDict[lineBossIsDead] = [emptyLineID, linePlayerCountList]
|
| | |
|
| | | GameWorld.DebugLog(" lineID=%s,lineBossState=%s,playerCount=%s,teamPlayerCount=%s,hurtTeamMemCount=%s,hurtTeamLineID=%s" |
| | | % (lineID, lineBossState, playerCount, teamPlayerCount, hurtTeamMemCount, hurtTeamLineID), playerID)
|
| | | |
| | | if not playerCount:
|
| | | if emptyLineID < 0:
|
| | | emptyLineID = lineID
|
| | | else:
|
| | | bossLinePlayerCntList.append([playerCount, lineID])
|
| | | if not lineBossIsDead:
|
| | | haveAliveLine = True
|
| | |
|
| | | GameWorld.DebugLog(" lineID=%s,lineBossIsDead=%s,playerCount=%s,teamPlayerCount=%s,hurtTeamMemCount=%s,hurtTeamLineID=%s" |
| | | % (lineID, lineBossIsDead, playerCount, teamPlayerCount, hurtTeamMemCount, hurtTeamLineID), playerID)
|
| | | |
| | | if hurtTeamLineID >= 0:
|
| | | GameWorld.DebugLog(" 分流到队友人数多的线路 hurtTeamLineID=%s" % hurtTeamLineID, playerID)
|
| | | return hurtTeamLineID
|
| | |
|
| | | if not bossLinePlayerCntList:
|
| | | GameWorld.DebugLog(" 没有人在该boss状态下的线路,默认空新线路!bossState=%s,emptyLineID=%s" % (bossState, emptyLineID), playerID)
|
| | | return emptyLineID
|
| | | if curMapID == tagMapID and curMapID in IpyGameDataPY.GetFuncEvalCfg("MapLine", 4):
|
| | | GameWorld.DebugLog(" 中立地图在本地图中默认当前线路 curLineID=%s" % curLineID, playerID)
|
| | | return curLineID
|
| | |
|
| | | bossLinePlayerCntList.sort() # 升序
|
| | | playerCount, minPlayerCntLineID = bossLinePlayerCntList[0]
|
| | | shuntBossIsDead = 0 if haveAliveLine else 1 # 优先分流到活着的线路
|
| | | GameWorld.DebugLog(" boss状态对应线路人数: haveAliveLine=%s, 状态key0为活着: %s" % (haveAliveLine, bossLinePlayerDict))
|
| | | emptyLineID, linePlayerCountList = bossLinePlayerDict[shuntBossIsDead]
|
| | | linePlayerCountList.sort() # 升序
|
| | | playerCount, minPlayerCntLineID = linePlayerCountList[0]
|
| | | bossShuntPlayerCountMax = IpyGameDataPY.GetFuncCfg("BossShunt", 2)
|
| | | if playerCount >= bossShuntPlayerCountMax and emptyLineID >= 0:
|
| | | GameWorld.DebugLog(" 分流到空新线路 bossState=%s,emptyLineID=%s" % (bossState, emptyLineID), playerID)
|
| | | GameWorld.DebugLog(" 分流到空新线路 shuntBossIsDead=%s,emptyLineID=%s" % (shuntBossIsDead, emptyLineID), playerID)
|
| | | return emptyLineID
|
| | |
|
| | | GameWorld.DebugLog(" 分流到人数最少的线路 bossState=%s,minPlayerCntLineID=%s,bossLinePlayerCntList=%s" |
| | | % (bossState, minPlayerCntLineID, bossLinePlayerCntList), playerID)
|
| | | GameWorld.DebugLog(" 分流到人数最少的线路 shuntBossIsDead=%s,minPlayerCntLineID=%s,linePlayerCountList=%s" |
| | | % (shuntBossIsDead, minPlayerCntLineID, linePlayerCountList), playerID)
|
| | | return minPlayerCntLineID
|
| | |
|
| | | #---------------------------------------------------------------------
|
| | |
| | | PyGameData.g_bossShuntPlayerInfo = eval(msgValue)
|
| | | return
|
| | |
|
| | | if key == ShareDefine.Def_Notify_WorldKey_BossShuntDeadLine:
|
| | | PyGameData.g_bossShuntDeadLine = eval(msgValue)
|
| | | if key == ShareDefine.Def_Notify_WorldKey_BossShuntLineState:
|
| | | PyGameData.g_bossShuntLineState = eval(msgValue)
|
| | | return
|
| | |
|
| | | if key == ShareDefine.Def_Notify_WorldKey_FamilyKillHorsePetRobBossCnt:
|
| | |
| | | g_fbPickUpItemDict = {} #副本玩家拾取物品记录 {playerID:[]}
|
| | |
|
| | | g_bossShuntPlayerInfo = {} # boss分流玩家信息{(mapID, lineID):{playerID:[bossID, teamID, relatedTick], ...}, ...}
|
| | | g_bossShuntDeadLine = {} # boss分流线路boss已死亡的线路 {bossID:[lineID, ...], ...}
|
| | | g_bossShuntLineState = {} # boss分流线路对应boss状态 {bossID:{lineID:isAlive, ...}, ...}
|
| | |
|
| | | g_delaySuccessDict = {} # 延迟处理成就
|
| | |
|
| | |
| | | Def_Notify_WorldKey_BossKilledCnt = 'BossKilledCnt_%s' # boss击杀次数, 参数为NPCID
|
| | | Def_Notify_WorldKey_GameWorldBossOnlineCnt = "GameWorldBossOnlineCnt_%s" #世界boss重生时间计算 在线人数统计 %s为bossid
|
| | | Def_Notify_WorldKey_BossShuntPlayer = 'BossShuntPlayer' # boss分流玩家信息
|
| | | Def_Notify_WorldKey_BossShuntDeadLine = 'BossShuntDeadLine' # boss分流线路已死亡的线路
|
| | | Def_Notify_WorldKey_BossShuntLineState = 'BossShuntLineState' # boss分流线路对应boss状态
|
| | | Def_Notify_WorldKey_BossOnlineHeroCnt = 'BossOnlineHeroCnt_%s' # boss刷新时间用的在线人数, 参数为NPCID
|
| | | Def_Notify_WorldKey_FamilyKillHorsePetRobBossCnt = 'FamilyKillHorsePetRobBossCnt' # 仙盟击杀骑宠boss数统计
|
| | | Def_Notify_WorldKey_HorsePetRobBossPlayerCount = 'HorsePetRobBossPlayerCount' # 骑宠争夺活动有效参考人数
|