From 6253040e3470059c4ef906da2d7122fc48e681e5 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 16 三月 2020 17:39:08 +0800
Subject: [PATCH] 8401 【后端】BOSS复活修改(全服奖励邮件、排名奖励邮件发放) 新增发送全服邮件;新增伤血列表邮件发放奖励模块管理;

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py        |   19 +
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py                                   |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py                   |   15 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBossReborn.py         |   33 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py                      |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py                  |  453 +++++++++++++++++++++++++++++++++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py                         |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py            |   24 ++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py                            |   48 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                        |    3 
 11 files changed, 594 insertions(+), 15 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py
index ca9a2d2..bda5d47 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py
@@ -1002,7 +1002,7 @@
         return
     rebornCnt = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_BossRebornCnt)
     maxRebornCnt = IpyGameDataPY.GetFuncCfg('BossRebornTotalPoint', 3)
-    if rebornCnt >= maxRebornCnt:
+    if maxRebornCnt and rebornCnt >= maxRebornCnt:
         GameWorld.DebugLog(' boss复活已达到最大次数! maxRebornCnt=%s' % maxRebornCnt)
         return
     
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py
index d67cf3f..2bba962 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py
@@ -335,6 +335,54 @@
             
     return successGUIDList
 
+def SendEntireMail(mailTypeKey, getDays, limitLV, limitLVType, addItemList=[], paramList=[], \
+                   gold=0, goldPaper=0, silver=0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail, GUID=""):
+    ''' 发送全服邮件
+    @param mailTypeKey: 邮件模板key
+    @param getDays: 有效天数
+    @param limitLV: 领取最低等级限制
+    @param limitLVType: 等级不足的升级后是否可领 0-不可,1-可以
+    '''
+    
+    if not mailTypeKey or getDays <= 0:
+        return
+    
+    addItemDictList = []
+    for itemInfo in addItemList:
+        if isinstance(itemInfo, dict):
+            addItemDictList.append(itemInfo)
+            continue
+        
+        if len(itemInfo) == 3:
+            itemID, itemCnt, isAuctionItem = itemInfo
+        else:
+            continue
+        
+        addItemDict = {}
+        addItemDict['ItemID'] = itemID
+        addItemDict['Count'] = itemCnt
+        addItemDict['IsAuctionItem'] = isAuctionItem
+        addItemDictList.append(addItemDict)
+        
+    if not GUID:
+        GUID = str(uuid.uuid1())
+        
+    limitTime = str(GameWorld.GetDatetimeByDiffDays(getDays))
+    limitTime = limitTime.split(".")[0]
+    
+    sender = ChConfig.Def_Mail_SenderSys
+    title = ""
+    content = "<MailTemplate>%s</MailTemplate>%s" % (mailTypeKey, json.dumps(paramList, ensure_ascii=False))
+    
+    checkState = 0 # 邮件审核状态,为兼容老邮件,默认0-已审核,1-未审核
+    mailInfo = GetEntireCompensationInfo(checkState, limitLVType, limitLV)
+    PlayerJob = 127 # 默认全职业可领
+    serverID = 0 # 默认所有服务器ID
+    
+    AddEntireItem(GUID, addItemDictList, limitTime, mailInfo, PlayerJob, "%s<$_$>%s<$_$>%s" % (sender, title, content), 
+                  gold, goldPaper, silver, detail, serverID)
+    return
+
 ## 添加全服补偿
 #  @param addItemDictList, LimitTime, mailInfo, PlayerJob,  Text 
 #  @return None
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index 3bc8090..1401d34 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -507,6 +507,11 @@
         PlayerCompensation.SendPersonalItemMailBatch(eval(resultName))
         return
     
+    if callName == "SendEntireMail":
+        mailTypeKey, getDays, limitLV, limitLVType, addItemList, paramList, gold, goldPaper, silver, detail, moneySource = eval(resultName)
+        PlayerCompensation.SendEntireMail(mailTypeKey, getDays, limitLV, limitLVType, addItemList, paramList, gold, goldPaper, silver, detail, moneySource)
+        return
+    
     if callName == "SendMsgToCrossServer":
         msgType, dataMsg = eval(resultName)
         CrossRealmMsg.SendMsgToCrossServer(msgType, dataMsg)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
index c902e92..72a5b60 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
@@ -61,6 +61,7 @@
 import FBCommon
 import ChNPC
 import BossHurtMng
+import NPCHurtMgr
 
 import datetime
 import math
@@ -720,6 +721,9 @@
         if NPCHurtManager.AddHurtValue(curObj, curTagObj, hurtHP, isBounce):
             return
         
+        if NPCHurtMgr.AddHurtValue(curObj, curTagObj, hurtHP, isBounce):
+            return
+        
         curTeam = curObj.GetTeam()
         
         #2012-04-23 jiang 攻击镖车只算个人伤害
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 30266ae..6707c9e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2134,7 +2134,8 @@
 DropOwnerType_Special, # 特殊 6
 DropOwnerType_Family, # 仙盟 7
 DropOwnerType_Contend, # 争夺 8 第一个攻击的获得归属,击杀当前归属者的玩家成为新归属者
-) = range(9)
+DropOwnerType_RankHurtPlayer, # 个人伤血排行奖励归属 9 根据玩家个人伤血排行给奖励,伤血不重置
+) = range(10)
 
 #------------------------------------------------
 #技能类型
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
index b685cd0..9d8bb48 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
@@ -20,6 +20,7 @@
 import NPCCommon
 import ChConfig
 import NPCHurtManager
+import NPCHurtMgr
 import PlayerTeam
 import GameObj
 
@@ -49,17 +50,21 @@
         FamilyRobBoss.OnGMPrintFamilyOwnerBossHurt(curPlayer, curNPC)
         return
     
-    isPyHurtList = 1
+    isAssistHurt = 0
     npcHurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
+    if npcHurtList:
+        isAssistHurt = 1
+    if not npcHurtList:
+        npcHurtList = NPCHurtMgr.GetPlayerHurtList(curNPC)
     if not npcHurtList:
         npcHurtList = curNPC.GetPlayerHurtList()
-        isPyHurtList = 0
+        
     if isSort:
         npcHurtList.Sort()  #sort以后伤血列表从大到小排序
         
-    GameWorld.DebugAnswer(curPlayer, "ID=%s,NPCID=%s, 伤血数=%s,排序=%s,PY=%s" 
-                          % (curNPC.GetID(), curNPC.GetNPCID(), npcHurtList.GetHurtCount(), isSort, isPyHurtList))
-    if isPyHurtList:
+    GameWorld.DebugAnswer(curPlayer, "ID=%s,NPCID=%s, 伤血数=%s,排序=%s,协=%s" 
+                          % (curNPC.GetID(), curNPC.GetNPCID(), npcHurtList.GetHurtCount(), isSort, isAssistHurt))
+    if isAssistHurt:
         for playerID, assistPlayerIDList in npcHurtList.GetNoAssitPlayerIDDict().items():
             GameWorld.DebugAnswer(curPlayer, "玩家:%s, 协助玩家:%s" % (playerID, assistPlayerIDList))
         for assistPlayerID, tagPlayerID in npcHurtList.GetAssistPlayerIDDict().items():
@@ -85,7 +90,7 @@
                 d = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), hurtPlayer.GetPosX(), hurtPlayer.GetPosY())
                 GameWorld.DebugAnswer(curPlayer, "%s 玩家ID=%s,距离=%s, V=%s" % (index, hurtID, d, hurtValue))
                 
-            if isPyHurtList:
+            if isAssistHurt:
                 playerHurtValue, assistPlayerHurtDict = npcHurtList.GetPlayerHurtDetail(hurtID)
                 GameWorld.DebugAnswer(curPlayer, "    非协id=%s,v=%s" % (hurtID, playerHurtValue))
                 for assistPlayerID, assistHurtValue in assistPlayerHurtDict.items():
@@ -99,7 +104,7 @@
             else:
                 GameWorld.DebugAnswer(curPlayer, "%s 队伍ID=%s,人数=%s, V=%s" % (index, hurtID, curTeam.GetMemberCount(), hurtValue))
                 
-            if isPyHurtList:
+            if isAssistHurt:
                 mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(hurtID)
                 for teamPlayerID in mapTeamPlayerIDList:
                     if not npcHurtList.IsNoAssistPlayer(teamPlayerID):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
index 1efe1c7..070232a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -60,6 +60,7 @@
 import PlayerState
 import PyGameData
 import PlayerTeam
+import NPCHurtMgr
 import PlayerVip
 import GameObj
 import ChNPC
@@ -2296,6 +2297,7 @@
     # 清除自定义伤血列表
     #BossHurtMng.ClearHurtValueList(curNPC)
     NPCHurtManager.DeletePlayerHurtList(curNPC)
+    NPCHurtMgr.DeletePlayerHurtList(curNPC)
     if curNPC.GetType() == ChConfig.ntRobot:
         lineID = GameWorld.GetGameWorld().GetLineID()
         lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})
@@ -3258,6 +3260,7 @@
         self.ClearAllBuff(isClearAuraBuff)
         curNPC = self.__Instance
         NPCHurtManager.ClearPlayerHurtList(curNPC)
+        NPCHurtMgr.ClearPlayerHurtList(curNPC)
         return True
     
     #---------------------------------------------------------------------
@@ -5182,11 +5185,13 @@
             GameWorld.Log("Boss死亡: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s" 
                           % (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType))
         #if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:
-        if NPCHurtManager.GetPlayerHurtList(curNPC):
-            maxHurtInfo = NPCHurtManager.RefreshHurtList(curNPC, tick, refreshInterval, isDead)
-            if maxHurtInfo:
-                tagObj, ownerType, ownerID = maxHurtInfo
-                
+        maxHurtInfo = NPCHurtManager.RefreshHurtList(curNPC, tick, refreshInterval, isDead)
+        if not maxHurtInfo:
+            maxHurtInfo = NPCHurtMgr.RefreshHurtList(curNPC, tick, refreshInterval, isDead)
+            
+        if maxHurtInfo:
+            tagObj, ownerType, ownerID = maxHurtInfo
+            
         elif dropOwnerType == ChConfig.DropOwnerType_Family:
             ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(self, curNPC, tick, refreshInterval)
             if ownerInfo:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py
new file mode 100644
index 0000000..b6503ea
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py
@@ -0,0 +1,453 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package NPCHurtMgr
+#
+# @todo:NPC伤血管理
+# @author hxp
+# @date 2020年03月16日
+# @version 1.0
+#
+# 详细描述: NPC伤血管理
+#
+# 由于 NPCHurtManager 模块之前针对协助做的,测试比较麻烦,为了不去动到原来的模块逻辑,故新写一个伤血模块管理
+# 新模块伤血列表通用逻辑由父类处理,且函数命名与c++接口提供的函数名一致,不同需求类型的伤血列表额外逻辑则可扩展子类进行处理
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2020年03月16日 18:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PyGameData
+import IPY_GameWorld
+import IpyGameDataPY
+import PlayerBossReborn
+import ChPyNetSendPack
+import NetPackCommon
+import ShareDefine
+import PlayerTeam
+import NPCCommon
+import ChConfig
+
+
+class HurtValueObj():
+    ''' 伤血对象,可能是玩家、队伍等
+    '''
+    
+    def __init__(self):
+        self.__hurtID = 0
+        self.__hurtType = ChConfig.Def_NPCHurtTypePlayer # 均默认是玩家
+        self.__hurtName = ""
+        self.__hurtValue = 0
+        return
+    
+    def GetValueID(self): return self.__hurtID
+    def SetValueID(self, hurtID): self.__hurtID = hurtID
+    def GetValueType(self): return self.__hurtType
+    def SetValueType(self, hurtType): self.__hurtType = hurtType
+    def GetHurtName(self): return self.__hurtName
+    def SetHurtName(self, hurtName): self.__hurtName = hurtName
+    def GetHurtValue(self): return self.__hurtValue
+    def SetHurtValue(self, hurtValue): self.__hurtValue = hurtValue
+    
+class HurtValueObjList(object):
+    ''' 伤血列表父类,类似 IPY_GameObj.IPY_PlayerHurtList
+                    只做基础的伤血累加、排序等公共逻辑
+                    
+            注意:
+                原协助伤害因为是最先做的逻辑,测试比较麻烦,暂不修改继承该类,还是保留原来的单独处理
+                后续需要增加的不同伤血规则逻辑可直接继承该类进行扩展处理
+                
+    '''
+    
+    def __init__(self, lineID, objID, npcID):
+        GameWorld.DebugLog("加载NPC伤血列表!", npcID, lineID)
+        self.lineID = lineID
+        self.objID = objID
+        self.npcID = npcID
+        self.curNPC = GameWorld.FindNPCByID(objID)
+        
+        self.__hurtPlayerDict = {} # 所有伤血玩家个体实例字典 {playerID:HurtValueObj, ...}
+        
+        self.__hurtSortList = []
+        self.__hurtDict = {} # 伤血列表实例字典,实际的NPC伤血列表实例,可能不是玩家{(hurtID, hurtType):HurtValueObj, ...}
+        
+        self.checkHurtValidFunc = None # 检查伤血有效性函数,无效伤血清除,可不设置,则不检查
+        self.getHurtObjPlayerIDListFunc = None # 获取伤血团体实例包含的玩家ID列表,可不设置,则按伤血类型取对应默认ID列表
+        self.onKilledFunc = None # npc被击杀后续处理函数,可不设置
+        return
+    
+    def Clear(self):
+        GameWorld.DebugLog("清除NPC伤血列表!", self.npcID, self.lineID)
+        
+        self.__hurtSortList = []
+        self.__hurtDict = {}
+        # 重置所有玩家伤血值
+        for hurtObj in self.__hurtPlayerDict.values():
+            hurtObj.SetHurtValue(0)
+        return
+    
+    def OnDelete(self):
+        return
+    
+    def __GetHurtObj(self, hurtID, hurtType, hurtName=""):
+        ## 获取伤血列表伤血类型实例,可能是个人、队伍、家族、阵营等
+        hurtObj = None
+        hurtKey = (hurtID, hurtType)
+        if hurtKey not in self.__hurtDict:
+            GameWorld.DebugLog("添加伤血列表对象: hurtID=%s,hurtType=%s" % (hurtID, hurtType), self.npcID, self.lineID)
+            hurtObj = HurtValueObj()
+            hurtObj.SetValueID(hurtID)
+            hurtObj.SetValueType(hurtType)
+            hurtObj.SetHurtName(hurtName)
+            self.__hurtDict[hurtKey] = hurtObj
+        hurtObj = self.__hurtDict[hurtKey]
+        return hurtObj
+    
+    def __GetHurtPlayer(self, playerID, playerName=""):
+        ## 获取伤血玩家实例, 每个玩家独立, 且伤血独立统计
+        hurtPlayer = None
+        if playerID not in self.__hurtPlayerDict:
+            GameWorld.DebugLog("添加伤血玩家: playerID=%s,playerName=%s" % (playerID, playerName), self.npcID, self.lineID)
+            hurtPlayer = HurtValueObj()
+            hurtPlayer.SetValueID(playerID)
+            #hurtPlayer.SetHurtName(playerName)
+            self.__hurtPlayerDict[playerID] = hurtPlayer
+        hurtPlayer = self.__hurtPlayerDict[playerID]
+        # 因为伤血玩家可能在某些情况下创建了没有名字的实例,所以这里在有传入名字时进行强制更新
+        if playerName:
+            hurtPlayer.SetHurtName(playerName)
+        return hurtPlayer
+    
+    def AddHurtValue(self, playerID, playerName, addValue, hurtType, hurtID, hurtName):
+        ''' 添加伤血
+        @param playerID: 贡献伤害的玩家ID
+        @param playerName: 贡献伤害的玩家名
+        @param addValue: 贡献伤害值
+        @param hurtType: 伤血团体实例类型,可能是玩家个人、队伍、家族、阵营等
+        @param hurtID: 伤血团体实例ID
+        @param hurtName: 伤血团体实例名
+        '''
+        
+        hurtObj = self.__GetHurtObj(hurtID, hurtType, hurtName)
+        
+        # 伤血列表伤血累加,某个团体的累计伤害
+        befValue = hurtObj.GetHurtValue()
+        updValue = befValue + addValue
+        hurtObj.SetHurtValue(updValue)
+        isNewHurt = befValue == 0 and updValue > 0
+        
+        hurtPlayer = self.__GetHurtPlayer(playerID, playerName)
+        # 伤血玩家伤血累加,这个仅伤血玩家自己的个人输出,非伤血列表中的汇总输出
+        updHurtPlayerValue = hurtPlayer.GetHurtValue() + addValue
+        hurtPlayer.SetHurtValue(updHurtPlayerValue)
+        
+        #GameWorld.DebugLog("    hurtID=%s,hurtType=%s,updValue=%s (%s + %s), playerID=%s,updHurtPlayerValue=%s" 
+        #                   % (hurtID, hurtType, updValue, befValue, addValue, playerID, updHurtPlayerValue), self.npcID, self.lineID)
+        if isNewHurt:
+            self.__Sort()
+            
+        return isNewHurt
+    
+    def __CmpHurtValue(self, hurtObjA, hurtObjB):
+        ## 伤害排序比较函数
+        if hurtObjA.GetHurtValue() > hurtObjB.GetHurtValue():
+            return 1
+        if hurtObjA.GetHurtValue() == hurtObjB.GetHurtValue():
+            return 0
+        return -1
+    
+    def __Sort(self):
+        ## 伤血排序
+        self.__hurtSortList = sorted(self.__hurtDict.values(), cmp=self.__CmpHurtValue, reverse=True)
+        return
+    
+    def __SyncHurtList(self):
+        ## 同步前端伤血列表
+        
+        syncPlayerIDList = []
+        # 暂定排序后默认同步伤血列表给所有相关玩家,伤血为0的不同步前端,仅用于后端逻辑用
+        hurtValueList = []
+        for hurtObj in self.__hurtSortList:
+            hurtValue = hurtObj.GetHurtValue()
+            if not hurtValue:
+                continue
+            syncPlayerIDList += self.__GetHurtObjAllPlayerID(hurtObj)
+            
+            hurtValueObj = ChPyNetSendPack.tagMCBossHurtValue()
+            hurtValueObj.HurtID = hurtObj.GetValueID()
+            hurtValueObj.HurtType = hurtObj.GetValueType()
+            hurtValueObj.HurtName = hurtObj.GetHurtName()
+            hurtValueObj.HurtValue = hurtValue % ShareDefine.Def_PerPointValue
+            hurtValueObj.HurtValueEx = hurtValue / ShareDefine.Def_PerPointValue
+            hurtValueList.append(hurtValueObj)
+            
+        if not syncPlayerIDList:
+            return
+        
+        bossHurtInfoPack = ChPyNetSendPack.tagMCBossHurtValueRankInfo()
+        bossHurtInfoPack.ObjID = self.objID
+        bossHurtInfoPack.HurtValueList = hurtValueList
+        bossHurtInfoPack.HurtCount = len(hurtValueList)
+        
+        curNPC = self.curNPC
+        copyPlayerManager = GameWorld.GetMapCopyPlayerManager()
+        for playerID in syncPlayerIDList:
+            player = copyPlayerManager.FindPlayerByID(playerID)
+            if not player:
+                continue
+            if not player.CanSeeOther(curNPC):
+                continue
+            NetPackCommon.SendFakePack(player, bossHurtInfoPack)
+            
+        return
+    
+    def RefreshHurtList(self, tick, refreshInterval=3000, isKilled=False):
+        '''刷新伤血列表
+        @return: atkPlayer, hurtID, hurtType
+        '''
+        
+        curNPC = self.curNPC
+        
+        if not isKilled:
+            if refreshInterval and tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < refreshInterval:
+                return self.__GetAtkObj(isKilled)
+            
+        curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)
+        
+        # 1. 检查清除无效伤血
+        if self.checkHurtValidFunc:
+            self.checkHurtValidFunc()
+            
+        # 2. 排序
+        self.__Sort()
+        
+        # 3. 同步前端
+        self.__SyncHurtList()
+        
+        # 4. 击杀附加逻辑
+        if isKilled:
+            if self.onKilledFunc:
+                self.onKilledFunc()
+                
+        return self.__GetAtkObj(isKilled)
+    
+    def __GetAtkObj(self, isKilled):
+        '''第一个可攻击的最大伤血对象
+        @return: atkPlayer, hurtType, hurtID
+        '''
+        
+        atkPlayer, atkHurtType, atkHurtID = None, 0, 0
+        curNPC = self.curNPC
+        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
+        for rank, hurtObj in enumerate(self.__hurtSortList, 1):
+            
+            hurtID = hurtObj.GetValueID()
+            hurtType = hurtObj.GetValueType()
+            
+            playerIDList = self.__GetHurtObjAllPlayerID(hurtObj)
+            
+            playerDisableReason = {}
+            maxHurtValue = 0
+            for playerID in playerIDList:
+                
+                player = GameWorld.GetObj(playerID, IPY_GameWorld.gotPlayer)
+                if player == None:
+                    continue
+                
+                if player.GetHP() <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie:
+                    playerDisableReason[playerID] = "dead"
+                    continue
+                
+                if not player.GetVisible() or player.GetSightLevel() != curNPC.GetSightLevel():
+                    playerDisableReason[playerID] = "no visible or sightLevel different"
+                    continue
+                
+                if not self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
+                    playerDisableReason[playerID] = "not in boss area"
+                    continue
+                
+                if playerID not in self.__hurtPlayerDict:
+                    playerDisableReason[playerID] = "no hurt"
+                    continue
+                hurtPlayer = self.__hurtPlayerDict[playerID]
+                hurtValue = hurtPlayer.GetHurtValue()                
+                if hurtValue > maxHurtValue:
+                    maxHurtValue = hurtValue
+                    atkPlayer, atkHurtType, atkHurtID = player, hurtType, hurtID
+                    
+            if maxHurtValue:
+                return atkPlayer, atkHurtType, atkHurtID
+            
+            if rank == 1 and isKilled:
+                pass
+                #GameWorld.Log("boss死亡时,第一名团队没有归属权! playerDisableReason=%s" % playerDisableReason)
+                
+        return atkPlayer, atkHurtType, atkHurtID
+    
+    def __GetHurtObjAllPlayerID(self, hurtObj):
+        ## 获取伤血实例团体所有的玩家ID
+        
+        hurtID = hurtObj.GetValueID()
+        hurtType = hurtObj.GetValueType()
+        if self.getHurtObjPlayerIDListFunc:
+            return self.getHurtObjPlayerIDListFunc(hurtObj)
+        
+        if hurtType == ChConfig.Def_NPCHurtTypePlayer:
+            return [hurtID]
+        
+        if hurtType == ChConfig.Def_NPCHurtTypeTeam:
+            teamID = hurtID
+            return PlayerTeam.GetMapTeamPlayerIDList(teamID)
+        
+        return []
+    
+    def GetIsInRefreshPoint(self, curPosX, curPosY, refreshPoint):
+        if not refreshPoint:
+            return False
+        
+        if (curPosX >= refreshPoint.GetPosX() - refreshPoint.GetMoveDist() and
+                curPosX <= refreshPoint.GetPosX() + refreshPoint.GetMoveDist() and
+                curPosY >= refreshPoint.GetPosY() - refreshPoint.GetMoveDist() and
+                curPosY <= refreshPoint.GetPosY() + refreshPoint.GetMoveDist()):
+            return True
+        
+        return False
+    
+    def GetHurtCount(self): return len(self.__hurtSortList)
+    def GetHurtAt(self, index): return self.__hurtSortList[index]
+    
+    def GetMaxHurtValue(self): return None if not self.__hurtSortList else self.__hurtSortList[0]
+    def GetLastTimeHurtValue(self):
+        return
+    
+class PlayerRankHurtList(HurtValueObjList):
+    ''' 排行伤血列表子类, 类似 IPY_GameObj.IPY_PlayerHurtList
+                    伤血列表规则:
+                            统计归属类型为 ChConfig.DropOwnerType_RankHurtPlayer
+                            不支持协助,仅统计个人伤害,不清伤血,根据玩家排名发放邮件奖励
+    '''
+    
+    def __init__(self, lineID, objID, npcID):
+        super(PlayerRankHurtList, self).__init__(lineID, objID, npcID)
+        
+        self.onKilledFunc = self.__DoNPCOnKilledLogic
+        return
+    
+    def Clear(self):
+        ## 该列表不清伤血,重写Clear函数
+        GameWorld.DebugLog("不清NPC伤血列表!", self.npcID, self.lineID)
+        
+        return
+    
+    def AddHurtValue(self, atkPlayer, addValue):
+        ## 添加玩家排行伤血
+        playerID = atkPlayer.GetPlayerID()
+        playerName = atkPlayer.GetPlayerName()
+        hurtType = ChConfig.Def_NPCHurtTypePlayer # 该列表只默认玩家
+        super(PlayerRankHurtList, self).AddHurtValue(playerID, playerName, addValue, hurtType, playerID, playerName)
+        return
+    
+    def __DoNPCOnKilledLogic(self):
+        ## 执行NPC击杀后续处理逻辑
+        
+        if self.npcID == IpyGameDataPY.GetFuncCfg("BossRebornServerBoss", 3):
+            PlayerBossReborn.DoBossRebornActionBossOnKilledLogic(self)
+            
+        ## 同样榜单逻辑的不同功能奖励处理 ...
+        
+        return
+
+def __GetBossLineID(npcID):
+    return GameWorld.GetGameWorld().GetLineID()
+
+def ClearPlayerHurtList(curNPC):
+    ## 清空伤血列表 - 重置NPC状态时调用
+    
+    objID = curNPC.GetID()
+    npcID = curNPC.GetNPCID()
+    lineID = __GetBossLineID(npcID)
+    key = (lineID, objID, npcID)
+    
+    if key in PyGameData.g_npcHurtListDict:
+        hurtList = PyGameData.g_npcHurtListDict[key]
+        hurtList.Clear()
+        
+    return
+
+def DeletePlayerHurtList(curNPC):
+    ## 删除伤血列表 - NPC死亡时调用
+    
+    objID = curNPC.GetID()
+    npcID = curNPC.GetNPCID()
+    lineID = __GetBossLineID(npcID)
+    key = (lineID, objID, npcID)
+    
+    if key in PyGameData.g_npcHurtListDict:
+        hurtList = PyGameData.g_npcHurtListDict.pop(key)
+        hurtList.OnDelete()
+        
+    return
+
+def RefreshHurtList(curNPC, tick, refreshInterval=3000, isKilled=False):
+    ## 刷新伤血列表
+    # @return: atkPlayer, ownerType, ownerID
+    
+    objID = curNPC.GetID()
+    npcID = curNPC.GetNPCID()
+    lineID = __GetBossLineID(npcID)
+    key = (lineID, objID, npcID)
+    
+    if key not in PyGameData.g_npcHurtListDict:
+        return
+    hurtList = PyGameData.g_npcHurtListDict[key]
+    return hurtList.RefreshHurtList(tick, refreshInterval, isKilled)
+
+def AddHurtValue(atkPlayer, defNPC, value, isBounce):
+    '''添加伤血
+    @param isBounce: 是否反弹伤害,反弹伤害不计入非主动攻击的玩家伤血,因为规定玩家攻击另一个boss则要清除同地图上一个boss的该玩家伤害
+                                                        防止死亡回复活点跑图中被主动型boss攻击计入伤血导致清除同地图上一个主动攻击的boss伤血
+    '''
+    
+    if not ChConfig.IsGameBoss(defNPC):
+        return
+    
+    ## 根据个人伤血排行直接给奖励的
+    if NPCCommon.GetDropOwnerType(defNPC) == ChConfig.DropOwnerType_RankHurtPlayer:
+        hurtList = __AddNewHurtList(defNPC, PlayerRankHurtList)
+        
+    ## 其他伤血列表子类管理 ...
+    
+    else:
+        return
+    
+    return hurtList.AddHurtValue(atkPlayer, value)
+
+def __AddNewHurtList(curNPC, className):
+    objID = curNPC.GetID()
+    npcID = curNPC.GetNPCID()
+    lineID = __GetBossLineID(npcID)
+    key = (lineID, objID, npcID)
+    if key not in PyGameData.g_npcHurtListDict:
+        hurtList = className(lineID, objID, npcID)
+        PyGameData.g_npcHurtListDict[key] = hurtList
+    hurtList = PyGameData.g_npcHurtListDict[key]
+    return hurtList
+
+def GetPlayerHurtList(curNPC):
+    ''' 获取伤血列表,可能为None
+    '''
+    
+    if not ChConfig.IsGameBoss(curNPC):
+        return
+    
+    objID = curNPC.GetID()
+    npcID = curNPC.GetNPCID()
+    lineID = __GetBossLineID(npcID)
+    key = (lineID, objID, npcID)
+    if key not in PyGameData.g_npcHurtListDict:
+        return
+    
+    return PyGameData.g_npcHurtListDict[key]
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBossReborn.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBossReborn.py
index 0457521..95e4582 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBossReborn.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBossReborn.py
@@ -255,3 +255,36 @@
     actInfo.TaskCnt = len(actInfo.TaskInfo)
     NetPackCommon.SendFakePack(curPlayer, actInfo)
     return
+
+def DoBossRebornActionBossOnKilledLogic(npcRankHurtMgr):
+    ## boss复活活动boss被击杀
+    #  @param rankHurtList: NPCHurtMgr.PlayerRankHurtList
+    
+    npcID = npcRankHurtMgr.npcID
+    
+    GameWorld.Log("Boss复活活动boss被击杀: npcID=%s" % (npcID))
+    rankItemDict = IpyGameDataPY.GetFuncEvalCfg("BossRebornServerBoss", 2) # {名次:[[物品ID,个数,是否拍品], ...], ...}
+    
+    for index in xrange(npcRankHurtMgr.GetHurtCount()):
+        rank = index + 1
+        hurtObj = npcRankHurtMgr.GetHurtAt(index)
+        if hurtObj.GetValueType() != ChConfig.Def_NPCHurtTypePlayer:
+            continue
+        playerID = hurtObj.GetValueID()
+        rankItemList = GameWorld.GetOrderValueByDict(rankItemDict, rank)
+        GameWorld.Log("    排行玩家奖励: rank=%s,rankItemList=%s" % (rank, rankItemList), playerID)
+        if not rankItemList:
+            continue
+        paramList = [npcID, rank]
+        PlayerControl.SendMailByKey("BossRebornActionBossRank", [playerID], rankItemList, paramList)
+        
+    entireMailItemList = IpyGameDataPY.GetFuncEvalCfg("BossRebornServerBoss", 1) # [[物品ID,个数,是否拍品], ...]
+    if entireMailItemList:
+        getDays, limitLV, limitLVType = IpyGameDataPY.GetFuncEvalCfg("BossRebornServerBoss", 4)
+        paramList = [npcID]
+        PlayerControl.SendEntireMail("BossRebornActionBossAll", getDays, limitLV, limitLVType, entireMailItemList, paramList)
+        
+    return
+
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 5c552b2..6ad330b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -362,6 +362,30 @@
     GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_SendMail, dataMsg, [serverGroupID])
     return
 
+def SendEntireMail(mailTypeKey, getDays, limitLV, limitLVType, addItemList=[], paramList=[], \
+                   gold=0, goldPaper=0, silver=0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail):
+    ''' 发送全服邮件
+    @param mailTypeKey: 邮件模板key
+    @param getDays: 有效天数
+    @param limitLV: 领取最低等级限制
+    @param limitLVType: 等级不足的升级后是否可领 0-不可,1-可以
+    '''
+    
+    # 有效天数限制
+    if not mailTypeKey or getDays <= 0:
+        return
+    
+    # 跨服服务器不允许发送邮件
+    if GameWorld.IsCrossServer():
+        return
+    
+    combineItemList = CombineMailItem(addItemList)
+    cmdList = [mailTypeKey, getDays, limitLV, limitLVType, combineItemList, paramList, gold, goldPaper, silver, detail, moneySource]
+    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "SendEntireMail", '%s' % (cmdList), len(str(cmdList)))
+    GameWorld.Log("发送全服邮件: %s,getDays=%s,limitLV=%s,limitLVType=%s,combineItemList=%s,paramList=%s,gold=%s,goldPaper=%s,silver=%s,detail=%s,moneySource=%s" % 
+                  (mailTypeKey, getDays, limitLV, limitLVType, combineItemList, paramList, gold, goldPaper, silver, detail, moneySource))
+    return
+
 ## 功能发放物品补偿/奖励邮件
 #  @param addItemList [(itemID, itemCnt, 是否拍品), {或物品信息字典}, ...]
 #  @return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index e288d29..91d760f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -29,7 +29,8 @@
 
 g_filterEquipDict = {} # 按装备条件过滤的装备ID,不分职业 {"classLV_color_star":{(itemJob,itemPlace):itemID, ...}, ...}
 
-g_npcHurtDict = {} # npc伤血列表信息字典 {(lineID,objID,npcID):PlayerHurtList, ...}
+g_npcHurtDict = {} # npc伤血列表信息字典,协助版 {(lineID,objID,npcID):PlayerHurtList, ...}
+g_npcHurtListDict = {} # npc伤血排行列表信息字典 {(lineID,objID,npcID):HurtValueObjList, ...}
 
 g_teamPlayerHurtValue = {} # 队伍玩家对NPC伤害输出量 {(lineID, objID, npcID):{(teamID, playerID):hurtValue, ...}, }
 g_teamPlayerDict = {} # 地图队伍对应玩家ID列表,含离线玩家 {teamID:[playerID, ...], ...}

--
Gitblit v1.8.0