hxp
2018-09-26 0a17e139006a7e19bc3a100fa394ad7d9b4bb716
3810 【后端】前期BOSS分线修改
13个文件已修改
446 ■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/ClearOpenServerDay.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -2317,8 +2317,9 @@
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):
@@ -2328,43 +2329,52 @@
    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
@@ -2900,6 +2910,7 @@
    RecordLen = 0    #(WORD RecordLen)// 长度
    KillRecord = ""    #(String KillRecord)// 最近击杀记录时间玩家名size = RecordLen
    RefreshSecond = 0    #(DWORD RefreshSecond)// 刷新倒计时, 秒    
    RefreshCD = 0    #(DWORD RefreshCD)// 刷新总CD时, 秒
    data = None
    def __init__(self):
@@ -2913,6 +2924,7 @@
        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):
@@ -2921,6 +2933,7 @@
        self.RecordLen = 0
        self.KillRecord = ""
        self.RefreshSecond = 0
        self.RefreshCD = 0
        return
    def GetLength(self):
@@ -2929,6 +2942,7 @@
        length += 1
        length += 2
        length += len(self.KillRecord)
        length += 4
        length += 4
        return length
@@ -2940,6 +2954,7 @@
        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):
@@ -2948,14 +2963,16 @@
                                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
@@ -22435,6 +22452,66 @@
#------------------------------------------------------
# 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):
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/ClearOpenServerDay.py
@@ -31,6 +31,7 @@
import PlayerUniversalGameRec
import GameWorldActionTeHui
import GameWorldProcess
import GameWorldBoss
import GMCommon
import time
@@ -100,6 +101,9 @@
    tick = GameWorld.GetGameWorld().GetTick()
    GMCommon.ActionControlRefresh(tick)
    
    # 广播分流boss状态
    GameWorldBoss.Sync_BossShuntLineInfo()
    if curPlayer:
        PlayerEventCounter.Sync_OpenServerDay(curPlayer)
        GameWorld.DebugAnswer(curPlayer, '开服星期%s, 天数:%s 是否合服:%s, 合服天数:%s'%\
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py
@@ -153,11 +153,8 @@
    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
@@ -165,17 +162,19 @@
    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):
@@ -188,26 +187,22 @@
        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
@@ -339,6 +334,7 @@
        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)
@@ -481,7 +477,7 @@
    __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]
@@ -814,10 +810,10 @@
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
@@ -872,16 +868,23 @@
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)
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -618,7 +618,7 @@
    
    # 世界boss状态
    if callName =="GameWorldBossState":
        GameWorldBoss.DoGameWorldBossOnReborn(eval(resultName), tick)
        GameWorldBoss.OnGameWorldBossStateChange(eval(resultName), tick)
        return
    
    # 仙盟归属boss信息同步
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
@@ -59,8 +59,8 @@
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, ...], ...}, ...}
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -188,7 +188,7 @@
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'   # 骑宠争夺活动有效参考人数
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -2317,8 +2317,9 @@
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):
@@ -2328,43 +2329,52 @@
    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
@@ -2900,6 +2910,7 @@
    RecordLen = 0    #(WORD RecordLen)// 长度
    KillRecord = ""    #(String KillRecord)// 最近击杀记录时间玩家名size = RecordLen
    RefreshSecond = 0    #(DWORD RefreshSecond)// 刷新倒计时, 秒    
    RefreshCD = 0    #(DWORD RefreshCD)// 刷新总CD时, 秒
    data = None
    def __init__(self):
@@ -2913,6 +2924,7 @@
        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):
@@ -2921,6 +2933,7 @@
        self.RecordLen = 0
        self.KillRecord = ""
        self.RefreshSecond = 0
        self.RefreshCD = 0
        return
    def GetLength(self):
@@ -2929,6 +2942,7 @@
        length += 1
        length += 2
        length += len(self.KillRecord)
        length += 4
        length += 4
        return length
@@ -2940,6 +2954,7 @@
        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):
@@ -2948,14 +2963,16 @@
                                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
@@ -22435,6 +22452,66 @@
#------------------------------------------------------
# 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):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
@@ -390,7 +390,7 @@
    
    gameFB = GameWorld.GetGameFB()
    gameWorldMgr = GameWorld.GetGameWorld()
    isActivityBoss = False
    isActivityBoss = False # 是否活动boss
    # 关联日常活动
    if relatedType == 1:
        actionKey = ShareDefine.Def_Notify_WorldKey_DailyActionState % relatedID
@@ -495,16 +495,18 @@
    '''分流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
#===================================================================================================
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -5547,4 +5547,17 @@
    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
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -87,6 +87,7 @@
import PlayerState
import QuestCommon
import PlayerDogz
import ChPlayer
import GMShell
import random
@@ -2026,8 +2027,12 @@
    #---同地图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
@@ -2063,7 +2068,7 @@
    # 非常规地图之间的切换不处理
    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)
@@ -2080,7 +2085,7 @@
            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)
@@ -2169,10 +2174,23 @@
    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()
@@ -2180,65 +2198,75 @@
    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
#---------------------------------------------------------------------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -1225,8 +1225,8 @@
            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:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -55,7 +55,7 @@
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 = {} # 延迟处理成就
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -188,7 +188,7 @@
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'   # 骑宠争夺活动有效参考人数