8401 【后端】BOSS复活修改(全服奖励邮件、排名奖励邮件发放)
新增发送全服邮件;新增伤血列表邮件发放奖励模块管理;
10个文件已修改
1个文件已添加
601 ■■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldBoss.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerCompensation.py 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py 453 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBossReborn.py 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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
    
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
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)
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 攻击镖车只算个人伤害
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)
#------------------------------------------------
#技能类型
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):
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,8 +5185,10 @@
            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 not maxHurtInfo:
            maxHurtInfo = NPCHurtMgr.RefreshHurtList(curNPC, tick, refreshInterval, isDead)
            if maxHurtInfo:
                tagObj, ownerType, ownerID = maxHurtInfo
                
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py
New file
@@ -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]
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
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
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, ...], ...}