hxp
2018-08-29 9f13daf65e0f6acc43ffab6462b737a70879f5cc
Add: 2961 【后端】仙盟抢Boss活动;
25个文件已修改
1个文件已添加
1877 ■■■■■ 已修改文件
PySysDB/PySysDBPY.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Boss.py 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/KillScreenNPC.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FamilyRobBoss.py 555 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -848,6 +848,9 @@
    DWORD        _NPCID;    //ID
    DWORD        MapID;    //地图ID
    BYTE        RefreshMark;    //刷新标识点
    BYTE        IsNeedShunt;    //是否需要分流
    BYTE        RelatedType;    //刷怪关联类型
    WORD        RelatedID;    //关联ID
    DWORD        StoneNPCID;    //墓碑NPCID
};
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -319,12 +319,16 @@
Writer = xdh
Releaser = xdh
RegType = 0
RegisterPackCount = 1
RegisterPackCount = 2
PacketCMD_1=0xA9
PacketSubCMD_1=0x03
PacketCallFunc_1=OnAttentionBoss
PacketCMD_2=0xAC
PacketSubCMD_2=0x04
PacketCallFunc_2=OnQueryAllFamilyBossHurt
[PlayerXMZZ]
ScriptName = Player\PlayerXMZZ.py
Writer = xdh
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -1485,6 +1485,54 @@
#------------------------------------------------------
# AC 04 查询仙盟抢Boss所有Boss当前进度 #tagCGQueryAllFamilyBossHurt
class  tagCGQueryAllFamilyBossHurt(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xAC
        self.SubCmd = 0x04
        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 = 0xAC
        self.SubCmd = 0x04
        return
    def GetLength(self):
        return sizeof(tagCGQueryAllFamilyBossHurt)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AC 04 查询仙盟抢Boss所有Boss当前进度 //tagCGQueryAllFamilyBossHurt:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCGQueryAllFamilyBossHurt=tagCGQueryAllFamilyBossHurt()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGQueryAllFamilyBossHurt.Cmd,m_NAtagCGQueryAllFamilyBossHurt.SubCmd))] = m_NAtagCGQueryAllFamilyBossHurt
#------------------------------------------------------
# AC 03 仙魔之争信息查询 #tagCGXMZZInfoQuery
class  tagCGXMZZInfoQuery(Structure):
@@ -4012,6 +4060,66 @@
#------------------------------------------------------
# A2 28 查询仙盟抢Boss伤血列表 #tagCMQueryFamilyBossHurt
class  tagCMQueryFamilyBossHurt(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ObjID", c_int),
                  ("NPCID", c_int),
                  ("QueryType", c_ubyte),    # 0-实时仙盟伤血,1-历史仙盟伤血,2-实时玩家伤血,3-历史玩家伤血
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA2
        self.SubCmd = 0x28
        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 = 0xA2
        self.SubCmd = 0x28
        self.ObjID = 0
        self.NPCID = 0
        self.QueryType = 0
        return
    def GetLength(self):
        return sizeof(tagCMQueryFamilyBossHurt)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A2 28 查询仙盟抢Boss伤血列表 //tagCMQueryFamilyBossHurt:
                                Cmd:%s,
                                SubCmd:%s,
                                ObjID:%d,
                                NPCID:%d,
                                QueryType:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ObjID,
                                self.NPCID,
                                self.QueryType
                                )
        return DumpString
m_NAtagCMQueryFamilyBossHurt=tagCMQueryFamilyBossHurt()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMQueryFamilyBossHurt.Cmd,m_NAtagCMQueryFamilyBossHurt.SubCmd))] = m_NAtagCMQueryFamilyBossHurt
#------------------------------------------------------
# A2 27 查询地图NPC数量信息 #tagCMQueryNPCCntInfo
class  tagCMQueryNPCCntInfo(Structure):
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -4237,6 +4237,162 @@
#------------------------------------------------------
# AC 10 仙盟抢Boss所有Boss伤血进度信息 #tagGCAllFamilyBossHurtInfoList
class  tagGCFamilyBossHurtInfo(Structure):
    NPCID = 0    #(DWORD NPCID)
    CurHP = 0    #(DWORD CurHP)
    CurHPEx = 0    #(DWORD CurHPEx)
    MaxHP = 0    #(DWORD MaxHP)
    MaxHPEx = 0    #(DWORD MaxHPEx)
    FamilyID = 0    #(DWORD FamilyID)// 最大实时伤血仙盟
    NameLen = 0    #(BYTE NameLen)
    FamilyName = ""    #(String FamilyName)
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.NPCID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.CurHP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.CurHPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MaxHP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MaxHPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.FamilyName,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
        return _pos
    def Clear(self):
        self.NPCID = 0
        self.CurHP = 0
        self.CurHPEx = 0
        self.MaxHP = 0
        self.MaxHPEx = 0
        self.FamilyID = 0
        self.NameLen = 0
        self.FamilyName = ""
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 1
        length += len(self.FamilyName)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.NPCID)
        data = CommFunc.WriteDWORD(data, self.CurHP)
        data = CommFunc.WriteDWORD(data, self.CurHPEx)
        data = CommFunc.WriteDWORD(data, self.MaxHP)
        data = CommFunc.WriteDWORD(data, self.MaxHPEx)
        data = CommFunc.WriteDWORD(data, self.FamilyID)
        data = CommFunc.WriteBYTE(data, self.NameLen)
        data = CommFunc.WriteString(data, self.NameLen, self.FamilyName)
        return data
    def OutputString(self):
        DumpString = '''
                                NPCID:%d,
                                CurHP:%d,
                                CurHPEx:%d,
                                MaxHP:%d,
                                MaxHPEx:%d,
                                FamilyID:%d,
                                NameLen:%d,
                                FamilyName:%s
                                '''\
                                %(
                                self.NPCID,
                                self.CurHP,
                                self.CurHPEx,
                                self.MaxHP,
                                self.MaxHPEx,
                                self.FamilyID,
                                self.NameLen,
                                self.FamilyName
                                )
        return DumpString
class  tagGCAllFamilyBossHurtInfoList(Structure):
    Head = tagHead()
    NPCCount = 0    #(BYTE NPCCount)// 个数
    NPCHurtInfo = list()    #(vector<tagGCFamilyBossHurtInfo> NPCHurtInfo)// NPC伤血信息列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xAC
        self.Head.SubCmd = 0x10
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.NPCCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.NPCCount):
            temNPCHurtInfo = tagGCFamilyBossHurtInfo()
            _pos = temNPCHurtInfo.ReadData(_lpData, _pos)
            self.NPCHurtInfo.append(temNPCHurtInfo)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xAC
        self.Head.SubCmd = 0x10
        self.NPCCount = 0
        self.NPCHurtInfo = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        for i in range(self.NPCCount):
            length += self.NPCHurtInfo[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.NPCCount)
        for i in range(self.NPCCount):
            data = CommFunc.WriteString(data, self.NPCHurtInfo[i].GetLength(), self.NPCHurtInfo[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                NPCCount:%d,
                                NPCHurtInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.NPCCount,
                                "..."
                                )
        return DumpString
m_NAtagGCAllFamilyBossHurtInfoList=tagGCAllFamilyBossHurtInfoList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCAllFamilyBossHurtInfoList.Head.Cmd,m_NAtagGCAllFamilyBossHurtInfoList.Head.SubCmd))] = m_NAtagGCAllFamilyBossHurtInfoList
#------------------------------------------------------
# AC 08 boss复活点数通知 #tagGCBossRebornPoint
class  tagGCBossRebornPoint(Structure):
@@ -16349,6 +16505,183 @@
#------------------------------------------------------
# A7 15 通知仙盟抢Boss伤血信息 #tagMCFamilyBossHurtList
class  tagMCFamilyBossHurt(Structure):
    FamilyID = 0    #(DWORD FamilyID)// 所属仙盟ID
    HurtID = 0    #(DWORD HurtID)// 伤血的ID, 根据伤血类型表示不同的ID, 如仙盟ID或玩家ID
    NameLen = 0    #(BYTE NameLen)
    HurtName = ""    #(String HurtName)
    HurtValue = 0    #(DWORD HurtValue)// 累计伤血,求余1亿的值
    HurtValueEx = 0    #(DWORD HurtValueEx)// 累计伤血,整除1亿的值
    InitTick = 0    #(DWORD InitTick)// 伤血初始tick,用于排序,先按伤血倒序排,再按tick正序排
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.HurtID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.HurtName,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
        self.HurtValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.HurtValueEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.InitTick,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        return _pos
    def Clear(self):
        self.FamilyID = 0
        self.HurtID = 0
        self.NameLen = 0
        self.HurtName = ""
        self.HurtValue = 0
        self.HurtValueEx = 0
        self.InitTick = 0
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 4
        length += 1
        length += len(self.HurtName)
        length += 4
        length += 4
        length += 4
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.FamilyID)
        data = CommFunc.WriteDWORD(data, self.HurtID)
        data = CommFunc.WriteBYTE(data, self.NameLen)
        data = CommFunc.WriteString(data, self.NameLen, self.HurtName)
        data = CommFunc.WriteDWORD(data, self.HurtValue)
        data = CommFunc.WriteDWORD(data, self.HurtValueEx)
        data = CommFunc.WriteDWORD(data, self.InitTick)
        return data
    def OutputString(self):
        DumpString = '''
                                FamilyID:%d,
                                HurtID:%d,
                                NameLen:%d,
                                HurtName:%s,
                                HurtValue:%d,
                                HurtValueEx:%d,
                                InitTick:%d
                                '''\
                                %(
                                self.FamilyID,
                                self.HurtID,
                                self.NameLen,
                                self.HurtName,
                                self.HurtValue,
                                self.HurtValueEx,
                                self.InitTick
                                )
        return DumpString
class  tagMCFamilyBossHurtList(Structure):
    Head = tagHead()
    ObjID = 0    #(DWORD ObjID)
    NPCID = 0    #(DWORD NPCID)
    HurtType = 0    #(BYTE HurtType)// 0-实时仙盟伤血,1-历史仙盟伤血,2-实时玩家伤血,3-历史玩家伤血
    IsSort = 0    #(BYTE IsSort)// 是否排序过的,一般boss被击杀后会统一同步一次排序过的最终结果,其他情况下客户端自己排序
    HurtCount = 0    #(WORD HurtCount)// 伤血个数
    HurtList = list()    #(vector<tagMCFamilyBossHurt> HurtList)// 伤血列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA7
        self.Head.SubCmd = 0x15
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.ObjID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.NPCID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.HurtType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.IsSort,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.HurtCount,_pos = CommFunc.ReadWORD(_lpData, _pos)
        for i in range(self.HurtCount):
            temHurtList = tagMCFamilyBossHurt()
            _pos = temHurtList.ReadData(_lpData, _pos)
            self.HurtList.append(temHurtList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA7
        self.Head.SubCmd = 0x15
        self.ObjID = 0
        self.NPCID = 0
        self.HurtType = 0
        self.IsSort = 0
        self.HurtCount = 0
        self.HurtList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 4
        length += 4
        length += 1
        length += 1
        length += 2
        for i in range(self.HurtCount):
            length += self.HurtList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteDWORD(data, self.ObjID)
        data = CommFunc.WriteDWORD(data, self.NPCID)
        data = CommFunc.WriteBYTE(data, self.HurtType)
        data = CommFunc.WriteBYTE(data, self.IsSort)
        data = CommFunc.WriteWORD(data, self.HurtCount)
        for i in range(self.HurtCount):
            data = CommFunc.WriteString(data, self.HurtList[i].GetLength(), self.HurtList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                ObjID:%d,
                                NPCID:%d,
                                HurtType:%d,
                                IsSort:%d,
                                HurtCount:%d,
                                HurtList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.ObjID,
                                self.NPCID,
                                self.HurtType,
                                self.IsSort,
                                self.HurtCount,
                                "..."
                                )
        return DumpString
m_NAtagMCFamilyBossHurtList=tagMCFamilyBossHurtList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyBossHurtList.Head.Cmd,m_NAtagMCFamilyBossHurtList.Head.SubCmd))] = m_NAtagMCFamilyBossHurtList
#------------------------------------------------------
# A7 03 通知进入副本时间 #tagMCFBEnterTickList
class  tagMCFBEnterTick(Structure):
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py
@@ -176,6 +176,10 @@
        __SetIsAlive(bossID, isAlive)
        # 全服广播世界boss变更信息
        Sync_BossInfo(None, [bossID])
    # 仙盟归属boss的重置
    if bossID in PyGameData.g_familyOwnerBossInfo:
        PyGameData.g_familyOwnerBossInfo.pop(bossID)
    return
@@ -1036,4 +1040,42 @@
        if PlayerControl.GetIsTJG(curPlayer):
            return
        NetPackCommon.SendFakePack(curPlayer, packData)
    return
    return
def MapServer_FamilyOwnerBossInfo(msgInfo):
    ## 地图同步仙盟归属boss信息
    #GameWorld.DebugLog("地图同步仙盟归属boss信息: %s" % msgInfo)
    if not isinstance(msgInfo, dict):
        return
    PyGameData.g_familyOwnerBossInfo.update(msgInfo)
    return
#// AC 04 查询仙盟抢Boss所有Boss当前进度 #tagCGQueryAllFamilyBossHurt
#
#struct    tagCGQueryAllFamilyBossHurt
#{
#    tagHead        Head;
#};
def OnQueryAllFamilyBossHurt(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    hurtPack = ChPyNetSendPack.tagGCAllFamilyBossHurtInfoList()
    hurtPack.NPCHurtInfo = []
    for npcID, hurtInfo in PyGameData.g_familyOwnerBossInfo.items():
        curHP, maxHP, firstFamilyID, firstFamilyName = hurtInfo
        hurtInfo = ChPyNetSendPack.tagGCFamilyBossHurtInfo()
        hurtInfo.NPCID = npcID
        hurtInfo.CurHP = curHP%ShareDefine.Def_PerPointValue
        hurtInfo.CurHPEx = curHP/ShareDefine.Def_PerPointValue
        hurtInfo.MaxHP = maxHP%ShareDefine.Def_PerPointValue
        hurtInfo.MaxHPEx = maxHP/ShareDefine.Def_PerPointValue
        hurtInfo.FamilyID = firstFamilyID
        hurtInfo.FamilyName = firstFamilyName
        hurtInfo.NameLen = len(hurtInfo.FamilyName)
        hurtPack.NPCHurtInfo.append(hurtInfo)
    hurtPack.NPCCount = len(hurtPack.NPCHurtInfo)
    NetPackCommon.SendFakePack(curPlayer, hurtPack)
    return
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
@@ -39,6 +39,7 @@
import PlayerFamilyParty
import PlayerFamilySWRH
import PlayerViewCache
import GameWorldBoss
import PlayerTalk
import copy
@@ -1363,6 +1364,10 @@
        PlayerControl.NotifyCode(curPlayer, "DungeonGuardSkyText2")
        return
    
    if GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_FamilyRobBoss):
        PlayerControl.NotifyCode(curPlayer, "FairyGrabBossExitError")
        return
    tagPlayerName = curTagMember.GetName()  # 被踢玩家名
    tagPlayerID = curTagMember.GetPlayerID()  # 被踢玩家ID
    tagFamilyLV = curTagMember.GetFamilyLV()  # 被踢玩家职位
@@ -1437,6 +1442,11 @@
    if PlayerFamilySWRH.IsInFamilySWRH():
        PlayerControl.NotifyCode(curPlayer, "DungeonGuardSkyText1")
        return
    if GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_FamilyRobBoss):
        PlayerControl.NotifyCode(curPlayer, "FairyGrabBossExitError")
        return
    #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
    NotifyAllFamilyMemberMsg(curFamily, curPlayer, "XW_JZ_LeaveFamily", [curPlayer.GetName()])
    
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -621,6 +621,11 @@
        GameWorldBoss.DoGameWorldBossOnReborn(eval(resultName), tick)
        return
    
    # 仙盟归属boss信息同步
    if callName =="FamilyOwnerBossInfo":
        GameWorldBoss.MapServer_FamilyOwnerBossInfo(eval(resultName))
        return
    # 全局掉落CD
    if callName =="GlobalDropCD":
        GameWorldProcess.UpdGlobalDropCD(eval(resultName))
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
@@ -62,6 +62,8 @@
g_bossShuntDeadLine = {} # boss分流线路boss已死亡的线路 {bossID:[lineID, ...], ...}
g_bossShuntDeadLineChangeBoss = [] # boss分流已死亡线路有变更的boss列表
g_familyOwnerBossInfo = {} # 地图同步上来的仙盟归属boss信息
g_todayPlayerLVDict = {} #今日玩家等级字典 {playerID:lv,..}
g_yesterdayPlayerLVDict = {} #昨日玩家等级字典{playerID:lv,..}
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -1466,9 +1466,10 @@
DailyActionID_XXX12, # 废弃12
DailyActionID_Tower, # 符印塔
DailyActionID_MagicWeapon, # 法宝集魂
DailyActionID_FBHelp, # 助战副本
DailyActionID_FBHelp, # 助战副本 15
DailyActionID_BOSSHome, # BOSS之家
) = range(1, 16 + 1)
DailyActionID_FamilyRobBoss, # 仙盟抢boss
) = range(1, 17 + 1)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1245,6 +1245,18 @@
PacketSubCMD_1=0x03
PacketCallFunc_1=OnActiveAllEquipAttr
;仙盟抢boss
[FamilyRobBoss]
ScriptName = GameWorldLogic\FamilyRobBoss.py
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 1
PacketCMD_1=0xA2
PacketSubCMD_1=0x28
PacketCallFunc_1=OnQueryFamilyBossHurt
;神兽
[PlayerDogz]
ScriptName = Player\PlayerDogz.py
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
@@ -41,7 +41,7 @@
import PlayerTruck
#import PlayerPrestigeSys
import PlayerFamily
import BossHurtMng
#import BossHurtMng
import PassiveBuffEffMng
import PlayerSuccess
import GameFuncComm
@@ -56,6 +56,7 @@
import PlayerState
import ChPyNetSendPack
import NetPackCommon
import FamilyRobBoss
import FBCommon
import datetime
@@ -610,7 +611,7 @@
#  @remarks 获得curPlayer是否是新手
def GetIsNewGuy(curPlayer):
    
    if curPlayer.GetLV() < ReadChConfig.GetEvalChConfig("MinPKLV"):
    if curPlayer.GetLV() < IpyGameDataPY.GetFuncCfg("PKConfig", 5):
        return True
    
    return False
@@ -679,7 +680,8 @@
    defNPCHurtList = curTagObj.GetPlayerHurtList()
    curObjType = curObj.GetGameObjType()
    if curObjType == IPY_GameWorld.gotPlayer:
        BossHurtMng.BossAddPlayerInHurtList(curObj, curTagObj, hurtHP)
        #BossHurtMng.BossAddPlayerInHurtList(curObj, curTagObj, hurtHP)
        FamilyRobBoss.OnPlayerHurtFamilyOwnerBoss(curObj, curTagObj, hurtHP)
        if curTagObj.GetGameObjType() == IPY_GameWorld.gotNPC:
            FBLogic.DoFB_Player_HurtNPC(curObj, curTagObj, hurtHP)
        if GameObj.GetHP(curTagObj) == 0:
@@ -748,6 +750,10 @@
        if not CheckKillNPCByCnt(attacker, defender):
            return False
        
        #仙盟归属NPC判断
        if not CheckCanAttackFamilyOwnerNPC(attacker, defender):
            return False
    # NPC打玩家,反过来判断
    elif atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotPlayer:
        ##攻击次数判断
@@ -758,12 +764,19 @@
        if not CheckKillNPCByCnt(defender, attacker, False):
            return False
        
        #仙盟归属NPC判断
        if not CheckCanAttackFamilyOwnerNPC(defender, attacker, False):
            return False
        
    # NPC打NPC
    elif atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotNPC:
        if PetControl.IsPet(attacker) or attacker.GetGameNPCObjType()== IPY_GameWorld.gnotSummon:
            #击杀次数判断
            if not CheckKillNPCByCnt(attacker, defender, False):
                return False
            #仙盟归属NPC判断
            if not CheckCanAttackFamilyOwnerNPC(attacker, defender, False):
                return False
            
    #攻击NPC等级限制
@@ -817,6 +830,34 @@
              
    return False
def CheckCanAttackFamilyOwnerNPC(attacker, defender, isNotify=True):
    ''' 判断可否攻击仙盟归属的NPC '''
    if defender.GetGameObjType() != IPY_GameWorld.gotNPC:
        #GameWorld.DebugLog("只判断被攻击的是NPC的情况")
        return True
    if NPCCommon.GetDropOwnerType(defender) != ChConfig.DropOwnerType_Family:
        return True
    atkPlayer, npcObjType = GetAttackPlayer(attacker)
    # 攻击者非玩家不限制
    if not atkPlayer:
        #GameWorld.DebugLog("攻击者非玩家不限制")
        return True
    atkLimitNotifyMark = ""
    if GetIsNewGuy(atkPlayer):
        atkLimitNotifyMark = "FairyGrabBossNotAtk"
    elif not atkPlayer.GetFamilyID():
        atkLimitNotifyMark = "FairyGrabBossNoFairy"
    if atkLimitNotifyMark:
        if npcObjType is None and isNotify:
            PlayerControl.NotifyCode(atkPlayer, atkLimitNotifyMark)
        return False
    return True
def CheckKillNPCByCnt(attacker, defender, isNotify=True):
    ''' 判断当日击杀该NPC次数是否已满 '''
    if defender.GetGameObjType() != IPY_GameWorld.gotNPC:
@@ -853,9 +894,9 @@
    
    
    if hasKillCnt >= limitCnt + itemAddKillCnt:
        if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender):
            GameWorld.DebugLog("攻击过该boss可继续攻击")
            return True
        #if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender):
        #    GameWorld.DebugLog("攻击过该boss可继续攻击")
        #    return True
        #次数不足
        # 实际攻击者类型None则需要提示玩家
        if npcObjType is None:
@@ -888,9 +929,9 @@
    hasAttackCnt = atkPlayer.NomalDictGetProperty(ChConfig.Def_PDict_WorldBoss_HurtCnt, 0)
    
    if hasAttackCnt >= limitCnt:
        if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender):
            GameWorld.DebugLog("攻击过该boss可继续攻击")
            return True
        #if BossHurtMng.GetPlayerBossHurt(atkPlayer, defender):
        #    GameWorld.DebugLog("攻击过该boss可继续攻击")
        #    return True
        #次数不足
        # 实际攻击者类型None则需要提示玩家
        if npcObjType is None:
@@ -2210,6 +2251,12 @@
    if tagPlayer.GetPlayerAction() == IPY_GameWorld.paSit:
        return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_SitNotPK
    
    if GetIsNewGuy(curPlayer):
        return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_NewGuy
    if GetIsNewGuy(tagPlayer):
        return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_NotAttackNewGuy
    #攻守双方同一队伍,不可PK,可加增益buff
    #if curPlayerAreaType not in [ShareDefine.gatManor] and CanAlikeTeam(curPlayer, tagPlayer):
    #    #副本队友特殊判断
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -1028,13 +1028,13 @@
) = range( 0, Def_PA_MaxReason )
#提示原因及对应的提示mark组成的字典
Def_MessageDic = {Def_PASysMessage_NewGuy:"XW_RY_CancelWay01",            #攻击新手
Def_MessageDic = {Def_PASysMessage_NewGuy:"FairyGrabBossNewPlayer",            #攻击新手
                  Def_PASysMessage_IsSafeArea: "CannotAtk01",             #安全区域
                  Def_PASysMessage_AttackMode:"AtkModeErr",               #攻击模式
                  Def_PASysMessage_CountrySafe:"PlayerPK_Error_GoalLvLow",#国家保护
                  Def_PASysMessage_IsSafeArea_Country:"Cadres_PK_Lost",   #国家安全区保护
                  Def_PASysMessage_NewGuyNotPK:"PK_lhs_0",                #新手不能PK
                  Def_PASysMessage_NotAttackNewGuy:"PK_lhs_31379",        #不能攻击新手
                  Def_PASysMessage_NotAttackNewGuy:"FairyGrabBossNewPlayer",        #不能攻击新手
                  Def_PASysMessage_NotAttackFamily:"Old_andyshao_161795", #不能攻击同家族成员
                  Def_PASysMessage_NotAttackTeam:"PK_lhs_861048",         #不能攻击队友
                  Def_PASysMessage_AttackNotPK:"PK_lhs_202580",           #攻击方PK值过大,不能PK
@@ -1913,6 +1913,7 @@
Map_Player_AreaReward_GetCnt = "AreaAward_GetCnt%s" # 玩家战场区域福利-累计获得次数
#---地图NPC---
Map_NPC_ActivityBossRebornCount = 'ActivityBossRebornCount_%s' # 活动boss已刷新只数,参数(标识点)
Map_NPC_WorldBossLastReBornTick = 'WorldBossLastReBornTick_%s' # 世界boss上次重生时间
Map_NPC_WorldBossDeadTick = 'WorldBossDeadTick_%s' # 世界boss死亡时间
Map_NPC_RandomMapNPCID = 'RandMapNPCID_%s' # 当前地图随机NPCID, 参数为标识点mark
@@ -2035,6 +2036,7 @@
Def_NPCHurtTypeAll    = 4       #所有玩家
Def_NPCHurtTypeFaction= 5       #阵营
Def_NPCHurtTypeSpecial= 6       #特殊, 指定某些玩家, 玩家ID取ShareDefine.Def_MapItemInfo_SpecOwner
Def_NPCHurtTypeFamily = 7       #仙盟 7
#掉落归属类型-NPC表的定义
DropOwnerType = (
@@ -2045,7 +2047,8 @@
DropOwnerType_MaxHurtPlayer, # 最大伤血玩家, 伤血不会被重置, 仅限玩家 4
DropOwnerType_Faction, # 阵营 5
DropOwnerType_Special, # 特殊 6
) = range(7)
DropOwnerType_Family, # 仙盟 7
) = range(8)
#------------------------------------------------
#技能类型
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -1485,6 +1485,54 @@
#------------------------------------------------------
# AC 04 查询仙盟抢Boss所有Boss当前进度 #tagCGQueryAllFamilyBossHurt
class  tagCGQueryAllFamilyBossHurt(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xAC
        self.SubCmd = 0x04
        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 = 0xAC
        self.SubCmd = 0x04
        return
    def GetLength(self):
        return sizeof(tagCGQueryAllFamilyBossHurt)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AC 04 查询仙盟抢Boss所有Boss当前进度 //tagCGQueryAllFamilyBossHurt:
                                Cmd:%s,
                                SubCmd:%s
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd
                                )
        return DumpString
m_NAtagCGQueryAllFamilyBossHurt=tagCGQueryAllFamilyBossHurt()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGQueryAllFamilyBossHurt.Cmd,m_NAtagCGQueryAllFamilyBossHurt.SubCmd))] = m_NAtagCGQueryAllFamilyBossHurt
#------------------------------------------------------
# AC 03 仙魔之争信息查询 #tagCGXMZZInfoQuery
class  tagCGXMZZInfoQuery(Structure):
@@ -4012,6 +4060,66 @@
#------------------------------------------------------
# A2 28 查询仙盟抢Boss伤血列表 #tagCMQueryFamilyBossHurt
class  tagCMQueryFamilyBossHurt(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ObjID", c_int),
                  ("NPCID", c_int),
                  ("QueryType", c_ubyte),    # 0-实时仙盟伤血,1-历史仙盟伤血,2-实时玩家伤血,3-历史玩家伤血
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA2
        self.SubCmd = 0x28
        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 = 0xA2
        self.SubCmd = 0x28
        self.ObjID = 0
        self.NPCID = 0
        self.QueryType = 0
        return
    def GetLength(self):
        return sizeof(tagCMQueryFamilyBossHurt)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A2 28 查询仙盟抢Boss伤血列表 //tagCMQueryFamilyBossHurt:
                                Cmd:%s,
                                SubCmd:%s,
                                ObjID:%d,
                                NPCID:%d,
                                QueryType:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ObjID,
                                self.NPCID,
                                self.QueryType
                                )
        return DumpString
m_NAtagCMQueryFamilyBossHurt=tagCMQueryFamilyBossHurt()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMQueryFamilyBossHurt.Cmd,m_NAtagCMQueryFamilyBossHurt.SubCmd))] = m_NAtagCMQueryFamilyBossHurt
#------------------------------------------------------
# A2 27 查询地图NPC数量信息 #tagCMQueryNPCCntInfo
class  tagCMQueryNPCCntInfo(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -4237,6 +4237,162 @@
#------------------------------------------------------
# AC 10 仙盟抢Boss所有Boss伤血进度信息 #tagGCAllFamilyBossHurtInfoList
class  tagGCFamilyBossHurtInfo(Structure):
    NPCID = 0    #(DWORD NPCID)
    CurHP = 0    #(DWORD CurHP)
    CurHPEx = 0    #(DWORD CurHPEx)
    MaxHP = 0    #(DWORD MaxHP)
    MaxHPEx = 0    #(DWORD MaxHPEx)
    FamilyID = 0    #(DWORD FamilyID)// 最大实时伤血仙盟
    NameLen = 0    #(BYTE NameLen)
    FamilyName = ""    #(String FamilyName)
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.NPCID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.CurHP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.CurHPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MaxHP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.MaxHPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.FamilyName,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
        return _pos
    def Clear(self):
        self.NPCID = 0
        self.CurHP = 0
        self.CurHPEx = 0
        self.MaxHP = 0
        self.MaxHPEx = 0
        self.FamilyID = 0
        self.NameLen = 0
        self.FamilyName = ""
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 4
        length += 1
        length += len(self.FamilyName)
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.NPCID)
        data = CommFunc.WriteDWORD(data, self.CurHP)
        data = CommFunc.WriteDWORD(data, self.CurHPEx)
        data = CommFunc.WriteDWORD(data, self.MaxHP)
        data = CommFunc.WriteDWORD(data, self.MaxHPEx)
        data = CommFunc.WriteDWORD(data, self.FamilyID)
        data = CommFunc.WriteBYTE(data, self.NameLen)
        data = CommFunc.WriteString(data, self.NameLen, self.FamilyName)
        return data
    def OutputString(self):
        DumpString = '''
                                NPCID:%d,
                                CurHP:%d,
                                CurHPEx:%d,
                                MaxHP:%d,
                                MaxHPEx:%d,
                                FamilyID:%d,
                                NameLen:%d,
                                FamilyName:%s
                                '''\
                                %(
                                self.NPCID,
                                self.CurHP,
                                self.CurHPEx,
                                self.MaxHP,
                                self.MaxHPEx,
                                self.FamilyID,
                                self.NameLen,
                                self.FamilyName
                                )
        return DumpString
class  tagGCAllFamilyBossHurtInfoList(Structure):
    Head = tagHead()
    NPCCount = 0    #(BYTE NPCCount)// 个数
    NPCHurtInfo = list()    #(vector<tagGCFamilyBossHurtInfo> NPCHurtInfo)// NPC伤血信息列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xAC
        self.Head.SubCmd = 0x10
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.NPCCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.NPCCount):
            temNPCHurtInfo = tagGCFamilyBossHurtInfo()
            _pos = temNPCHurtInfo.ReadData(_lpData, _pos)
            self.NPCHurtInfo.append(temNPCHurtInfo)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xAC
        self.Head.SubCmd = 0x10
        self.NPCCount = 0
        self.NPCHurtInfo = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        for i in range(self.NPCCount):
            length += self.NPCHurtInfo[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.NPCCount)
        for i in range(self.NPCCount):
            data = CommFunc.WriteString(data, self.NPCHurtInfo[i].GetLength(), self.NPCHurtInfo[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                NPCCount:%d,
                                NPCHurtInfo:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.NPCCount,
                                "..."
                                )
        return DumpString
m_NAtagGCAllFamilyBossHurtInfoList=tagGCAllFamilyBossHurtInfoList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCAllFamilyBossHurtInfoList.Head.Cmd,m_NAtagGCAllFamilyBossHurtInfoList.Head.SubCmd))] = m_NAtagGCAllFamilyBossHurtInfoList
#------------------------------------------------------
# AC 08 boss复活点数通知 #tagGCBossRebornPoint
class  tagGCBossRebornPoint(Structure):
@@ -16349,6 +16505,183 @@
#------------------------------------------------------
# A7 15 通知仙盟抢Boss伤血信息 #tagMCFamilyBossHurtList
class  tagMCFamilyBossHurt(Structure):
    FamilyID = 0    #(DWORD FamilyID)// 所属仙盟ID
    HurtID = 0    #(DWORD HurtID)// 伤血的ID, 根据伤血类型表示不同的ID, 如仙盟ID或玩家ID
    NameLen = 0    #(BYTE NameLen)
    HurtName = ""    #(String HurtName)
    HurtValue = 0    #(DWORD HurtValue)// 累计伤血,求余1亿的值
    HurtValueEx = 0    #(DWORD HurtValueEx)// 累计伤血,整除1亿的值
    InitTick = 0    #(DWORD InitTick)// 伤血初始tick,用于排序,先按伤血倒序排,再按tick正序排
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.HurtID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.HurtName,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
        self.HurtValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.HurtValueEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.InitTick,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        return _pos
    def Clear(self):
        self.FamilyID = 0
        self.HurtID = 0
        self.NameLen = 0
        self.HurtName = ""
        self.HurtValue = 0
        self.HurtValueEx = 0
        self.InitTick = 0
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 4
        length += 1
        length += len(self.HurtName)
        length += 4
        length += 4
        length += 4
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.FamilyID)
        data = CommFunc.WriteDWORD(data, self.HurtID)
        data = CommFunc.WriteBYTE(data, self.NameLen)
        data = CommFunc.WriteString(data, self.NameLen, self.HurtName)
        data = CommFunc.WriteDWORD(data, self.HurtValue)
        data = CommFunc.WriteDWORD(data, self.HurtValueEx)
        data = CommFunc.WriteDWORD(data, self.InitTick)
        return data
    def OutputString(self):
        DumpString = '''
                                FamilyID:%d,
                                HurtID:%d,
                                NameLen:%d,
                                HurtName:%s,
                                HurtValue:%d,
                                HurtValueEx:%d,
                                InitTick:%d
                                '''\
                                %(
                                self.FamilyID,
                                self.HurtID,
                                self.NameLen,
                                self.HurtName,
                                self.HurtValue,
                                self.HurtValueEx,
                                self.InitTick
                                )
        return DumpString
class  tagMCFamilyBossHurtList(Structure):
    Head = tagHead()
    ObjID = 0    #(DWORD ObjID)
    NPCID = 0    #(DWORD NPCID)
    HurtType = 0    #(BYTE HurtType)// 0-实时仙盟伤血,1-历史仙盟伤血,2-实时玩家伤血,3-历史玩家伤血
    IsSort = 0    #(BYTE IsSort)// 是否排序过的,一般boss被击杀后会统一同步一次排序过的最终结果,其他情况下客户端自己排序
    HurtCount = 0    #(WORD HurtCount)// 伤血个数
    HurtList = list()    #(vector<tagMCFamilyBossHurt> HurtList)// 伤血列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA7
        self.Head.SubCmd = 0x15
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.ObjID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.NPCID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.HurtType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.IsSort,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.HurtCount,_pos = CommFunc.ReadWORD(_lpData, _pos)
        for i in range(self.HurtCount):
            temHurtList = tagMCFamilyBossHurt()
            _pos = temHurtList.ReadData(_lpData, _pos)
            self.HurtList.append(temHurtList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA7
        self.Head.SubCmd = 0x15
        self.ObjID = 0
        self.NPCID = 0
        self.HurtType = 0
        self.IsSort = 0
        self.HurtCount = 0
        self.HurtList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 4
        length += 4
        length += 1
        length += 1
        length += 2
        for i in range(self.HurtCount):
            length += self.HurtList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteDWORD(data, self.ObjID)
        data = CommFunc.WriteDWORD(data, self.NPCID)
        data = CommFunc.WriteBYTE(data, self.HurtType)
        data = CommFunc.WriteBYTE(data, self.IsSort)
        data = CommFunc.WriteWORD(data, self.HurtCount)
        for i in range(self.HurtCount):
            data = CommFunc.WriteString(data, self.HurtList[i].GetLength(), self.HurtList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                ObjID:%d,
                                NPCID:%d,
                                HurtType:%d,
                                IsSort:%d,
                                HurtCount:%d,
                                HurtList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.ObjID,
                                self.NPCID,
                                self.HurtType,
                                self.IsSort,
                                self.HurtCount,
                                "..."
                                )
        return DumpString
m_NAtagMCFamilyBossHurtList=tagMCFamilyBossHurtList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyBossHurtList.Head.Cmd,m_NAtagMCFamilyBossHurtList.Head.SubCmd))] = m_NAtagMCFamilyBossHurtList
#------------------------------------------------------
# A7 03 通知进入副本时间 #tagMCFBEnterTickList
class  tagMCFBEnterTick(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Boss.py
@@ -40,21 +40,22 @@
    mapID = GameWorld.GetMap().GetMapID()
    dataList = IpyGameDataPY.GetIpyGameDataByCondition('BOSSInfo', {"MapID":mapID}, returnList=True)
    if not dataList:
        return
    for ipyData in dataList:
        bossID = ipyData.GetNPCID()
        if not bossID:
            continue
        key = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID
        GameWorld.GetGameWorld().SetGameWorldDict(key, 1)
        bossKey = ChConfig.Map_NPC_WorldBossLastReBornTick % bossID
        GameWorld.GetGameFB().SetGameFBDict(bossKey, 0)
        bossKey = ChConfig.Map_NPC_WorldBossLastReBornTick % ipyData.GetStoneNPCID()
        GameWorld.GetGameFB().SetGameFBDict(bossKey, 0)
    if dataList:
        for ipyData in dataList:
            bossID = ipyData.GetNPCID()
            if not bossID:
                continue
            key = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID
            GameWorld.GetGameWorld().SetGameWorldDict(key, 1)
            bossKey = ChConfig.Map_NPC_WorldBossLastReBornTick % bossID
            GameWorld.GetGameFB().SetGameFBDict(bossKey, 0)
            bossKey = ChConfig.Map_NPC_WorldBossLastReBornTick % ipyData.GetStoneNPCID()
            GameWorld.GetGameFB().SetGameFBDict(bossKey, 0)
            GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_NPC_ActivityBossRebornCount % ipyData.GetRefreshMark(), 0)
        
    gameNPCManager = GameWorld.GetNPCManager()
    tick = GameWorld.GetGameWorld().GetTick()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/KillScreenNPC.py
@@ -88,11 +88,13 @@
        return
    
    curHP = GameObj.GetHP(curNPC)
    if curPlayer.GetTeamID() > 0:
        AttackCommon.AddHurtValue(curNPC, curPlayer.GetTeamID(), ChConfig.Def_NPCHurtTypeTeam, curHP)
        AttackCommon.AddTeamPlayerHurtValue(curNPC, curPlayer.GetTeamID(), curPlayer.GetPlayerID(), curHP)
    else:
        AttackCommon.AddHurtValue(curNPC, curPlayer.GetPlayerID(), ChConfig.Def_NPCHurtTypePlayer, curHP)
    AttackCommon.NPCAddObjInHurtList(curPlayer, curNPC, curHP, curHP)
    #if curPlayer.GetTeamID() > 0:
    #    AttackCommon.AddHurtValue(curNPC, curPlayer.GetTeamID(), ChConfig.Def_NPCHurtTypeTeam, curHP)
    #    AttackCommon.AddTeamPlayerHurtValue(curNPC, curPlayer.GetTeamID(), curPlayer.GetPlayerID(), curHP)
    #else:
    #    AttackCommon.AddHurtValue(curNPC, curPlayer.GetPlayerID(), ChConfig.Def_NPCHurtTypePlayer, curHP)
    
    #统一调用攻击结束动作
    GameObj.SetHP(curNPC, 0)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
@@ -16,6 +16,8 @@
#-------------------------------------------------------------------------------
import GameWorld
import IPY_GameWorld
import FamilyRobBoss
import NPCCommon
import ChConfig
##查看点选的NPC仇恨列表
@@ -36,7 +38,13 @@
        GameWorld.DebugAnswer(curPlayer, "objID(%s) 错误 找不到对应NPC" % objID)
        return
    
    GameWorld.DebugAnswer(curPlayer, "-------------------------------")
    GameWorld.DebugAnswer(curPlayer, "---%s,ID=%s,team=%s,family=%s"
                          % (GameWorld.GetGameWorld().GetTick()%1000, curPlayer.GetPlayerID(), curPlayer.GetTeamID(), curPlayer.GetFamilyID()))
    # 归属仙盟的,取仙盟伤血统计
    if NPCCommon.GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
        FamilyRobBoss.OnGMPrintFamilyOwnerBossHurt(curPlayer, curNPC)
        return
    
    npcHurtList = curNPC.GetPlayerHurtList()
    if isSort:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FamilyRobBoss.py
New file
@@ -0,0 +1,555 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GameWorldLogic.FamilyRobBoss
#
# @todo:仙盟抢boss
# @author hxp
# @date 2018-08-29
# @version 1.0
#
# 详细描述: 仙盟抢boss
#
#-------------------------------------------------------------------------------
#"""Version = 2018-08-29 20:00"""
#-------------------------------------------------------------------------------
import GameWorld
import ShareDefine
import IPY_GameWorld
import NetPackCommon
import ChPyNetSendPack
import PlayerControl
import IpyGameDataPY
import NPCCommon
import ChConfig
import GameObj
FamilyHurtObjType_Family = 1
FamilyHurtObjType_Player = 2
## 伤血对象类
class FamilyHurtObj():
    def __init__(self, familyID, objType, objID, name):
        self.familyID = familyID
        self.objType = objType
        self.objID = objID
        self.name = name
        self.hurtValue = 0
        self.initTick = GameWorld.GetGameWorld().GetTick()
        self.startProtectTick = 0 # 伤血开始保护tick, 默认0为不需要保护
        return
## 伤血信息类
class FamilyOwnerBossHurt():
    def __init__(self):
        # key = (lineID, objID, npcID)
        self.familyNowHurtSort = {} # 仙盟当前伤血,排完序的, 伤血类型是仙盟  {key:[FamilyHurtObj, ...], ...}
        self.familyNowHurtDict = {} # 仙盟当前伤血,伤血可能清除 {key:{familyID:FamilyHurtObj, ...}, ...}
        self.familyHisHurtDict = {} # 仙盟历史伤血,伤血不会清除 {key:{familyID:FamilyHurtObj, ...}, ...}
        self.playerHisHurtDict = {} # 玩家历史伤血,伤血不会清除 {key:{playerID:FamilyHurtObj, ...}, ...}
        self.familyPlayerIDDict = {} # 仙盟成员ID列表字典,{key:{familyID:[playerID, ...], ...}, ...}
        self.bossHPInfo = {} # boss当前血量信息,{key:[curHP, maxHP], ...},用于同步GameServer
        self.lastSortTick = 0
        GameWorld.DebugLog("FamilyBossHurtMgr __init__")
        return
    def ClearNPCHurt(self, key):
        self.familyNowHurtSort.pop(key, 0)
        self.familyNowHurtDict.pop(key, 0)
        self.familyHisHurtDict.pop(key, 0)
        self.playerHisHurtDict.pop(key, 0)
        self.familyPlayerIDDict.pop(key, 0)
        self.bossHPInfo = {}
        return
    def GetPlayerHisHurtDict(self):
        return
g_familyOwnerBossHurt = None
def GetFamilyHurtMgr():
    global g_familyOwnerBossHurt
    if not g_familyOwnerBossHurt:
        g_familyOwnerBossHurt = FamilyOwnerBossHurt()
    return g_familyOwnerBossHurt
def OnGMPrintFamilyOwnerBossHurt(curPlayer, curNPC):
    ## GM显示仙盟归属boss伤血信息
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = curNPC.GetID()
    bossID = curNPC.GetNPCID()
    key = (lineID, objID, bossID)
    GameWorld.DebugAnswer(curPlayer, "NPCID(%s,%s), HP: %s/%s" % (objID, bossID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC)))
    hurtMgr = GetFamilyHurtMgr()
    npcFamilyNowHurtDict = hurtMgr.familyNowHurtDict.get(key, {})
    npcFamilyHisHurtDict = hurtMgr.familyHisHurtDict.get(key, {})
    npcPlayerHisHurtDict = hurtMgr.playerHisHurtDict.get(key, {})
    npcNowHurtFamilyList = npcFamilyNowHurtDict.values()
    npcNowHurtFamilyList.sort(cmp=CmpFamilyOwnerBossHurtSort)
    npcHisHurtFamilyList = npcFamilyHisHurtDict.values()
    npcHisHurtFamilyList.sort(cmp=CmpFamilyOwnerBossHurtSort)
    npcHisHurtPlayerList = npcPlayerHisHurtDict.values()
    npcHisHurtPlayerList.sort(cmp=CmpFamilyOwnerBossHurtSort)
    GameWorld.DebugAnswer(curPlayer, "实时伤血仙盟数: %s" % len(npcNowHurtFamilyList))
    for i, hurtObj in enumerate(npcNowHurtFamilyList, 1):
        GameWorld.DebugAnswer(curPlayer, "%s,仙盟ID=%s,伤血=%s" % (i, hurtObj.objID, hurtObj.hurtValue))
    GameWorld.DebugAnswer(curPlayer, "历史伤血仙盟数: %s" % (len(npcHisHurtFamilyList)))
    for i, hurtObj in enumerate(npcHisHurtFamilyList, 1):
        GameWorld.DebugAnswer(curPlayer, "%s,仙盟ID=%s,伤血=%s" % (i, hurtObj.objID, hurtObj.hurtValue))
    GameWorld.DebugAnswer(curPlayer, "历史伤血玩家数: %s" % (len(npcHisHurtPlayerList)))
    for i, hurtObj in enumerate(npcHisHurtPlayerList, 1):
        GameWorld.DebugAnswer(curPlayer, "%s,玩家ID=%s,伤血=%s,仙盟ID=%s" % (i, hurtObj.objID, hurtObj.hurtValue, hurtObj.familyID))
    return
def OnPlayerHurtFamilyOwnerBoss(curPlayer, curBoss, hurtValue):
    ## 仙盟玩家对仙盟归属boss造成伤害
    GameWorld.DebugLog("OnPlayerHurtFamilyOwnerBoss hurtValue=%s" % hurtValue)
    if hurtValue <= 0:
        return
    if not curPlayer or not curBoss:
        return
    curObjType = curPlayer.GetGameObjType()
    if curObjType != IPY_GameWorld.gotPlayer:
        return
    curBossType = curBoss.GetGameObjType()
    if curBossType != IPY_GameWorld.gotNPC:
        return
    if NPCCommon.GetDropOwnerType(curBoss) != ChConfig.DropOwnerType_Family:
        return
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = curBoss.GetID()
    bossID = curBoss.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    familyID = curPlayer.GetFamilyID()
    GameWorld.DebugLog("仙盟抢Boss增加伤血: lineID=%s,objID=%s,bossID=%s,familyID=%s,hurtValue=%s"
                       % (lineID, objID, bossID, familyID, hurtValue), playerID)
    key = (lineID, objID, bossID)
    hurtMgr = GetFamilyHurtMgr()
    AddPlayerHurtFamilyOwnerBoss(curPlayer, curBoss, hurtMgr, key, hurtValue)
    return
def AddPlayerHurtFamilyOwnerBoss(curPlayer, curBoss, hurtMgr, key, hurtValue):
    ## 添加仙盟成员伤血
    if hurtValue < 0:
        return
    playerID = curPlayer.GetPlayerID()
    familyID = curPlayer.GetFamilyID()
    playerName = curPlayer.GetPlayerName()
    familyName = curPlayer.GetFamilyName()
    addHurtDict = {"FamilyNowHurt":[hurtMgr.familyNowHurtDict, FamilyHurtObjType_Family],
                   "FamilyHisHurt":[hurtMgr.familyHisHurtDict, FamilyHurtObjType_Family],
                   "PlayerHisHurt":[hurtMgr.playerHisHurtDict, FamilyHurtObjType_Player],
                   }
    for mark, hurtInfo in addHurtDict.items():
        hurtDict, hurtType = hurtInfo
        if key not in hurtDict:
            hurtDict[key] = {}
        objHurtDict = hurtDict[key]
        hurtID = familyID if hurtType == FamilyHurtObjType_Family else playerID
        if hurtID not in objHurtDict:
            hurtName = familyName if hurtType == FamilyHurtObjType_Family else playerName
            objHurtDict[hurtID] = FamilyHurtObj(familyID, hurtType, hurtID, hurtName)
        hurtObj = objHurtDict[hurtID]
        hurtObj.hurtValue += hurtValue
        GameWorld.DebugLog("    更新伤血%s: hurtType=%s,hurtID=%s,hurtValue=%s"
                           % (mark, hurtType, hurtID, hurtObj.hurtValue), playerID)
    # 加入关联的仙盟成员ID列表
    npcFamilyPlayerIDDict = hurtMgr.familyPlayerIDDict.get(key, {})
    npcFamilyPlayerIDList = npcFamilyPlayerIDDict.get(familyID, [])
    if playerID not in npcFamilyPlayerIDList:
        npcFamilyPlayerIDList.append(playerID)
        npcFamilyPlayerIDDict[familyID] = npcFamilyPlayerIDList
        hurtMgr.familyPlayerIDDict[key] = npcFamilyPlayerIDDict
    # 更新boss当前血量信息
    npcHP = GameObj.GetHP(curBoss)
    npcMaxHP = GameObj.GetMaxHP(curBoss)
    hurtMgr.bossHPInfo[key] = [npcHP, npcMaxHP]
    # 血量百分比广播
    npcHPPerNotifyList = IpyGameDataPY.GetFuncEvalCfg("FairyGrabBoss", 4)
    hpPerLogicMark = curBoss.GetDictByKey(ChConfig.Def_NPC_Dict_HPPerLogicMark)
    logicHPPerList = npcHPPerNotifyList[hpPerLogicMark:]
    if logicHPPerList:
        npcHPPer = int(npcHP * 100.0 / npcMaxHP)
        notifyPer, notifyKey = logicHPPerList[0]
        if npcHPPer <= notifyPer:
            curBoss.SetDict(ChConfig.Def_NPC_Dict_HPPerLogicMark, hpPerLogicMark + 1)
            PlayerControl.WorldNotify(0, notifyKey, [curBoss.GetNPCID()])
    return
def FamilyOwnerBossOnReborn(curBoss):
    ## 仙盟归属boss重生
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = curBoss.GetID()
    bossID = curBoss.GetNPCID()
    key = (lineID, objID, bossID)
    hurtMgr = GetFamilyHurtMgr()
    hurtMgr.ClearNPCHurt(key)
    hurtMgr.bossHPInfo[key] = [GameObj.GetHP(curBoss), GameObj.GetMaxHP(curBoss)]
    return
def FamilyOwnerBossOnKilled(curBoss, ownerFamilyID):
    '''仙盟归属boss被击杀
                     归属ID由外层归属算好传入,不由伤血决定,防止归属逻辑修改时改到逻辑
                     因为有伤血保护,如果伤血第一不算归属的话,逻辑就需要修改
    '''
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = curBoss.GetID()
    bossID = curBoss.GetNPCID()
    key = (lineID, objID, bossID)
    maxHP = GameObj.GetMaxHP(curBoss)
    GameWorld.Log("FamilyOwnerBossOnKilled lineID=%s,objID=%s,bossID=%s,maxHP=%s,ownerFamilyID=%s"
                  % (lineID, objID, bossID, maxHP, ownerFamilyID))
    hurtMgr = GetFamilyHurtMgr()
    npcPlayerHisHurtDict = hurtMgr.playerHisHurtDict.get(key, {})
    npcFamilyHisHurtDict = hurtMgr.familyHisHurtDict.get(key, {})
    npcFamilyPlayerIDDict = hurtMgr.familyPlayerIDDict.get(key, {})
    if ownerFamilyID in npcFamilyHisHurtDict:
        ownerFamilyHisHurt = npcFamilyHisHurtDict[ownerFamilyID]
        PlayerControl.WorldNotify(0, "FairyGrabBossDead", [ownerFamilyHisHurt.name, bossID])
    # 击杀结算前强制排序历史玩家伤血
    npcHisHurtPlayerList = npcPlayerHisHurtDict.values()
    npcHisHurtPlayerList.sort(cmp=CmpFamilyOwnerBossHurtSort)
    # 归属仙盟前x名玩家额外奖励,算历史伤血
    batchPlayerIDList, batchAddItemList, batchParamList = [], [], []
    ownerFamilyPlayerOrderAwardDict = IpyGameDataPY.GetFuncEvalCfg("FairyGrabBoss", 1, {})
    curNPCPlayerOrderAwardDict = ownerFamilyPlayerOrderAwardDict.get(bossID, {})
    maxOrder = max(curNPCPlayerOrderAwardDict) if curNPCPlayerOrderAwardDict else 0
    curOrder = 0
    #orderPlayerNameList = []
    for hurtPlayer in npcHisHurtPlayerList:
        # 只算归属仙盟的
        if hurtPlayer.familyID != ownerFamilyID:
            continue
        curOrder += 1
        awardItemList = GameWorld.GetDictValueByRangeKey(curNPCPlayerOrderAwardDict, curOrder, [])
        batchPlayerIDList.append([hurtPlayer.objID])
        batchAddItemList.append(awardItemList)
        batchParamList.append([bossID, curOrder])
        #orderPlayerNameList.append(hurtPlayer.name)
        GameWorld.Log("    归属仙盟第%s名额外奖励: %s" % (curOrder, awardItemList))
        if curOrder >= maxOrder:
            break
    if batchPlayerIDList:
        PlayerControl.SendMailBatch("FairyGrabBoss2", batchPlayerIDList, batchAddItemList, batchParamList)
        #PlayerControl.WorldNotify(0, "FairyGrabBossRank", orderPlayerNameList + [bossID])
    # 参与仙盟历史伤血奖励, 算历史伤血
    joinAwardNeedHurtHPPer = IpyGameDataPY.GetFuncCfg("FairyGrabBoss", 2)
    joinFamilyAwardDict = IpyGameDataPY.GetFuncEvalCfg("FairyGrabBoss", 3, {})
    curNPCJoinFamilyAwardList = joinFamilyAwardDict.get(bossID, [])
    joinAwardPlayerIDList = []
    GameWorld.Log("    参与奖需求伤血比例: %s%%, 参与奖励:%s" % (joinAwardNeedHurtHPPer, curNPCJoinFamilyAwardList))
    for familyID, hurtFamily in npcFamilyHisHurtDict.items():
        familyHisHurt = hurtFamily.hurtValue
        hurtPer = int(familyHisHurt * 100.0 / maxHP)
        familyPlayerIDList = npcFamilyPlayerIDDict.get(familyID, [])
        GameWorld.Log("    仙盟ID=%s, 历史伤血=%s, 伤血比例: %s%%, 参与玩家ID=%s" % (familyID, familyHisHurt, hurtPer, familyPlayerIDList))
        if hurtPer < joinAwardNeedHurtHPPer:
            continue
        joinAwardPlayerIDList += familyPlayerIDList
    if joinAwardPlayerIDList:
        PlayerControl.SendMailByKey("FairyGrabBoss1", joinAwardPlayerIDList, curNPCJoinFamilyAwardList, [bossID, joinAwardNeedHurtHPPer])
    # 同步最终结果给所有参与过的玩家
    hurtPack = __GetFamilyOwnerBossHurtPack(hurtMgr, key, objID, bossID, 0)
    copyPlayerMng = GameWorld.GetMapCopyPlayerManager()
    npcFamilyPlayerIDDict = hurtMgr.familyPlayerIDDict.get(key, {})
    for playerIDList in npcFamilyPlayerIDDict.values():
        for playerID in playerIDList:
            curPlayer = copyPlayerMng.FindPlayerByID(playerID)
            if curPlayer:
                NetPackCommon.SendFakePack(curPlayer, hurtPack)
    # 伤血在NPCCommon统一清
    return
def RefreshFamilyOwnerNPCHurt(npcControl, curNPC, tick, refreshInterval):
    ## 仙盟归属boss刷新伤血列表
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = curNPC.GetID()
    bossID = curNPC.GetNPCID()
    key = (lineID, objID, bossID)
    hurtMgr = GetFamilyHurtMgr()
    refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
    # refreshInterval 0时立即刷新
    if tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < refreshInterval:
        return GetFamilyOwnerAtkObj(npcControl, refreshPoint, hurtMgr, key)
    curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)
    npcPlayerHisHurtDict = hurtMgr.playerHisHurtDict.get(key, {}) # 玩家历史伤血,伤血不会清除 {key:{playerID:FamilyHurtObj, ...}, ...}
    # 1. 把NPC视野中没有造成伤害的玩家初始化伤血
    seePlayerCount = curNPC.GetInSightObjCount()
    for i in xrange(seePlayerCount):
        seeObj = curNPC.GetInSightObjByIndex(i)
        if seeObj == None :
            continue
        if not seeObj.GetVisible():
            continue
        seeObjType = seeObj.GetGameObjType()
        if seeObjType != IPY_GameWorld.gotPlayer:
            continue
        seePlayer = GameWorld.GetObj(seeObj.GetID(), seeObjType)
        if seePlayer.GetPlayerID() not in npcPlayerHisHurtDict:
            GameWorld.DebugLog("仙盟归属Boss看到玩家,加入伤血!lineID=%s, objID=%s, bossID=%s,playerID=%s"
                               % (lineID, objID, bossID, seePlayer.GetPlayerID()))
            AddPlayerHurtFamilyOwnerBoss(seePlayer, curNPC, hurtMgr, key, 0)
    npcFamilyNowHurtDict = hurtMgr.familyNowHurtDict.get(key, {}) # 仙盟当前伤血,伤血可能清除 {key:{familyID:FamilyHurtObj, ...}, ...}
    npcPlayerHisHurtDict = hurtMgr.playerHisHurtDict.get(key, {}) # 玩家历史伤血,伤血不会清除 {key:{playerID:FamilyHurtObj, ...}, ...}
    npcFamilyPlayerIDDict = hurtMgr.familyPlayerIDDict.get(key, {}) # 仙盟成员ID列表字典,{key:{familyID:[playerID, ...], ...}, ...}
    clearHurtFamilyIDList = [] # 要清除伤血的仙盟ID列表
    for familyID in npcFamilyNowHurtDict.keys():
        if familyID not in npcFamilyPlayerIDDict:
            continue
        isInProtect = False
        familyPlayerIDList = npcFamilyPlayerIDDict[familyID]
        for playerID in familyPlayerIDList:
            if playerID not in npcPlayerHisHurtDict:
                continue
            playerHurtObj = npcPlayerHisHurtDict[playerID]
            hurtPlayer = GameWorld.GetObj(playerID, IPY_GameWorld.gotPlayer)
            # 玩家在该boss范围内
            if hurtPlayer and npcControl.GetIsInRefreshPoint(hurtPlayer.GetPosX(), hurtPlayer.GetPosY(), refreshPoint):
                isInProtect = True
                playerHurtObj.startProtectTick = 0 # 重置保护tick
                #GameWorld.DebugLog("有成员在boss范围内,保护中!familyID=%s,playerID=%s" % (familyID, playerID))
                break
            startProtectTick = playerHurtObj.startProtectTick
            # 此boss与世界boss保护逻辑不一样,该boss只要是不在范围内的均视为开始保护
            if not startProtectTick:
                #说明: 这里为了减少循环次数,有满足保护条件的就直接break了,所以理论上最大保护延迟为所有成员都不满足条件后才激活保护tick判断
                playerHurtObj.startProtectTick = tick # 激活开始保护tick
                #GameWorld.DebugLog("激活成员开始保护tick!familyID=%s,playerID=%s,startProtectTick=%s" % (familyID, playerID, tick))
                isInProtect = True
                break
            elif tick - startProtectTick < IpyGameDataPY.GetFuncCfg("BossHurtValue", 1) * 1000:
                isInProtect = True
                #GameWorld.DebugLog("有成员在保护时间内,保护中!familyID=%s,playerID=%s,startProtectTick=%s,%s"
                #                   % (familyID, playerID, startProtectTick, tick - startProtectTick))
                break
        if not isInProtect:
            clearHurtFamilyIDList.append(familyID)
    for clearHurtFamilyID in clearHurtFamilyIDList:
        npcFamilyNowHurtDict.pop(clearHurtFamilyID, 0)
        npcFamilyPlayerIDDict.pop(clearHurtFamilyID, 0)
        GameWorld.Log("清除仙盟伤血: lineID=%s,objID=%s,bossID=%s" % (lineID, objID, bossID))
    # 排序
    npcNowHurtFamilyList = npcFamilyNowHurtDict.values()
    npcNowHurtFamilyList.sort(cmp=CmpFamilyOwnerBossHurtSort)
    hurtMgr.familyNowHurtSort[key] = npcNowHurtFamilyList # 注意伤血第一名不一定是归属, 因为有伤血保护
    return GetFamilyOwnerAtkObj(npcControl, refreshPoint, hurtMgr, key)
def CmpFamilyOwnerBossHurtSort(hurtObj1, hurtObj2):
    # 伤血倒序
    ret = cmp(hurtObj2.hurtValue, hurtObj1.hurtValue)
    if ret != 0:
        return ret
    # 创建时间正序
    ret = cmp(hurtObj1.initTick, hurtObj2.initTick)
    if ret != 0:
        return ret
    return 0
def GetFamilyOwnerAtkObj(npcControl, refreshPoint, hurtMgr, key):
    '''获取仙盟归属boss攻击目标, 攻击在boss范围内的归属仙盟成员,至于打谁,随便
    '''
    if key not in hurtMgr.familyNowHurtSort or key not in hurtMgr.familyPlayerIDDict:
        return
    npcFamilyNowHurtSortList = hurtMgr.familyNowHurtSort[key]
    npcFamilyPlayerIDDict = hurtMgr.familyPlayerIDDict[key]
    ownerFamilyID = 0
    for i, hurtFamily in enumerate(npcFamilyNowHurtSortList):
        familyID = hurtFamily.familyID
        if i == 0:
            ownerFamilyID = familyID # 策划伤血第一就是归属仙盟ID
        if familyID not in npcFamilyPlayerIDDict:
            continue
        familyPlayerIDList = npcFamilyPlayerIDDict[familyID]
        for playerID in familyPlayerIDList:
            hurtPlayer = GameWorld.GetObj(playerID, IPY_GameWorld.gotPlayer)
            if hurtPlayer and npcControl.GetIsInRefreshPoint(hurtPlayer.GetPosX(), hurtPlayer.GetPosY(), refreshPoint):
                return hurtPlayer, ownerFamilyID
    return
def OnFamilyOwnerBossProcess(tick):
    ''' 仙盟归属boss伤血定时处理,同步GameServer
    '''
    hurtMgr = GetFamilyHurtMgr()
    # 没有boss血量信息,不需要处理排序
    if not hurtMgr.bossHPInfo:
        return
    if not hurtMgr.lastSortTick:
        hurtMgr.lastSortTick = tick
        return
    # 10秒同步一次, 排序间隔由NPCAI决定
    if tick - hurtMgr.lastSortTick < 10000:
        return
    hurtMgr.lastSortTick = tick
    syncMsg = {}
    for key, bossHPInfo in hurtMgr.bossHPInfo.items():
        lineID, objID, bossID = key
        curHP, maxHP = bossHPInfo
        firstFamilyID = 0
        firstFamilyName = ""
        nowHurtList = hurtMgr.familyNowHurtSort.get(key, [])
        if nowHurtList:
            firstFamilyHurtObj = nowHurtList[0]
            firstFamilyID = firstFamilyHurtObj.familyID
            firstFamilyName = firstFamilyHurtObj.name
        syncMsg[bossID] = [curHP, maxHP, firstFamilyID, firstFamilyName]
    #GameWorld.DebugLog("同步GameServer仙盟归属boss汇总信息: %s" % syncMsg, GameWorld.GetGameWorld().GetLineID())
    syncMsg = str(syncMsg)
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "FamilyOwnerBossInfo", syncMsg, len(syncMsg))
    return
def ClearFamilyOwnerBossHurt(curBoss):
    ## 清除对应objID伤血
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = curBoss.GetID()
    bossID = curBoss.GetNPCID()
    key = (lineID, objID, bossID)
    hurtMgr = GetFamilyHurtMgr()
    hurtMgr.ClearNPCHurt(key)
    GameWorld.DebugLog("ClearFamilyOwnerBossHurt lineID=%s, objID=%s, bossID=%s" % (lineID, objID, bossID))
    return
#// A2 28 查询仙盟抢Boss伤血列表 #tagCMQueryFamilyBossHurt
#
#struct    tagCMQueryFamilyBossHurt
#{
#    tagHead         Head;
#    DWORD        ObjID;
#    DWORD        NPCID;
#    BYTE        QueryType;    // 0-实时仙盟伤血,1-历史仙盟伤血,2-实时玩家伤血,3-历史玩家伤血
#};
def OnQueryFamilyBossHurt(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    lineID = GameWorld.GetGameWorld().GetLineID()
    objID = clientData.ObjID
    npcID = clientData.NPCID
    queryType = clientData.QueryType
    key = (lineID, objID, npcID)
    hurtMgr = GetFamilyHurtMgr()
    hurtPack = __GetFamilyOwnerBossHurtPack(hurtMgr, key, objID, npcID, queryType)
    if hurtPack:
        NetPackCommon.SendFakePack(curPlayer, hurtPack)
    return
def __GetFamilyOwnerBossHurtPack(hurtMgr, key, objID, npcID, queryType=0):
    ## @param queryType: 0-实时仙盟伤血,1-历史仙盟伤血,2-实时玩家伤血,3-历史玩家伤血
    isSort = 0
    if queryType == 0:
        hurtObjList = hurtMgr.familyNowHurtSort.get(key, [])
        isSort = 1
    else:
        # 赶时间,暂不支持
        return
    hurtPack = ChPyNetSendPack.tagMCFamilyBossHurtList()
    hurtPack.Clear()
    hurtPack.ObjID = objID
    hurtPack.NPCID = npcID
    hurtPack.HurtType = queryType
    hurtPack.IsSort = isSort
    hurtPack.HurtList = []
    for hurtObj in hurtObjList:
        hurtInfo = ChPyNetSendPack.tagMCFamilyBossHurt()
        hurtInfo.FamilyID = hurtObj.familyID
        hurtInfo.HurtID = hurtObj.objID
        hurtInfo.HurtName = hurtObj.name
        hurtInfo.NameLen = len(hurtInfo.HurtName)
        hurtInfo.InitTick = hurtObj.initTick
        hurtInfo.HurtValue = hurtObj.hurtValue%ShareDefine.Def_PerPointValue
        hurtInfo.HurtValueEx = hurtObj.hurtValue/ShareDefine.Def_PerPointValue
        hurtPack.HurtList.append(hurtInfo)
    hurtPack.HurtCount = len(hurtPack.HurtList)
    return hurtPack
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py
@@ -39,6 +39,7 @@
import GameWorld
import ChConfig
import PlayerControl
import FamilyRobBoss
import EventShell
import FBLogic
import FBCommon
@@ -501,6 +502,9 @@
    __RefreshOnFiveMinute(tick)
    #定时检测关闭超时文件
    EventReport.OnTimeCloseScribeTxt()
    #仙盟归属boss定时处理
    FamilyRobBoss.OnFamilyOwnerBossProcess(tick)
    return
## 通知RouteServer 消息
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -697,6 +697,9 @@
                        ("DWORD", "NPCID", 1),
                        ("DWORD", "MapID", 0),
                        ("BYTE", "RefreshMark", 0),
                        ("BYTE", "IsNeedShunt", 0),
                        ("BYTE", "RelatedType", 0),
                        ("WORD", "RelatedID", 0),
                        ("DWORD", "StoneNPCID", 0),
                        ),
@@ -2348,12 +2351,18 @@
        self.NPCID = 0
        self.MapID = 0
        self.RefreshMark = 0
        self.IsNeedShunt = 0
        self.RelatedType = 0
        self.RelatedID = 0
        self.StoneNPCID = 0
        return
        
    def GetNPCID(self): return self.NPCID # ID
    def GetMapID(self): return self.MapID # 地图ID
    def GetRefreshMark(self): return self.RefreshMark # 刷新标识点
    def GetIsNeedShunt(self): return self.IsNeedShunt # 是否需要分流
    def GetRelatedType(self): return self.RelatedType # 刷怪关联类型
    def GetRelatedID(self): return self.RelatedID # 关联ID
    def GetStoneNPCID(self): return self.StoneNPCID # 墓碑NPCID
# 古神禁地表
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -1225,6 +1225,12 @@
        if curPlayer.GetPlayerID() not in ownerIDList:
            #GameWorld.Log("该物品不属于你,不能拾取6! ownerIDList=%s" % ownerIDList, curPlayer.GetPlayerID())
            return False
    #仙盟归属
    elif itemOwnerType == ChConfig.Def_NPCHurtTypeFamily:
        if mapItem.GetOwnerID() != curPlayer.GetFamilyID():
            #GameWorld.Log("该物品不属于你仙盟的,不能拾取7! ownerFamilyID=%s,curFamilyID=%s"
            #              % (mapItem.GetOwnerID(), curPlayer.GetFamilyID()), curPlayer.GetPlayerID())
            return False
        
    return True
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py
@@ -31,6 +31,7 @@
import NPCCommon
import AICommon
import IPY_GameWorld
import FamilyRobBoss
import AttackCommon
import GameWorld
import BaseAttack
@@ -110,6 +111,12 @@
            elif ownerType == ChConfig.Def_NPCHurtTypePlayer:
                tagObj = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
                
    elif dropOwnerType == ChConfig.DropOwnerType_Family:
        ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(npcControl, curNPC, tick, refreshInterval)
        if ownerInfo:
            tagObj, ownerFamilyID = ownerInfo
            ownerType, ownerID = ChConfig.Def_NPCHurtTypeFamily, ownerFamilyID
    # 没有攻击目标,则刷新仇恨,支持主动怪
    if not tagObj:
        angryObjType, maxAngryObj = None, None
@@ -122,7 +129,7 @@
            maxAngryObj = GameWorld.GetObj(angryID, angryObjType)
            
        tagObj = maxAngryObj
        if angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj:
        if angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj and not ownerType:
            teamID = maxAngryObj.GetTeamID()
            if teamID:
                ownerType, ownerID = ChConfig.Def_NPCHurtTypeTeam, teamID
@@ -149,7 +156,7 @@
def __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType=0, ownerID=0, isDead=False):
    npcID = curNPC.GetNPCID()
    dropOwnerType = NPCCommon.GetDropOwnerType(curNPC)
    if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry]:
    if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry, ChConfig.DropOwnerType_Family]:
        #GameWorld.DebugLog("不需要展示掉落归属的NPC! npcID=%s,dropOwnerType=%s" % (npcID, dropOwnerType))
        return
    
@@ -202,12 +209,35 @@
                if isOk:
                    GameWorld.DebugLog("删除归属队员buff: teamID=%s,playerID=%s" % (ownerID, curTeamPlayer.GetPlayerID()))
                    
    elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
        hurtType, hurtID = ChConfig.Def_NPCHurtTypeFamily, ownerID
        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
        for index in xrange(copyPlayerMgr.GetPlayerCount()):
            player = copyPlayerMgr.GetPlayerByIndex(index)
            if not player:
                continue
            # 归属仙盟 且 在boss区域内
            if player.GetFamilyID() == ownerID and npcControl.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
                __AddBossDropOwnerPlayerBuff(player, tick, curNPC)
            else:
                isOk = BuffSkill.DelBuffBySkillID(player, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
                if isOk:
                    GameWorld.DebugLog("删除非归属仙盟成员buff: teamID=%s,playerID=%s" % (ownerID, player.GetPlayerID()))
    if isDead:
        key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)
        teamID = curTeam.GetTeamID() if curTeam else 0
        if killerDict:
            PyGameData.g_npcKillerInfo[key] = killerDict, curTeam, hurtType, hurtID
        GameWorld.Log("Boss被击杀: npcID=%s,key=%s,playerIDList=%s,teamID=%s" % (npcID, key, killerDict.keys(), teamID))
        elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
            PyGameData.g_npcKillerInfo[key] = {}, None, hurtType, hurtID
        GameWorld.Log("Boss被击杀: npcID=%s,key=%s,playerIDList=%s,teamID=%s,hurtType=%s,hurtID=%s"
                      % (npcID, key, killerDict.keys(), teamID, hurtType, hurtID))
    return
def __AddBossDropOwnerPlayerBuff(curPlayer, tick, curNPC):
@@ -259,6 +289,14 @@
            if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                continue
            __SetBossDropOwnerBuffDisappearTime(curTeamPlayer, curNPC)
    elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
        copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
        for index in xrange(copyPlayerMgr.GetPlayerCount()):
            player = copyPlayerMgr.GetPlayerByIndex(index)
            if not player:
                continue
            __SetBossDropOwnerBuffDisappearTime(player, curNPC)
    return
def __SetBossDropOwnerBuffDisappearTime(curPlayer, curNPC):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -52,6 +52,7 @@
import PlayerMagicWeapon
import PlayerBossReborn
import PlayerFairyCeremony
import FamilyRobBoss
import IpyGameDataPY
import PyGameData
import PlayerTeam
@@ -1946,11 +1947,14 @@
            #因为存在boss分流,所以用gameFB字典,但是存活状态还是用GameWorld字典
            GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_NPC_WorldBossDeadTick % npcid, GameWorld.GetGameWorld().GetTick())
        
            if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                FamilyRobBoss.ClearFamilyOwnerBossHurt(curNPC)
    
    # 清除队伍成员伤血列表
    AttackCommon.ClearTeamPlayerHurtValue(curNPC)
    # 清除自定义伤血列表
    BossHurtMng.ClearHurtValueList(curNPC)
    #BossHurtMng.ClearHurtValueList(curNPC)
    # C++设置npc死亡
    curNPC.SetDead(curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason),
@@ -1984,6 +1988,9 @@
        self.__Killer = None # 击杀者, 由各种规则得出, 一般也是物品归属的代表, 用于广播、记录等确保与归属一致
        self.__AllKillerDict = {} # 所有击杀的玩家ID对应字典, 非队伍, 一般也是归属的拥有者
        self.__FeelPlayerList = [] # 所有摸怪玩家列表,处理任务及某些逻辑用
        self.__OwnerHurtType = 0
        self.__OwnerHurtID = 0
        return
    #---------------------------------------------------------------------
    ## 移动到某一个点的附近点
@@ -3359,6 +3366,9 @@
                GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState',
                                                            '%s' % (msgList), len(str(msgList)))
                
                if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                    FamilyRobBoss.FamilyOwnerBossOnReborn(curNPC)
        # 检查是否有光环, 在重生时处理,不然可能导致有些无战斗逻辑的怪物无法套上光环buff
        skillManager = curNPC.GetSkillManager()
        for index in xrange(skillManager.GetSkillCount()):
@@ -3736,7 +3746,7 @@
        #=====================================================================================================
        
        #boss伤血排行榜击杀逻辑
        BossHurtMng.BossOnKilled(curNPC)
        #BossHurtMng.BossOnKilled(curNPC)
        
        #掉落需要用到摸怪,所以在处理掉落奖励之前设置
        self.__SetFeelNPCPlayerList()
@@ -3752,6 +3762,8 @@
        # 记录boss击杀信息的NPC
        bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID)
        if bossIpyData:
            if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                killerName = FamilyRobBoss.FamilyOwnerBossOnKilled(curNPC, self.__OwnerHurtID)
            #KillerJob = 0 if not self.__Killer else self.__Killer.GetJob()
            GameServer_KillGameWorldBoss(curNPC.GetNPCID(), killerName, 0)
        #===========================================================================================
@@ -4197,7 +4209,8 @@
        self.__MaxHurtPlayer = self.__FindBossMaxHurtObj() # py自定义伤血所得到的Boss最大伤血玩家
        
        self.__AllKillerDict, curTeam, hurtType, hurtID = self.__FindNPCKillerInfo()
        self.__OwnerHurtType, self.__OwnerHurtID = hurtType, hurtID
        #最后一击处理
        self.__DoLastTimeHurtLogic()
        
@@ -4227,6 +4240,10 @@
        elif curTeam != None:
            self.__KilledByTeamSetPrize(curTeam, hurtType, hurtID)
        
        #被仙盟杀死
        elif hurtType == ChConfig.Def_NPCHurtTypeFamily:
            self.__KilledByFamilySetPrize(hurtType, hurtID)
        else:
            GameWorld.ErrLog("NPC归属异常:npcID=%s,hurtType=%s,hurtID=%s" % (npcID, hurtType, hurtID))
            
@@ -4621,7 +4638,60 @@
        self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
        #GameWorld.Log("队伍杀死怪物奖励,逻辑成功结束")
        return
    def __KilledByFamilySetPrize(self, hurtType, hurtID):
        ## 仙盟杀死NPC奖励逻辑
        curNPC = self.__Instance
        maxLV = 0
        dropPlayer = None
        ownerPlayerList = []
        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
        for index in xrange(copyPlayerMgr.GetPlayerCount()):
            player = copyPlayerMgr.GetPlayerByIndex(index)
            if not player:
                continue
            if player.GetFamilyID() != hurtID or not self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
                continue
            curPlayerLV = player.GetLV()
            if maxLV < curPlayerLV:
                maxLV = curPlayerLV
                dropPlayer = player
            ownerPlayerList.append(player)
        if not ownerPlayerList:
            GameWorld.Log("奖励归属仙盟,但是不存在可获得该奖励的成员!npcID=%s,hurtType=%s,hurtID=%s"
                          % (curNPC.GetNPCID(), hurtType, hurtID))
        # 因为仙盟归属boss归属伤血第一的仙盟,仙盟伤血有保护,可能存在伤血第一仙盟在boss死亡的时候都不在
        # 此时掉落计算玩家算最后一击玩家,归属还是算伤血第一仙盟的
        if not dropPlayer:
            dropPlayer = self.__LastHurtPlayer
        if not dropPlayer:
            GameWorld.ErrLog("奖励归属仙盟,找不到掉落玩家!npcID=%s,hurtType=%s,hurtID=%s"
                             % (curNPC.GetNPCID(), hurtType, hurtID))
            return
        # 赶时间,先简单处理直接取最大等级的,之后可按实际情况来
        if not self.__LastHurtPlayer:
            self.__LastHurtPlayer = dropPlayer
        if not self.__MaxHurtPlayer:
            self.__MaxHurtPlayer = dropPlayer
        if not self.__Killer:
            self.__Killer = dropPlayer
        maxHurtID = dropPlayer.GetPlayerID()
        for curPlayer in ownerPlayerList:
            self.__KillNPCFuncEx(curPlayer, curNPC, maxHurtID, False)
        #调用物品掉落
        self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
        return
    ## 队伍或自己击杀NPC扩展功能
    #  @param curPlayer
    #  @return None
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
@@ -17,6 +17,7 @@
import ShareDefine
import ReadChConfig
import GameLogic_SealDemon
import PlayerControl
import IPY_GameWorld
import IpyGameDataPY
import GameWorld
@@ -337,6 +338,18 @@
def NPCRefresh_100(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def ResetActivityBossRefreshCount():
    ## 重置活动boss刷怪个数
    gameFB = GameWorld.GetGameFB()
    gameNPC = GameWorld.GetNPCManager()
    for i in xrange(gameNPC.GetCustomNPCRefreshCount()):
        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
        refreshMark = npcRefresh.GetRefreshMark()
        if gameFB.GetGameFBDictByKey(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark):
            gameFB.SetGameFBDict(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark, 0)
            GameWorld.DebugLog("重置活动boss刷怪点刷怪个数: refreshMark=%s" % refreshMark)
    return
## 世界boss刷怪
#  @param npcRefresh 刷新实例
#  @param tick 当前时间
@@ -363,9 +376,42 @@
    
    gameFB = GameWorld.GetGameFB()
    gameWorldMgr = GameWorld.GetGameWorld()
    bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID
    rebornBossState = gameWorldMgr.GetGameWorldDictByKey(bosskey)
    isNeedShunt = NPCCommon.IsMapNeedBossShunt(mapID)
    relatedType = ipyData.GetRelatedType()
    relatedID = ipyData.GetRelatedID()
    isActivityBoss = False
    # 关联日常活动
    if relatedType == 1:
        actionKey = ShareDefine.Def_Notify_WorldKey_DailyActionState % relatedID
        rebornBossState = 1 if gameWorldMgr.GetGameWorldDictByKey(actionKey) else 0
        isActivityBoss = True
    # 关联运营活动,待扩展
    elif relatedType == 2:
        pass
    else:
        bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID
        rebornBossState = gameWorldMgr.GetGameWorldDictByKey(bosskey)
    rebornLineID = 0
    activityLineID = 0 # 活动线, 默认1线
    activityMapLineDict = IpyGameDataPY.GetFuncEvalCfg("MapLine", 2, {})
    if mapID in activityMapLineDict:
        activityLineID = max(0, activityMapLineDict[mapID] - 1)
    # 活动boss只在活动线路刷
    if isActivityBoss:
        activityBossRebornCount = gameFB.GetGameFBDictByKey(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark)
        rebornLineID = activityLineID # 活动boss只刷在活动线
        # 不是活动线
        if rebornBossState and lineID != rebornLineID:
            rebornBossState = 0
    # 非活动boss活动线不刷, 1线除外
    else:
        if activityLineID and lineID == activityLineID:
            rebornBossState = 0
            stoneNPCID = 0 # 活动线暂不刷墓碑
    isNeedShunt = NPCCommon.IsMapNeedBossShunt(mapID) and ipyData.GetIsNeedShunt()
    
    curNPC = None
    if npcRefresh.GetCount() > 0:
@@ -379,8 +425,13 @@
            #去掉非bossNPC
            NPCCommon.SetDeadEx(curNPC)
            
        # 非一线 且 不需要分流的地图 且 不是封魔坛  不允许复活
        if lineID != 0 and not isNeedShunt and mapID != ChConfig.Def_FBMapID_SealDemon:
        # 非复活线 且 不需要分流的地图 且 不是封魔坛  不允许复活
        if lineID != rebornLineID and not isNeedShunt and mapID != ChConfig.Def_FBMapID_SealDemon:
            return
        if isActivityBoss and activityBossRebornCount > 0:
            #GameWorld.DebugLog("活动线已经刷过不再刷活动boss: lineID=%s,rebornLineID=%s,refreshMark=%s,bossID=%s,activityBossRebornCount=%s"
            #                   % (lineID, rebornLineID, refreshMark, bossID, activityBossRebornCount))
            return
        
    # 死亡状态
@@ -391,6 +442,11 @@
                return
            if curNPC.GetNPCID() == stoneNPCID:
                return 
            # 活动的boss
            if curNPC.GetNPCID() == bossID and isActivityBoss:
                GameWorld.Log("活动boss,活动结束,系统设置boss死亡!bossID=%s" % bossID)
                PlayerControl.FBNotify("FairyGrabBossNoDead", [bossID])
            #去掉非墓碑NPC
            NPCCommon.SetDeadEx(curNPC)
        
@@ -415,7 +471,12 @@
    #初始化NPC
    __InitNewBornNPC(npcRefresh, tick)
    gameFB.SetGameFBDict(key, tick)
    GameWorld.DebugLog("BossRefresh mapID=%s,refreshMark=%s,rebornNPCID=%s,isNeedShunt=%s,OK!" % (mapID, refreshMark, rebornNPCID, isNeedShunt), lineID)
    if isActivityBoss and rebornBossState:
        gameFB.SetGameFBDict(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark, activityBossRebornCount + 1)
    GameWorld.DebugLog("BossRefresh mapID=%s,rebornLineID=%s,refreshMark=%s,rebornNPCID=%s,isNeedShunt=%s,OK!"
                       % (mapID, rebornLineID, refreshMark, rebornNPCID, isNeedShunt), lineID)
    return
def IsShuntBossNeedProcess(curNPC):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -1354,7 +1354,12 @@
                if curPlayer.GetID() == 0:
                    continue
                PlayerWorldAverageLv.UpdatePlayerWorldAverageLv(curPlayer)
    # 日常活动
    elif key.startswith(ShareDefine.Def_Notify_WorldKey_DailyActionState[:-2]):
        if value and gameWorldMgr.GetGameWorldDictByKey(key) != value:
            NPCCustomRefresh.ResetActivityBossRefreshCount()
    #通用设置
    gameWorldMgr.SetGameWorldDict(key, value)
    
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1466,9 +1466,10 @@
DailyActionID_XXX12, # 废弃12
DailyActionID_Tower, # 符印塔
DailyActionID_MagicWeapon, # 法宝集魂
DailyActionID_FBHelp, # 助战副本
DailyActionID_FBHelp, # 助战副本 15
DailyActionID_BOSSHome, # BOSS之家
) = range(1, 16 + 1)
DailyActionID_FamilyRobBoss, # 仙盟抢boss
) = range(1, 17 + 1)