9748 【BT7】跨服BOSS定时活动(跨服妖魔boss;增加跨服日常活动时间控制;Boss刷新增加支持关联跨服日常活动;优化跨服boss复活剩余时间计算使用跨服时间;)

# Conflicts:
# ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
# ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
20个文件已修改
3个文件已添加
974 ■■■■■ 已修改文件
PySysDB/PySysDBG.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossYaomoBoss.py 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerEventCounter.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossYaomoBoss.py 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossYaomoBoss.py 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBG.h
@@ -85,6 +85,16 @@
    list        RandMailKeyList;    //指定上架随机邮件列表,有配置时上架的时候在线玩家会收到一封上架邮件提醒
};
//跨服日常活动表
struct tagCrossDailyAction
{
    DWORD        _DailyID;    //活动ID
    dict        OpenTimeDict;    //开启时间
    DWORD        Duration;    //持续时间, 0为不限制
    dict        NotifyInfo;    //广播提示信息
};
//日常活动表
struct tagDailyAction
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -15140,6 +15140,66 @@
#------------------------------------------------------
# C0 11 跨服妖魔boss玩家伤害信息 #tagGCCrossYaomoBossPlayerHurtInfo
class  tagGCCrossYaomoBossPlayerHurtInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HurtTotal", c_int),    # 总伤害值,小于亿部分
                  ("HurtTotalEx", c_int),    # 总伤害值,整除亿部分
                  ("AwardState", c_int),    # 伤害目标值领奖状态,按奖励记录索引位运算判断是否已领取
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xC0
        self.SubCmd = 0x11
        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 = 0xC0
        self.SubCmd = 0x11
        self.HurtTotal = 0
        self.HurtTotalEx = 0
        self.AwardState = 0
        return
    def GetLength(self):
        return sizeof(tagGCCrossYaomoBossPlayerHurtInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// C0 11 跨服妖魔boss玩家伤害信息 //tagGCCrossYaomoBossPlayerHurtInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                HurtTotal:%d,
                                HurtTotalEx:%d,
                                AwardState:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HurtTotal,
                                self.HurtTotalEx,
                                self.AwardState
                                )
        return DumpString
m_NAtagGCCrossYaomoBossPlayerHurtInfo=tagGCCrossYaomoBossPlayerHurtInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossYaomoBossPlayerHurtInfo.Cmd,m_NAtagGCCrossYaomoBossPlayerHurtInfo.SubCmd))] = m_NAtagGCCrossYaomoBossPlayerHurtInfo
#------------------------------------------------------
# C0 14 幸运云购开奖记录 #tagGCLuckyCloudBuyLotteryRecInfo
class  tagGCLuckyCloudBuyLotteryRec(Structure):
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
@@ -673,3 +673,190 @@
        
    return
## ================================================================================================
def __GetTodayCrossDailyActionInfo():
    # 获取本日待处理的日常活动信息
    key = "TodayCrossDailyActionInfo"
    curTime = int(time.time())
    curDateStr = GameWorld.ChangeTimeNumToStr(curTime, ChConfig.TYPE_Time_YmdFormat) # 当天日期
    loadSign = curDateStr
    TodayDailyActionInfo = IpyGameDataPY.GetConfigEx(key)
    if TodayDailyActionInfo and TodayDailyActionInfo[0] == loadSign:
        GameWorld.DebugLog("已经加载过本日跨服日常活动处理信息!loadSign=%s" % loadSign)
        return TodayDailyActionInfo[1]
    todayActionInfo = []
    dayTime = GameWorld.GetServerTime()
    weekDay = str(dayTime.weekday() + 1) # 格式为json, 当前星期几, 1代表星期1
    GameWorld.Log("===== 加载今天跨服日常活动信息 =====")
    GameWorld.Log("当前星期%s" % weekDay)
    dailyTimeInfoList = []
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for i in xrange(ipyDataMgr.GetCrossDailyActionCount()):
        dailyIpyData = ipyDataMgr.GetCrossDailyActionByIndex(i)
        dailyID = dailyIpyData.GetDailyID()
        openTimeDict = dailyIpyData.GetOpenTimeDict()
        # 没有时间控制的,代表永久开放
        if not openTimeDict:
            todayActionInfo.append([dailyID])
            GameWorld.Log("    增加本日常开跨服日常活动信息: dailyID=%s" % dailyID)
            continue
        #如果星期key中存在 "0" 代表每日都开启
        if "0" not in openTimeDict and weekDay not in openTimeDict:
            GameWorld.Log("    不是跨服日常活动开启星期: dailyID=%s,openWeekLimit=%s" % (dailyID, openTimeDict.keys()))
            continue
        openTimeList = openTimeDict["0"] if "0" in openTimeDict else openTimeDict[weekDay]
        dailyTimeInfoList.append([openTimeList, dailyIpyData])
    GameWorld.Log("    -----------------------")
    for openTimeList, ipyData in dailyTimeInfoList:
        dailyID = ipyData.GetDailyID()
        notifyInfoDict = ipyData.GetNotifyInfo()
        openList = [] # [(时,分), ...]
        overList = [] # [(时,分), ...]
        goonStateDict = {} # {״̬:[(aDateTime, bDateTime)], ...}
        notifyDict = {} # {(时,分):[notifyKey, [参数]], ...}
        OpenState = 1 # 定义开启状态为1
        for hour, minute in openTimeList:
            openTimeStr = "%s %02d:%02d:%02d" % (curDateStr, hour, minute, 0)
            # 精确开启时间
            openDateTime = datetime.datetime.strptime(openTimeStr, ChConfig.TYPE_Time_Format)
            openList.append((openDateTime.hour, openDateTime.minute))
            # 精确关闭时间
            overDateTime = openDateTime + datetime.timedelta(minutes=ipyData.GetDuration())
            overList.append((overDateTime.hour, overDateTime.minute))
            # goon 开启状态
            openStateTimeList = goonStateDict.get(OpenState, [])
            openStateTimeList.append((openDateTime, overDateTime))
            goonStateDict[OpenState] = openStateTimeList
            # goon 其他状态,待扩展
            # ...
            # 广播
            for notifyMinute, notifyInfo in notifyInfoDict.items():
                notifyDateTime = openDateTime + datetime.timedelta(minutes=notifyMinute)
                notifyDict[(notifyDateTime.hour, notifyDateTime.minute)] = notifyInfo
        todayActionInfo.append([dailyID, openList, overList, goonStateDict, notifyDict])
        GameWorld.Log("    增加本日跨服日常活动信息: dailyID=%s,openList=%s,overList=%s,goonStateDict=%s,notifyDict=%s"
                      % (dailyID, openList, overList, goonStateDict, notifyDict))
    TodayDailyActionInfo = IpyGameDataPY.SetConfigEx(key, [loadSign, todayActionInfo])
    GameWorld.Log("本日跨服日常活动信息加载完毕! loadSign=%s" % loadSign)
    GameWorld.Log("=============================================================")
    return TodayDailyActionInfo[1]
def Dispose_CrossDailyActionState():
    # 跨服日常活动状态变更检查处理
    todayDailyActionInfo = __GetTodayCrossDailyActionInfo()
    if not todayDailyActionInfo:
        return
    gameWorld = GameWorld.GetGameWorld()
    dayTime = GameWorld.GetServerTime()
    curHourMinute = (dayTime.hour, dayTime.minute)
    sysnCrossDailyActionStateDict = {}
    for actionInfo in todayDailyActionInfo:
        dailyActionID = actionInfo[0]
        state = 0 # 默认关闭
        # 长度为1的代表常开的活动
        if len(actionInfo) == 1:
            state = 1
        else:
            #openList = [] # [(时,分), ...]
            #overList = [] # [(时,分), ...]
            #goonStateDict = {} # {״̬:[(aDateTime, bDateTime)], ...}
            #notifyDict = {} # {(时,分):[notifyKey, [参数]], ...}
            openList, overList, goonStateDict, notifyDict = actionInfo[1:]
            # 精确匹配开启
            if curHourMinute in openList:
                state = 1
            # 精确匹配关闭
            elif curHourMinute in overList:
                state = 0
            # goon ״̬
            else:
                for goonState, openStateTimeList in goonStateDict.items():
                    for dateTimeInfo in openStateTimeList:
                        if dateTimeInfo[0] < dayTime < dateTimeInfo[1]:
                            state = goonState
                            break
            # 全服广播提示信息
            if curHourMinute in notifyDict:
                notifyKey, paramList = notifyDict[curHourMinute]
                serverGroupIDList = []
                PlayerControl.WorldNotifyCross(serverGroupIDList, 0, notifyKey, paramList)
        dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID
        beforeState = gameWorld.GetDictByKey(dictName)
        if beforeState == state:
            #已经是这个状态了
            continue
        if state:
            if dailyActionID == ShareDefine.CrossDailyActionID_YaomoBoss:
                GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_ActionBossRebornSign % dailyActionID, int(time.time()))
        sysnCrossDailyActionStateDict[dailyActionID] = state
        #通知Mapserver,设置字典
        GameWorld.SendMapServerMsgEx(dictName, state)
        #更新字典值
        gameWorld.SetDict(dictName, state)
        GameWorld.Log("跨服日常活动状态变更: dailyActionID=%s,state=%s,dictName=%s" % (dailyActionID, state, dictName))
    # 同步子服务器
    if sysnCrossDailyActionStateDict:
        serverGroupIDList = []
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossDailyActionState, sysnCrossDailyActionStateDict, serverGroupIDList)
    return
def SendMapServerCrossDailyActionState():
    # 地图启动成功时通知本日进行中的日常活动状态
    todayDailyActionInfo = __GetTodayCrossDailyActionInfo()
    if not todayDailyActionInfo:
        return
    gameWorld = GameWorld.GetGameWorld()
    for actionInfo in todayDailyActionInfo:
        dailyActionID = actionInfo[0]
        dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID
        state = gameWorld.GetDictByKey(dictName)
        if state:
            GameWorld.SendMapServerMsgEx(dictName, state)
    return
def CrossServerMsg_CrossDailyActionState(msgData):
    gameWorld = GameWorld.GetGameWorld()
    for dailyActionID, state in msgData.items():
        dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID
        #通知Mapserver,设置字典
        GameWorld.SendMapServerMsgEx(dictName, state)
        #更新字典值
        gameWorld.SetDict(dictName, state)
        GameWorld.Log("收到跨服日常活动状态变更: dailyActionID=%s,state=%s,dictName=%s" % (dailyActionID, state, dictName))
    return
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
@@ -61,6 +61,13 @@
            self.__billboardDict[key] = billboardObj
        return billboardObj
    
    def RemoveBillboard(self, billboardType):
        ## 移除某个类型的榜单所有数据
        for key in self.__billboardDict.keys():
            if key[0] == billboardType:
                self.__billboardDict.pop(key)
        return
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
        savaData = ""
@@ -249,6 +256,37 @@
        for billboardType, groupValue1, groupValue2 in groupList:
            billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
            billboardObj.SaveDRData()
    return
def CopyBillboard(fromBillboardType, toBillboardType):
    ## 将某个类型的榜单完全拷贝到其他榜单 - 一般用于备份、转移数据
    billboardMgr = PyDataManager.GetCrossBillboardManager()
    billboardMgr.RemoveBillboard(toBillboardType) # 默认清空目标榜单
    groupList = billboardMgr.GetBillboardGroupList(fromBillboardType)
    for billboardType, groupValue1, groupValue2 in groupList:
        frbillboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
        toBillboardObj = billboardMgr.GetCrossBillboard(toBillboardType, groupValue1, groupValue2)
        GameWorld.Log("CopyCrossBillboard: billboardType=%s,toBillboardType=%s,groupValue1=%s,groupValue2=%s"
                      % (billboardType, toBillboardType, groupValue1, groupValue2))
        for frbillboardData in frbillboardObj.GetBillboardDataList():
            tobillboardData = PyGameDataStruct.tagDBCrossBillboard()
            tobillboardData.GroupValue1 = groupValue1
            tobillboardData.GroupValue2 = groupValue2
            tobillboardData.BillboardType = toBillboardType
            tobillboardData.ID = frbillboardData.ID
            tobillboardData.ID2 = frbillboardData.ID2
            tobillboardData.Name1 = frbillboardData.Name1
            tobillboardData.Name2 = frbillboardData.Name2
            tobillboardData.Type2 = frbillboardData.Type2
            tobillboardData.Value1 = frbillboardData.Value1
            tobillboardData.Value2 = frbillboardData.Value2
            tobillboardData.CmpValue = frbillboardData.CmpValue
            tobillboardData.CmpValue2 = frbillboardData.CmpValue2
            tobillboardData.CmpValue3 = frbillboardData.CmpValue3
            toBillboardObj.AddBillboardData(tobillboardData)
    return
#// C0 04 查看跨服排行榜 #tagCGViewCrossBillboard
@@ -470,7 +508,7 @@
    return
def UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
                      cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True):
                      cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True, noSortAndSync=False):
    ''' 更新跨服排行榜
    @param billboardType: 排行榜索引类型,同个榜单类型可以有多个分组榜单数据,独立排序
    @param groupValue1: 榜单分组1
@@ -486,6 +524,7 @@
    @param groupValue1: 榜单分组2
    @param id2: 扩展数据ID2
    @param autoSort: 是否排序,默认True
    @param noSortAndSync: 不排序及同步子服,默认False; 一般用于批量更新数据时设置为True,减少排序及同步频率,但是一定要在设置完数据或最后一条数据后手动调用一次排序SortData
    @return: 是否上榜更新榜单
    '''
    if not GameWorld.IsCrossServer():
@@ -542,6 +581,8 @@
                       % (billboardType, groupValue1, groupValue2, dataID, isNewData, cmpValueChange,
                          type2, value1, value2, cmpValue, cmpValue2, cmpValue3), dataID)
    
    if noSortAndSync:
        return True
    if autoSort and cmpValueChange:
        billboardObj.SortData()
    else:
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBoss.py
@@ -441,7 +441,7 @@
def Sync_CrossBossInfo(curPlayer=None, syncBOSSIDList=[]):
    ## 同步boss相关信息
    
    curTime = int(time.time())
    curTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCrossServerTimeStr())
    
    recTypeListData = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_CrossBossInfo)
    
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossYaomoBoss.py
New file
@@ -0,0 +1,274 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package CrossYaomoBoss
#
# @todo:跨服妖魔boss
# @author hxp
# @date 2022-11-11
# @version 1.0
#
# 详细描述: 跨服妖魔boss
#
#-------------------------------------------------------------------------------
#"""Version = 2022-11-11 15:30"""
#-------------------------------------------------------------------------------
import ShareDefine
import PyDataManager
import CrossRealmMsg
import IpyGameDataPY
import CrossBillboard
import ChPyNetSendPack
import PlayerCompensation
import CrossRealmPlayer
import PlayerViewCache
import NetPackCommon
import PlayerControl
import PyGameData
import GameWorld
Def_RecType_CrossYaomoBossHurtInfo = ShareDefine.Def_UniversalGameRecType_CrossYaomoBossHurtInfo
'''
跨服妖魔boss伤血信息
ShareDefine.Def_UniversalGameRecType_CrossYaomoBossHurtInfo
value1:zoneID              分区ID
value2:playerID            玩家ID
value3:awardState          目标伤害领奖记录
StrValue1:hurtTotal        今日总伤害
'''
def GetRecZoneID(recData): return recData.GetValue1()
def SetRecZoneID(recData, zoneID): return recData.SetValue1(zoneID)
def GetRecPlayerID(recData): return recData.GetValue2()
def SetRecPlayerID(recData, playerID): return recData.SetValue2(playerID)
def GetRecAwardState(recData): return recData.GetValue3()
def SetRecAwardState(recData, awardState): return recData.SetValue3(awardState)
def GetRecHurtTotal(recData): return GameWorld.ToIntDef(recData.GetStrValue1(), 0)
def SetRecHurtTotal(recData, hurtTotal): return recData.SetStrValue1(str(hurtTotal))
def DoOnDay():
    if not GameWorld.IsCrossServer():
        return
    hurtValueAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossYaomoBoss", 3, {})
    hurtValueIntAwardDict = {int(k):v for k, v in hurtValueAwardDict.items()}
    universalRecMgr = GameWorld.GetUniversalRecMgr()
    recDataList = universalRecMgr.GetTypeList(Def_RecType_CrossYaomoBossHurtInfo)
    for index in xrange(recDataList.Count()):
        recData = recDataList.At(index)
        playerID = GetRecPlayerID(recData)
        awardState = GetRecAwardState(recData)
        hurtTotal = GetRecHurtTotal(recData)
        for awardIndex, hurtValueInfo in hurtValueIntAwardDict.items():
            needHurtValue, awardItemList = hurtValueInfo
            if hurtTotal < needHurtValue:
                continue
            if awardState & pow(2, awardIndex):
                continue
            paramList = [needHurtValue]
            PlayerCompensation.SendMailByKey("CrossYaomoBossHurtValue", [playerID], awardItemList, paramList, crossMail=True)
    universalRecMgr.Delete(Def_RecType_CrossYaomoBossHurtInfo)
    # 广播子服重置伤害
    serverGroupIDList = []
    sendMsg = {"HurtReset":1}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossYaomoBossHurtInfo, sendMsg, serverGroupIDList)
    return
def ClientServerMsg_CrossYaomoBossHurtAward(serverGroupID, msgData):
    playerID = msgData["playerID"]
    awardIndex = msgData["awardIndex"]
    hurtValueAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossYaomoBoss", 3, {})
    if str(awardIndex) not in hurtValueAwardDict:
        return
    needHurtValue, awardItemList = hurtValueAwardDict[str(awardIndex)]
    universalRecMgr = GameWorld.GetUniversalRecMgr()
    recDataList = universalRecMgr.GetTypeList(Def_RecType_CrossYaomoBossHurtInfo)
    for index in xrange(recDataList.Count()):
        recData = recDataList.At(index)
        if playerID != GetRecPlayerID(recData):
            continue
        awardState = GetRecAwardState(recData)
        hurtTotal = GetRecHurtTotal(recData)
        if hurtTotal < needHurtValue:
            GameWorld.ErrLog("跨服妖魔boss伤害不足,无法领奖! awardIndex=%s,needHurtValue=%s > %s" % (awardIndex, needHurtValue, hurtTotal), playerID)
            return
        if awardState & pow(2, awardIndex):
            GameWorld.ErrLog("已经领取过该跨服妖魔boss伤害奖励! awardIndex=%s,awardState=%s" % (awardIndex, awardState), playerID)
            return
        awardState |= pow(2, awardIndex)
        SetRecAwardState(recData, awardState)
        GameWorld.Log("领取跨服妖魔boss伤害奖励! awardIndex=%s,awardState=%s,awardItemList=%s" % (awardIndex, awardState, awardItemList), playerID)
        serverGroupIDList = [serverGroupID]
        syncPlayerHurtInfo = {playerID:{"hurtTotal":hurtTotal, "awardState":awardState, "awardIndex":awardIndex, "awardItemList":awardItemList}}
        sendMsg = {"syncPlayerHurtInfo":syncPlayerHurtInfo}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossYaomoBossHurtInfo, sendMsg, serverGroupIDList)
        return
    return
def Sync_CrossYaomoBossDataToClientServer(serverGroupID=0):
    ''' 同步跨服数据到子服务器
    @param serverGroupID: 为0时同步所有子服
    '''
    GameWorld.Log("同步给子服跨服妖魔Boss数据: syncServerGroupID=%s" % (serverGroupID))
    syncPlayerHurtInfo = {}
    universalRecMgr = GameWorld.GetUniversalRecMgr()
    recDataList = universalRecMgr.GetTypeList(Def_RecType_CrossYaomoBossHurtInfo)
    for index in xrange(recDataList.Count()):
        recData = recDataList.At(index)
        playerID = GetRecPlayerID(recData)
        awardState = GetRecAwardState(recData)
        hurtTotal = GetRecHurtTotal(recData)
        syncPlayerHurtInfo[playerID] = {"hurtTotal":hurtTotal, "awardState":awardState}
    # 广播子服重置伤害
    if syncPlayerHurtInfo:
        serverGroupIDList = []
        sendMsg = {"syncPlayerHurtInfo":syncPlayerHurtInfo}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossYaomoBossHurtInfo, sendMsg, serverGroupIDList)
    return
def MapServer_CrossYaomoBossHurtInfo(msgList):
    zoneID, npcID, playerHurtList = msgList
    GameWorld.Log("地图跨服妖魔boss伤害结算信息: zoneID=%s,npcID=%s,hurtPlayerCount=%s" % (zoneID, npcID, len(playerHurtList)))
    rankAwardDict = IpyGameDataPY.GetFuncEvalCfg("CrossYaomoBoss", 2, {})
    rankIntAwardDict = {int(k):v for k, v in rankAwardDict.items()}
    universalRecMgr = GameWorld.GetUniversalRecMgr()
    recDataList = universalRecMgr.GetTypeList(Def_RecType_CrossYaomoBossHurtInfo)
    hurtRecDict = {}
    for index in xrange(recDataList.Count()):
        recData = recDataList.At(index)
        hurtRecDict[(GetRecZoneID(recData), GetRecPlayerID(recData))] = recData
    groupValue1 = zoneID
    billboardMgr = PyDataManager.GetCrossBillboardManager()
    billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_YaomoBossHurt, groupValue1)
    billboardObj.ClearData()
    syncPlayerHurtInfo = {}
    for rank, hurtInfo in enumerate(playerHurtList, 1):
        playerID, hurtValue, hurtName = hurtInfo
        job, realmLV, accID = 1, 1, ""
        curCache = PlayerViewCache.FindViewCache(playerID)
        if curCache:
            cacheDict = PlayerViewCache.GetCachePropDataDict(curCache)
            job = cacheDict.get("Job", job)
            realmLV = cacheDict.get("RealmLV", realmLV)
            accID = cacheDict.get("AccID", accID)
        # 更新最新一次伤害排名榜单
        dataID, name1, name2 = playerID, hurtName, ""
        type2, value1, value2 = job, realmLV, 0
        cmpValue = hurtValue / ShareDefine.Def_PerPointValue
        cmpValue2 = hurtValue % ShareDefine.Def_PerPointValue
        noSortAndSync = False if rank == len(playerHurtList) else True
        CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_YaomoBossHurt, groupValue1, dataID, name1, name2,
                                         type2, value1, value2, cmpValue, cmpValue2, noSortAndSync=noSortAndSync)
        # 名次奖励直接发放
        awardItemList = GameWorld.GetOrderValueByDict(rankIntAwardDict, rank, False)
        if awardItemList:
            paramList = [rank]
            PlayerCompensation.SendMailByKey("CrossYaomoBossHurtRank", [playerID], awardItemList, paramList, crossMail=True)
        key = (zoneID, playerID)
        if key not in hurtRecDict:
            recData = recDataList.AddRec()
            SetRecZoneID(recData, zoneID)
            SetRecPlayerID(recData, playerID)
            hurtTotal = hurtValue
        else:
            recData = hurtRecDict[key]
            hurtTotal = GetRecHurtTotal(recData) + hurtValue
        SetRecHurtTotal(recData, hurtTotal)
        syncPlayerHurtInfo[playerID] = {"hurtTotal":hurtTotal, "awardState":GetRecAwardState(recData)}
        GameWorld.Log("    rank=%s,playerID=%s,hurtValue=%s,hurtTotal=%s,accID=%s" % (rank, playerID, hurtValue, hurtTotal, accID))
    # 通知子服更新玩家总伤害
    if syncPlayerHurtInfo:
        serverGroupIDList = []
        sendMsg = {"syncPlayerHurtInfo":syncPlayerHurtInfo}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_CrossYaomoBossHurtInfo, sendMsg, serverGroupIDList)
    return
def CrossServerMsg_CrossYaomoBossHurtInfo(msgData):
    playerMgr = GameWorld.GetPlayerManager()
    if "HurtReset" in msgData:
        # 重置伤害
        syncPlayerIDList = PyGameData.g_crossYaomoBossHurtInfo.keys()
        PyGameData.g_crossYaomoBossHurtInfo = {}
        for playerID in syncPlayerIDList:
            curPlayer = playerMgr.FindPlayerByID(playerID)
            if not curPlayer or not curPlayer.GetInitOK():
                continue
            Sync_CrossYaomoBossPlayerHurtInfo(curPlayer)
        return
    #zoneID = msgData["zoneID"]
    #npcID = msgData["npcID"]
    syncPlayerHurtInfo = msgData["syncPlayerHurtInfo"]
    for playerID, hurtInfo in syncPlayerHurtInfo.items():
        if not PlayerControl.GetDBPlayerAccIDByID(playerID):
            continue
        awardIndex = hurtInfo.pop("awardIndex", None)
        awardItemList = hurtInfo.pop("awardItemList", None)
        PyGameData.g_crossYaomoBossHurtInfo[playerID] = hurtInfo
        curPlayer = playerMgr.FindPlayerByID(playerID)
        if not curPlayer or not curPlayer.GetInitOK():
            continue
        Sync_CrossYaomoBossPlayerHurtInfo(curPlayer)
        if awardIndex == None:
            continue
        # 通知地图发放奖励
        msgInfo = ["HurtValueAward", [awardIndex, awardItemList]]
        CrossRealmPlayer.MapServer_QueryCrossPlayerResult(playerID, "CrossYaomoBoss", msgInfo)
    return
def OnPlayerLogin(curPlayer):
    if GameWorld.IsCrossServer():
        return
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_crossYaomoBossHurtInfo:
        return
    Sync_CrossYaomoBossPlayerHurtInfo(curPlayer)
    return
def Sync_CrossYaomoBossPlayerHurtInfo(curPlayer):
    hurtInfo = PyGameData.g_crossYaomoBossHurtInfo.get(curPlayer.GetPlayerID(), {})
    hurtTotal = hurtInfo.get("hurtTotal", 0)
    awardState = hurtInfo.get("awardState", 0)
    clientPack = ChPyNetSendPack.tagGCCrossYaomoBossPlayerHurtInfo()
    clientPack.HurtTotal = hurtTotal % ShareDefine.Def_PerPointValue
    clientPack.HurtTotalEx = hurtTotal / ShareDefine.Def_PerPointValue
    clientPack.AwardState = awardState
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -1070,6 +1070,10 @@
def Dispose_DailyActionState():
    # 日常活动状态变更检查处理
    
    if GameWorld.IsCrossServer():
        CrossActionControl.Dispose_CrossDailyActionState()
        return
    todayDailyActionInfo = __GetTodayDailyActionInfo()
    if not todayDailyActionInfo:
        return
@@ -1135,11 +1139,21 @@
def SendMapServerDailyActionState():
    # 地图启动成功时通知本日进行中的日常活动状态
    
    if GameWorld.IsCrossServer():
        CrossActionControl.SendMapServerCrossDailyActionState()
        return
    gameWorld = GameWorld.GetGameWorld()
    for dailyActionID in ShareDefine.CrossDailyActionIDList:
        dictName = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % dailyActionID
        state = gameWorld.GetDictByKey(dictName)
        if state:
            GameWorld.SendMapServerMsgEx(dictName, state)
    todayDailyActionInfo = __GetTodayDailyActionInfo()
    if not todayDailyActionInfo:
        return
    
    gameWorld = GameWorld.GetGameWorld()
    for actionInfo in todayDailyActionInfo:
        dailyActionID = actionInfo[0]
        dictName = ShareDefine.Def_Notify_WorldKey_DailyActionState % dailyActionID 
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -98,6 +98,13 @@
                        ("list", "RandMailKeyList", 0),
                        ),
                "CrossDailyAction":(
                        ("DWORD", "DailyID", 1),
                        ("dict", "OpenTimeDict", 0),
                        ("DWORD", "Duration", 0),
                        ("dict", "NotifyInfo", 0),
                        ),
                "DailyAction":(
                        ("DWORD", "DailyID", 1),
                        ("dict", "OpenTimeDict", 0),
@@ -1023,6 +1030,21 @@
    def GetItemCountWeightList(self): return self.ItemCountWeightList # 指定上架随机件数权重列表, [[权重, 件数], ...]
    def GetAuctionItemWeightList(self): return self.AuctionItemWeightList # 指定上架物品随机权重, [[权重, 物品ID],[权重, [阶,颜色,部位集合,是否套装,星级]] ...]
    def GetRandMailKeyList(self): return self.RandMailKeyList # 指定上架随机邮件列表,有配置时上架的时候在线玩家会收到一封上架邮件提醒
# 跨服日常活动表
class IPY_CrossDailyAction():
    def __init__(self):
        self.DailyID = 0
        self.OpenTimeDict = {}
        self.Duration = 0
        self.NotifyInfo = {}
        return
    def GetDailyID(self): return self.DailyID # 活动ID
    def GetOpenTimeDict(self): return self.OpenTimeDict # 开启时间
    def GetDuration(self): return self.Duration # 持续时间, 0为不限制
    def GetNotifyInfo(self): return self.NotifyInfo # 广播提示信息
# 日常活动表
class IPY_DailyAction():
@@ -2706,6 +2728,8 @@
        self.ipyAuctionItemLen = len(self.ipyAuctionItemCache)
        self.ipyAuctionSystemItemCache = self.__LoadFileData("AuctionSystemItem", IPY_AuctionSystemItem)
        self.ipyAuctionSystemItemLen = len(self.ipyAuctionSystemItemCache)
        self.ipyCrossDailyActionCache = self.__LoadFileData("CrossDailyAction", IPY_CrossDailyAction)
        self.ipyCrossDailyActionLen = len(self.ipyCrossDailyActionCache)
        self.ipyDailyActionCache = self.__LoadFileData("DailyAction", IPY_DailyAction)
        self.ipyDailyActionLen = len(self.ipyDailyActionCache)
        self.ipyDailyActionCustomCache = self.__LoadFileData("DailyActionCustom", IPY_DailyActionCustom)
@@ -3034,6 +3058,8 @@
    def GetAuctionItemByIndex(self, index): return self.ipyAuctionItemCache[index]
    def GetAuctionSystemItemCount(self): return self.ipyAuctionSystemItemLen
    def GetAuctionSystemItemByIndex(self, index): return self.ipyAuctionSystemItemCache[index]
    def GetCrossDailyActionCount(self): return self.ipyCrossDailyActionLen
    def GetCrossDailyActionByIndex(self, index): return self.ipyCrossDailyActionCache[index]
    def GetDailyActionCount(self): return self.ipyDailyActionLen
    def GetDailyActionByIndex(self, index): return self.ipyDailyActionCache[index]
    def GetDailyActionCustomCount(self): return self.ipyDailyActionCustomLen
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerEventCounter.py
@@ -34,6 +34,7 @@
import PlayerCharm
import CrossBattlefield
import CrossChampionship
import CrossYaomoBoss
#---------------------------------------------------------------------
#---------------------------------------------------------------------
@@ -66,6 +67,8 @@
    PlayerFamily.FamilyOnDay(tick)
    #跨服排位
    CrossChampionship.DoOnDay()
    #跨服妖魔boss
    CrossYaomoBoss.DoOnDay()
    
    playerManager = GameWorld.GetPlayerManager()
    for i in xrange(playerManager.GetPlayerCount()):
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -67,6 +67,7 @@
import PyGameData
import PlayerTalk
import PlayerStore
import CrossYaomoBoss
import CrossRealmPlayer
import CrossRealmMsg
import CrossRealmPK
@@ -669,6 +670,11 @@
        CrossBattlefield.MapServer_CrossBattlefieldOver(eval(resultName))
        return
    
    # 跨服妖魔boss伤害结算
    if callName =="CrossYaomoBossHurtInfo":
        CrossYaomoBoss.MapServer_CrossYaomoBossHurtInfo(eval(resultName))
        return
    # 跨服全民充值
    if callName == "CrossActAllRecharge":
        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
@@ -148,6 +148,7 @@
g_championshipMgr = None # 跨服排位争霸赛管理
g_crossActAllRechargeInfo = {} # 跨服全民充值信息,本服用 {zoneID:{playerID:总充值, ...}, ...}
g_crossYaomoBossHurtInfo = {} # 跨服妖魔boss伤害信息,本服用 {playerID:hurtTotal, ...}
g_familyTalkCache = {} #{familyID:[[time,content,extras],..]}
g_worldTalkCache = [] #[[time,name, playerID, content,extras],..]
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -799,7 +799,9 @@
Def_CBT_BattlefieldWJoin, # 跨服战场每周参与榜  151
Def_CBT_BattlefieldWCall, # 跨服战场每周召集榜  152
Def_CBT_BattlefieldWScore, # 跨服战场每周积分榜  153
) = range(150, 153 + 1)
Def_CBT_BattlefieldWScoreLastWeek, # 跨服战场上周积分榜  154
Def_CBT_YaomoBossHurt, # 跨服妖魔boss最新一次伤血排名  155
) = range(150, 155 + 1)
#职业对应战力排行榜类型
JobFightPowerBillboardDict = {
@@ -1255,8 +1257,8 @@
                                Def_UniversalGameRecType_CrossChampionshipOfficial, # 跨服排位争霸赛最终排名官职信息 35
                                Def_UniversalGameRecType_CrossChampionshipOffChallenge, # 跨服排位争霸赛官职挑战信息 36
                                Def_UniversalGameRecType_CrossActAllRecharge, # 跨服全服充值活动信息 37
                                Def_UniversalGameRecType_38,
                                Def_UniversalGameRecType_39,
                                Def_UniversalGameRecType_CrossBattleChampionGroup, # 跨服战场冠军赛分组信息 38
                                Def_UniversalGameRecType_CrossYaomoBossHurtInfo, # 跨服妖魔boss伤血信息 39
                                Def_UniversalGameRecType_40,
                                Def_UniversalGameRecType_RedPacketRecord,   # 红包产出结果记录41
                                Def_UniversalGameRecType_42,
@@ -1453,6 +1455,8 @@
CrossServerMsg_ChampionshipOfficial = "ChampionshipOfficial"  # 跨服排位争霸赛官职信息
CrossServerMsg_ChampionshipDailyOfficial = "ChampionshipDailyOfficial"  # 跨服排位争霸赛每日官职信息
CrossServerMsg_ActAllRechargeInfo = "ActAllRechargeInfo"# 跨服全民充值信息
CrossServerMsg_CrossDailyActionState = "CrossDailyActionState" # 跨服日常任务状态信息
CrossServerMsg_CrossYaomoBossHurtInfo = "CrossYaomoBossHurtInfo" # 跨服妖魔boss玩家伤害信息
# 子服发送跨服信息定义
ClientServerMsg_ServerInitOK = "ServerInitOK"           # 子服启动成功
@@ -1488,6 +1492,7 @@
ClientServerMsg_ChampionshipGuess = "ChampionshipGuess" # 跨服排位竞猜
ClientServerMsg_ChampionshipWorship = "ChampionshipWorship" # 跨服排位膜拜
ClientServerMsg_ActAllRechargeValue = "ActAllRechargeValue" # 跨服全民充值额度
ClientServerMsg_CrossYaomoBossHurtAward = "CrossYaomoBossHurtAward" # 跨服妖魔boss玩家伤害领奖
#跨服广播类型定义
CrossNotify_CrossAct = "CrossAct"
@@ -1733,6 +1738,10 @@
DailyActionID_CrossBattlefield, # 跨服战场 35
) = range(1, 35 + 1)
# 跨服每日活动编号定义, 从150开始
CrossDailyActionIDList = (
CrossDailyActionID_YaomoBoss, # 妖魔boss 150
) = range(150, 150 + 1)
# 成就类型定义
SuccessTypeList = (
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
@@ -2777,7 +2777,11 @@
    
    if GetIsNewGuy(tagPlayer):
        return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_NotAttackNewGuy
    #和平光环
    if GetPeaceBuff(curPlayer) or GetPeaceBuff(tagPlayer):
        return ChConfig.Type_Relation_None, ChConfig.Def_PASysMessage_None
    #恶意攻击的玩家默认都是敌人, 无论什么模式
    if IsMaliciousAttackPlayer(curPlayer, tagPlayer):
        return ChConfig.Type_Relation_Enemy, ChConfig.Def_PASysMessage_None
@@ -2837,6 +2841,9 @@
    #敌人关系,可PK,可加减益buff
    return ChConfig.Type_Relation_Enemy , ChConfig.Def_PASysMessage_None
def GetPeaceBuff(curPlayer):
    return SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_Peace)[0]
## 获取玩家和镖车的关系
#  @param curPlayer: 攻击方实例
#  @param curTagTruck: 镖车实例
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -778,6 +778,8 @@
Def_AreaType_SkillID_FamilyPK = 20012  # 家族区
Def_AreaType_SkillID_Boss = 20008  # Boss区域
Def_SkillID_SitArea = 20009   # 打坐区域buff
Def_SkillID_Peace = 23048   # 玩家间和平buff
#----------------------------------------------------------------------
#战斗类型
Def_ChanceDefRate = 2000    # 抵御伤害概率, 目前固定20%概率
@@ -2279,6 +2281,7 @@
                         1000 * 10,                        # 跨服战场
                         1000 * 10,                        # 幸运云购
                         1000 * 10,                        # 跨服排位
                         1000 * 10,                        # 跨服妖魔boss
                         ]
TYPE_Player_Tick_Count = len(TYPE_Player_Tick_Time) 
@@ -2358,6 +2361,7 @@
TYPE_Player_Tick_Battlefield,        #跨服战场
TYPE_Player_Tick_LuckyCloudBuy,        #幸运云购
TYPE_Player_Tick_Championship,        #跨服排位
TYPE_Player_Tick_CrossYaomoBoss,        #跨服妖魔boss
) = range(0, TYPE_Player_Tick_Count)
#---------------------------------------------------------------------
@@ -5651,7 +5655,8 @@
Def_RewardType_ShediaoRedpacket, #射雕红包奖励 50
Def_RewardType_ShediaoEquip, #射雕装备奖励 51
Def_RewardType_CAAllRecharge, #跨服全民充值奖励 52
)= range(53)
Def_RewardType_CrossYaomoBossHurt, #跨服妖魔boss伤害奖励 53
)= range(54)
#boss复活相关活动定义
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -15140,6 +15140,66 @@
#------------------------------------------------------
# C0 11 跨服妖魔boss玩家伤害信息 #tagGCCrossYaomoBossPlayerHurtInfo
class  tagGCCrossYaomoBossPlayerHurtInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HurtTotal", c_int),    # 总伤害值,小于亿部分
                  ("HurtTotalEx", c_int),    # 总伤害值,整除亿部分
                  ("AwardState", c_int),    # 伤害目标值领奖状态,按奖励记录索引位运算判断是否已领取
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xC0
        self.SubCmd = 0x11
        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 = 0xC0
        self.SubCmd = 0x11
        self.HurtTotal = 0
        self.HurtTotalEx = 0
        self.AwardState = 0
        return
    def GetLength(self):
        return sizeof(tagGCCrossYaomoBossPlayerHurtInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// C0 11 跨服妖魔boss玩家伤害信息 //tagGCCrossYaomoBossPlayerHurtInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                HurtTotal:%d,
                                HurtTotalEx:%d,
                                AwardState:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HurtTotal,
                                self.HurtTotalEx,
                                self.AwardState
                                )
        return DumpString
m_NAtagGCCrossYaomoBossPlayerHurtInfo=tagGCCrossYaomoBossPlayerHurtInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossYaomoBossPlayerHurtInfo.Cmd,m_NAtagGCCrossYaomoBossPlayerHurtInfo.SubCmd))] = m_NAtagGCCrossYaomoBossPlayerHurtInfo
#------------------------------------------------------
# C0 14 幸运云购开奖记录 #tagGCLuckyCloudBuyLotteryRecInfo
class  tagGCLuckyCloudBuyLotteryRec(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -50,6 +50,7 @@
import FormulaControl
import PlayerBossReborn
import PlayerFairyCeremony
import PlayerCrossYaomoBoss
import PlayerActCollectWords
import PlayerNewFairyCeremony
import GameLogic_CrossGrassland
@@ -2391,7 +2392,9 @@
                FamilyRobBoss.ClearFamilyOwnerBossHurt(curNPC)
        ChNPC.OnNPCSetDead(curNPC)
        
        if npcid == IpyGameDataPY.GetFuncCfg("CrossYaomoBoss", 1):
            PlayerCrossYaomoBoss.OnCrossYaomoBossDead(curNPC)
    # 清除队伍成员伤血列表
    AttackCommon.ClearTeamPlayerHurtValue(curNPC)
    # 清除自定义伤血列表
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
@@ -315,6 +315,16 @@
def NPCRefresh_218(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_219(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_220(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_221(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_222(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_223(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_224(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_225(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_226(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_227(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_228(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_229(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_230(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
## 世界boss刷怪
#  @param npcRefresh 刷新实例
@@ -526,6 +536,7 @@
    lineID = GameWorld.GetGameWorld().GetLineID()
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    relatedType, relatedID = 0, ""
    
    if mapID == ChConfig.Def_FBMapID_CrossDemonKing:
        bossID = GameLogic_CrossDemonKing.GetCurFBLineBOSSID()
@@ -539,7 +550,9 @@
        
        stoneNPCID = bossIpyData.GetStoneNPCID()
        bossID = bossIpyData.GetNPCID()
        relatedType = bossIpyData.GetRelatedType()
        relatedID = bossIpyData.GetRelatedID()
        if mapID not in ChConfig.Def_CrossZoneMapTableName:
            return
        tableName = ChConfig.Def_CrossZoneMapTableName[mapID]
@@ -554,8 +567,34 @@
        return
    
    gameFB = GameWorld.GetGameFB()
    bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID)
    rebornBossState = GameWorld.GetGameWorld().GetGameWorldDictByKey(bosskey)
    gameWorldMgr = GameWorld.GetGameWorld()
    forceReborn = False # 强制重生
    actBossRebornSign = 0
    mapActBossRebornSign = 0
    # 关联日常活动
    if relatedType == 1:
        relatedID = int(relatedID)
        actionKey = ShareDefine.Def_Notify_WorldKey_CrossDailyActionState % relatedID
        rebornBossState = 1 if gameWorldMgr.GetGameWorldDictByKey(actionKey) else 0
    # 关联运营活动,待扩展
    elif relatedType == 2:
        pass
    else:
        bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID)
        rebornBossState = GameWorld.GetGameWorld().GetGameWorldDictByKey(bosskey)
    # 关联活动boss
    if relatedType:
        # 关联活动boss只要复活标记与上次不同,则强制重生
        actBossRebornSign = gameWorldMgr.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ActionBossRebornSign % relatedID)
        mapActBossRebornSign = gameFB.GetGameFBDictByKey(ChConfig.Map_NPC_ActBossLastRebornSign % refreshMark)
        rebornBossState = rebornBossState and actBossRebornSign
        if rebornBossState and actBossRebornSign != mapActBossRebornSign:
            forceReborn = True
    curNPC = None
    if npcRefresh.GetCount() > 0:
        curNPC = npcRefresh.GetAt(0)
@@ -563,11 +602,16 @@
    # 复活状态
    if rebornBossState:
        if curNPC:
            if curNPC.GetNPCID() == bossID:
            if not forceReborn and curNPC.GetNPCID() == bossID:
                return
            #去掉非bossNPC
            NPCCommon.SetDeadEx(curNPC)
            
        if mapActBossRebornSign and actBossRebornSign == mapActBossRebornSign:
            #GameWorld.DebugLog("活动线已经刷过不再刷活动boss: lineID=%s,refreshMark=%s,bossID=%s,actBossRebornSign=%s"
            #                   % (lineID, refreshMark, bossID, actBossRebornSign))
            return
    # 死亡状态
    else:
        if curNPC:
@@ -598,6 +642,9 @@
    __InitNewBornNPC(npcRefresh, tick)
    gameFB.SetGameFBDict(rebornTickKey, tick)
    
    if actBossRebornSign and rebornBossState:
        gameFB.SetGameFBDict(ChConfig.Map_NPC_ActBossLastRebornSign % refreshMark, actBossRebornSign)
    GameWorld.DebugLog("CrossBossRefresh mapID=%s,realMapID=%s,copyMapID=%s,refreshMark=%s,rebornNPCID=%s,OK!" 
                       % (mapID, realMapID, copyMapID, refreshMark, rebornNPCID), lineID)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtMgr.py
@@ -148,7 +148,7 @@
        #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()
            self.Sort()
            
        return isNewHurt
    
@@ -160,7 +160,7 @@
            return 0
        return -1
    
    def __Sort(self):
    def Sort(self):
        ## 伤血排序
        self.__hurtSortList = sorted(self.__hurtDict.values(), cmp=self.__CmpHurtValue, reverse=True)
        return
@@ -184,6 +184,8 @@
            hurtValueObj.HurtValue = hurtValue % ShareDefine.Def_PerPointValue
            hurtValueObj.HurtValueEx = hurtValue / ShareDefine.Def_PerPointValue
            hurtValueList.append(hurtValueObj)
            if len(hurtValueList) > 250:
                break
            
        if not syncPlayerIDList:
            return
@@ -223,7 +225,7 @@
            self.checkHurtValidFunc()
            
        # 2. 排序
        self.__Sort()
        self.Sort()
        
        # 3. 同步前端
        self.__SyncHurtList()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -119,6 +119,7 @@
import PlayerFairyCeremony
import PlayerNewFairyCeremony
import GY_Query_BossFirstKill
import PlayerCrossYaomoBoss
import PlayerFeastRedPacket
import PlayerLuckyCloudBuy
import PlayerLuckyTreasure
@@ -5605,6 +5606,9 @@
    # 跨服全民充值奖励
    elif rewardType == ChConfig.Def_RewardType_CAAllRecharge:
        CrossActAllRecharge.GetCrossActAllRechargeAward(curPlayer, dataEx)
    # 跨服妖魔boss伤害奖励
    elif rewardType == ChConfig.Def_RewardType_CrossYaomoBossHurt:
        PlayerCrossYaomoBoss.GetCrossYaomoBossHurtAward(curPlayer, dataEx, tick)
    #缥缈奇遇领取
    elif rewardType == ChConfig.Def_RewardType_FairyAdventuresAward:
        PlayerFairyDomain.GetFairyAdventuresAward(curPlayer, dataEx, dataExStr)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossYaomoBoss.py
New file
@@ -0,0 +1,114 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.PlayerCrossYaomoBoss
#
# @todo:跨服妖魔boss
# @author hxp
# @date 2022-11-11
# @version 1.0
#
# 详细描述: 跨服妖魔boss
#
#-------------------------------------------------------------------------------
#"""Version = 2022-11-11 15:30"""
#-------------------------------------------------------------------------------
import GameWorld
import NPCHurtMgr
import PlayerControl
import IpyGameDataPY
import ItemControler
import IPY_GameWorld
import ShareDefine
import ItemCommon
import ChConfig
def OnYaomoBossStateChange(state, tick):
    ## 活动状态变更
    if state:
        # 开始的不需要处理
        return
    return
def OnCrossYaomoBossDead(curNPC):
    objID = curNPC.GetID()
    npcID = curNPC.GetNPCID()
    mapID = GameWorld.GetGameWorld().GetMapID()
    lineID = GameWorld.GetGameWorld().GetLineID()
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    zoneID = 0
    zoneTypeName = ChConfig.Def_CrossZoneMapTableName.get(mapID)
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    if zoneTypeName and hasattr(ipyDataMgr, "Get%sCount" % zoneTypeName):
        for index in range(getattr(ipyDataMgr, "Get%sCount" % zoneTypeName)()):
            ipyData = getattr(ipyDataMgr, "Get%sByIndex" % zoneTypeName)(index)
            if realMapID == ipyData.GetMapID() and copyMapID == ipyData.GetCopyMapID():
                zoneID = ipyData.GetZoneID()
                break
    npcHurtList = NPCHurtMgr.GetPlayerHurtList(curNPC)
    if not npcHurtList or not npcHurtList.GetHurtCount():
        GameWorld.ErrLog("跨服妖魔boss结算无伤害列表: mapID=%s,lineID=%s,realMapID=%s,copyMapID=%s,zoneID=%s,npcID=%s,objID=%s"
                         % (mapID, lineID, realMapID, copyMapID, zoneID, npcID, objID))
        return
    GameWorld.Log("跨服妖魔boss伤害结算: mapID=%s,lineID=%s,realMapID=%s,copyMapID=%s,zoneID=%s,npcID=%s,objID=%s"
                  % (mapID, lineID, realMapID, copyMapID, zoneID, npcID, objID))
    npcHurtList.Sort()  #sort以后伤血列表从大到小排序
    rank = 0
    playerHurtList = []
    for index in xrange(npcHurtList.GetHurtCount()):
        #获得伤血对象
        hurtObj = npcHurtList.GetHurtAt(index)
        hurtType = hurtObj.GetValueType()
        hurtID = hurtObj.GetValueID()
        hurtValue = hurtObj.GetHurtValue()
        hurtName = hurtObj.GetHurtName()
        if hurtType != ChConfig.Def_NPCHurtTypePlayer or not hurtID:
            continue
        rank += 1
        playerID = hurtID
        GameWorld.Log("    zoneID=%s,rank=%s,playerID=%s,hurtValue=%s" % (zoneID, rank, playerID, hurtValue))
        playerHurtList.append([playerID, hurtValue, hurtName])
    msgInfo = str([zoneID, npcID, playerHurtList])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "CrossYaomoBossHurtInfo", msgInfo, len(msgInfo))
    return
def GetCrossYaomoBossHurtAward(curPlayer, awardIndex, tick):
    playerID = curPlayer.GetPlayerID()
    if not ItemCommon.CheckPackHasSpace(curPlayer, IPY_GameWorld.rptItem, True):
        return
    if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_CrossYaomoBoss, tick):
        PlayerControl.NotifyCode(curPlayer, "RequestLater")
        return
    # 发送跨服服务器
    dataMsg = {"playerID":playerID, "awardIndex":awardIndex}
    GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_CrossYaomoBossHurtAward, dataMsg)
    return
def GameServer_CrossYaomoBoss_DoResult(curPlayer, msgData):
    msgType, dataMsg = msgData[:2]
    #ret = msgData[2] if len(msgData) > 2 else None
    ## 伤害目标奖励
    if msgType == "HurtValueAward":
        __DoGiveCrossYaomoBossHurtAward(curPlayer, dataMsg)
    return
def __DoGiveCrossYaomoBossHurtAward(curPlayer, dataMsg):
    playerID = curPlayer.GetPlayerID()
    awardIndex, awardItemList = dataMsg
    GameWorld.Log("给玩家跨服妖魔boss伤害目标奖励: awardIndex=%s,awardItemList=%s" % (awardIndex, awardItemList), playerID)
    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["CrossYaomoBoss", False, {}])
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossYaomoBoss.py
New file
@@ -0,0 +1,48 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.RemoteQuery.GY_Query_CrossYaomoBoss
#
# @todo:跨服妖魔Boss
# @author hxp
# @date 2022-11-11
# @version 1.0
#
# 详细描述: 跨服妖魔Boss
#
#-------------------------------------------------------------------------------
#"""Version = 2022-11-11 15:30"""
#-------------------------------------------------------------------------------
import ChConfig
import GameWorld
import PlayerCrossYaomoBoss
#------------------------------------------------------------------------------
## 执行逻辑
#  @param query_Type 请求类型
#  @param query_ID 请求的玩家ID
#  @param packCMDList 发包命令
#  @param tick 当前时间
#  @return "True" or "False" or ""
#  @remarks 函数详细说明.
def DoLogic(query_Type, query_ID, packCMDList, tick):
    return
#------------------------------------------------------------------------------
## 执行结果
#  @param curPlayer 发出请求的玩家
#  @param callFunName 功能名称
#  @param funResult 查询的结果
#  @param tick 当前时间
#  @return None
#  @remarks 函数详细说明.
def DoResult(curPlayer, callFunName, funResult, tick):
    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_CrossYaomoBoss, 0)
    msgData = eval(funResult)
    playerID = curPlayer.GetPlayerID()
    GameWorld.Log("GY_Query_CrossYaomoBoss msgData=%s" % (msgData), playerID)
    PlayerCrossYaomoBoss.GameServer_CrossYaomoBoss_DoResult(curPlayer, msgData)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -799,7 +799,9 @@
Def_CBT_BattlefieldWJoin, # 跨服战场每周参与榜  151
Def_CBT_BattlefieldWCall, # 跨服战场每周召集榜  152
Def_CBT_BattlefieldWScore, # 跨服战场每周积分榜  153
) = range(150, 153 + 1)
Def_CBT_BattlefieldWScoreLastWeek, # 跨服战场上周积分榜  154
Def_CBT_YaomoBossHurt, # 跨服妖魔boss最新一次伤血排名  155
) = range(150, 155 + 1)
#职业对应战力排行榜类型
JobFightPowerBillboardDict = {
@@ -1255,8 +1257,8 @@
                                Def_UniversalGameRecType_CrossChampionshipOfficial, # 跨服排位争霸赛最终排名官职信息 35
                                Def_UniversalGameRecType_CrossChampionshipOffChallenge, # 跨服排位争霸赛官职挑战信息 36
                                Def_UniversalGameRecType_CrossActAllRecharge, # 跨服全服充值活动信息 37
                                Def_UniversalGameRecType_38,
                                Def_UniversalGameRecType_39,
                                Def_UniversalGameRecType_CrossBattleChampionGroup, # 跨服战场冠军赛分组信息 38
                                Def_UniversalGameRecType_CrossYaomoBossHurtInfo, # 跨服妖魔boss伤血信息 39
                                Def_UniversalGameRecType_40,
                                Def_UniversalGameRecType_RedPacketRecord,   # 红包产出结果记录41
                                Def_UniversalGameRecType_42,
@@ -1453,6 +1455,8 @@
CrossServerMsg_ChampionshipOfficial = "ChampionshipOfficial"  # 跨服排位争霸赛官职信息
CrossServerMsg_ChampionshipDailyOfficial = "ChampionshipDailyOfficial"  # 跨服排位争霸赛每日官职信息
CrossServerMsg_ActAllRechargeInfo = "ActAllRechargeInfo"# 跨服全民充值信息
CrossServerMsg_CrossDailyActionState = "CrossDailyActionState" # 跨服日常任务状态信息
CrossServerMsg_CrossYaomoBossHurtInfo = "CrossYaomoBossHurtInfo" # 跨服妖魔boss玩家伤害信息
# 子服发送跨服信息定义
ClientServerMsg_ServerInitOK = "ServerInitOK"           # 子服启动成功
@@ -1488,6 +1492,7 @@
ClientServerMsg_ChampionshipGuess = "ChampionshipGuess" # 跨服排位竞猜
ClientServerMsg_ChampionshipWorship = "ChampionshipWorship" # 跨服排位膜拜
ClientServerMsg_ActAllRechargeValue = "ActAllRechargeValue" # 跨服全民充值额度
ClientServerMsg_CrossYaomoBossHurtAward = "CrossYaomoBossHurtAward" # 跨服妖魔boss玩家伤害领奖
#跨服广播类型定义
CrossNotify_CrossAct = "CrossAct"
@@ -1733,6 +1738,10 @@
DailyActionID_CrossBattlefield, # 跨服战场 35
) = range(1, 35 + 1)
# 跨服每日活动编号定义, 从150开始
CrossDailyActionIDList = (
CrossDailyActionID_YaomoBoss, # 妖魔boss 150
) = range(150, 150 + 1)
# 成就类型定义
SuccessTypeList = (
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
@@ -1751,7 +1751,11 @@
        return True
    
    buffSkill = curObjBuff.GetSkill()
    if buffType == IPY_GameWorld.bfAura:
        if buffSkill.GetSkillLV() >= curSkillLV:
            #GameWorld.DebugLog("光环技能只添加更高级的效果!")
            return
    #buff根据情况可以叠加低级,或者低级覆盖高级
#    buffSkillLV = buffSkill.GetSkillLV()
#