From 7e459643c41df6fe63c9820660d35297c9a88ef0 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 10 七月 2024 18:32:03 +0800
Subject: [PATCH] 10192 【越南】【主干】【港台】【砍树】上线增加膜拜主动推送(膜拜玩家信息增加EquipShowSwitch;单引号替换为双引号;)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py |  976 +++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 703 insertions(+), 273 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
index 4f1976e..c89e50d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -33,8 +33,14 @@
 import PlayerFamilyRedPacket
 import PlayerFairyCeremony
 import PlayerNewFairyCeremony
+import PlayerActFamilyCTGAssist
+import PlayerActGarbageSorting
+import PlayerActBossTrial
 import PlayerUniversalGameRec
 import GameWorldAverageLv
+import PlayerFamilyBoss
+import PlayerHorsePetBoss
+import CrossActionControl
 import GameWorldProcess
 import ChPyNetSendPack
 import NetPackCommon
@@ -57,7 +63,14 @@
 
 def OnPlayerLogin(curPlayer):
     
-    isReload, OperationActionInfo = __GetOperationActionInfo()
+    if GameWorld.IsCrossServer():
+        # 跨服不处理运营活动
+        return
+    
+    # 玩家登录的不触发重载活动,不然刚好在0点服务器处理OnDay之前登录的时候会有问题
+    isReload, OperationActionInfo = __GetOperationActionInfo(needReload=False)
+    if not OperationActionInfo:
+        return
     operationActionDict = OperationActionInfo[OperationAction_TodayInfo]
     
     if isReload:
@@ -97,6 +110,12 @@
 def SendMapServerOperationActionState():
     # 地图启动成功时通知本日运行活动相关状态
     
+    CrossActionControl.SendMapServerCrossActionState()
+    
+    if GameWorld.IsCrossServer():
+        # 跨服不处理运营活动
+        return
+    
     isReload, OperationActionInfo = __GetOperationActionInfo()
     mapServerInfoDict = OperationActionInfo[OperationAction_MapServerInfo]
     
@@ -104,83 +123,265 @@
         # 如果是重读的,则在内层已经同步了,此处不重复同步
         return
     
-    gameWorld = GameWorld.GetGameWorld()
     for actName in ShareDefine.OperationActionNameList:
-        dictName = ChConfig.Def_WorldKey_OperationActionState % actName
-        state = gameWorld.GetDictByKey(dictName)
-        
         sendMapServerMsgDict = mapServerInfoDict.get(actName, {})
-        sendMapServerMsgDict[ShareDefine.ActKey_State] = state
-        GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_OperationActionInfo % actName, sendMapServerMsgDict)
+        if actName in ShareDefine.MultiActNumOperationActNameList:
+            for actNumMapMsgDict in sendMapServerMsgDict.values():
+                GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_OperationActionInfo % actName, actNumMapMsgDict)
+        else:
+            GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_OperationActionInfo % actName, sendMapServerMsgDict)
         
     return
 
-def __GetOperationActionInfo(isRefreshState=True):
+def GetOperationActNum(actName, ipyData=None):
+    ''' 获取运营活动分组编号
+        加入了分组编号概念,但由于有些活动配表还是旧规则配置,为了做规则兼容旧配表,减少配置表改动及代码改动这里做下自适应分配默认分组编号
+        活动类型定义:
+        1-默认(仅可配置开服天、日期、周循环W开头+数字,优先级 开服天 > 日期 > 周x)
+                                        非开服配置的开服前X天不开,不受合服影响,功能配置表可配置前X天后交叉可开,每日重置的活动前X天后默认可开
+        2-合服(仅可配置Mix开头+数字,如Mix1代表合服第1天,以此类推)
+        3-节日(仅可配置日期,不受开服、合服影响)
+        
+        活动分组编号 = 活动类型 * 10 + 不同界面编号
+    '''
+    if ipyData and hasattr(ipyData, "GetActNum"):
+        return ipyData.GetActNum()
+    
+    # 原节日活动的还是默认节日活动
+    if actName in ShareDefine.FeastOperationActionNameList:
+        return ShareDefine.ActType_Feast * 10
+    
+    # 其他默认常规,这里不考虑合服类型的了,新版本合服类型已独立出去,按 ipyData 配置
+    return ShareDefine.ActType_OpenComm * 10
+
+def GetOperationActType(actNum):
+    ## 运营活动类型
+    return actNum / 10
+
+def __SaveActWorldLVLimitInfo(actWorldLVLimitInfo):
+    GameWorld.GetUniversalRecMgr().Delete(ShareDefine.Def_UniversalGameRecType_ActWorldLVLimitInfo)
+    recDataList = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_ActWorldLVLimitInfo)
+    GameWorld.Log("保存运营活动世界等级限制开启信息: %s" % len(actWorldLVLimitInfo))
+    for actName, cfgLimitInfoDict in actWorldLVLimitInfo.items():
+        for cfgID, limitInfo in cfgLimitInfoDict.items():
+            recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV = limitInfo
+            recData = recDataList.AddRec()
+            recData.SetStrValue1(recStartDateStr)
+            recData.SetStrValue2(recEndDateStr)
+            recData.SetStrValue3(actName)
+            recData.SetValue1(cfgID)
+            recData.SetValue2(recLimitWorldLV)
+            recData.SetValue3(recWorldLV)
+            GameWorld.Log("    actName=%s,cfgID=%s,recStartDateStr=%s,recEndDateStr=%s,recLimitWorldLV=%s,recWorldLV=%s" 
+                          % (actName, cfgID, recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV))
+    return
+
+def __GetActWorldLVLimitInfo():
+    actWorldLVLimitInfo = {}
+    recDataList = GameWorld.GetUniversalRecMgr().GetTypeList(ShareDefine.Def_UniversalGameRecType_ActWorldLVLimitInfo)
+    GameWorld.Log("加载运营活动世界等级限制开启信息: %s" % recDataList.Count())
+    for index in xrange(recDataList.Count()):
+        recData = recDataList.At(index)
+        recStartDateStr = recData.GetStrValue1()
+        recEndDateStr = recData.GetStrValue2()
+        actName = recData.GetStrValue3()
+        cfgID = recData.GetValue1()
+        recLimitWorldLV = recData.GetValue2()
+        recWorldLV = recData.GetValue3()
+        if actName not in actWorldLVLimitInfo:
+            actWorldLVLimitInfo[actName] = {}
+        actWorldLVLimitInfo[actName][cfgID] = [recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV]
+        GameWorld.Log("    actName=%s,cfgID=%s,recStartDateStr=%s,recEndDateStr=%s,recLimitWorldLV=%s,recWorldLV=%s" 
+                      % (actName, cfgID, recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV))
+    return actWorldLVLimitInfo
+
+def __GetOperationActionInfo(isRefreshState=True, needReload=True):
     # @return: isReload, OperationActionInfo
     
     key = "OperationActionInfo"
     openServerDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ServerDay) + 1
+    isMixServer = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_IsMixServer)
+    mixServerDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_MixServerDay) + 1
     OperationActionInfo = IpyGameDataPY.GetConfigEx(key)
     serverTime = GameWorld.GetServerTime()
     curHour = serverTime.hour
     reloadSignHour = 0 if curHour < 5 else 5
-    reloadSign = "%s_%s" % (openServerDay, reloadSignHour)
+    reloadSign = [openServerDay, isMixServer, mixServerDay, reloadSignHour]
     if OperationActionInfo and OperationActionInfo[OperationAction_ReloadSign] == reloadSign:
         #GameWorld.DebugLog("已经加载过本日运营活动处理信息!openServerDay=%s" % openServerDay)
+        return False, OperationActionInfo
+    
+    if not needReload:
         return False, OperationActionInfo
     
     # 因为后面的时间判断都是精确到分的,而处理此逻辑的时候可能不是0秒,所以这里的datetime取当前时间精确到分的
     curDateTimeStr = "%d-%d-%d %02d:%02d:00" % (serverTime.year, serverTime.month, serverTime.day, serverTime.hour, serverTime.minute)
     curDateTime = datetime.datetime.strptime(curDateTimeStr, ChConfig.TYPE_Time_Format)
     
+    startDateInCustomCanOpenList = IpyGameDataPY.GetFuncEvalCfg("OperationAction", 2) # 开始天在定制天内在定制天结束后可继续开启的活动列表
     customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1) # 定制运营活动最大开服天
-    operationActionDict = {}
+    maxCustomServerDayMix = IpyGameDataPY.GetFuncCfg("MixServer", 1) # 定制运营活动最大合服天
+    operationTodayActionDict = {}
     mapServerOperationActionDict = {}
-    serverID = GameWorld.GetServerID()
+    platform = GameWorld.GetPlatform()
+    serverGroupID = GameWorld.GetServerGroupID()
     ipyDataMgr = IpyGameDataPY.IPY_Data()
+    curWeekday = curDateTime.weekday() + 1 # 今天星期几, 1代表星期1
+    curWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
+    actWorldLVLimitInfoOld = __GetActWorldLVLimitInfo()
+    actWorldLVLimitInfoNew = {}
     
-    GameWorld.Log("===== 加载本日运营活动信息: %s, serverID=%s,openServerDay=%s,customMaxServerDay=%s,reloadSign=%s =====" 
-                  % (curDateTime, serverID, openServerDay, customMaxServerDay, reloadSign))
+    GameWorld.Log("===== 加载本日运营活动信息: %s, serverGroupID=%s,openServerDay=%s,customMaxServerDay=%s,isMixServer=%s,mixServerDay=%s,maxCustomServerDayMix=%s,reloadSign=%s =====" 
+                  % (curDateTime, serverGroupID, openServerDay, customMaxServerDay, isMixServer, mixServerDay, maxCustomServerDayMix, reloadSign))
+    GameWorld.Log("    今日周%s, curWorldLV=%s" % (curWeekday, curWorldLV))
     
     for actName in ShareDefine.OperationActionNameList:
         
+        if actName not in mapServerOperationActionDict:
+            mapServerOperationActionDict[actName] = {}
+            
         # 取出本活动所属本服ID的所有配置
-        curServerActIpyDataList = __GetOperationActionServerIpyDataList(ipyDataMgr, serverID, actName)
-        GameWorld.Log("加载运营活动: actName=%s,可处理条数=%s" % (actName, len(curServerActIpyDataList)))
-        needStartList = [] # [startDateTime, ...]
-        needEndList = [] # [endDateTime, ...]
-        needNotifyDict = {} # {notifyDateTime:[notifyKey, [参数]], ...}
-        activityIpyData = None # 活动中的的配置,取需要处理的配置中开始时间最晚的,反之开关时间头尾相连的时候无法开启后面的活动
-        # 注意:每个活动配置会有多个活动时间点,但是有且只能生效一条活动配置,换句话说就是每个活动配置时间不允许交叉
+        GameWorld.Log("加载运营活动: actName=%s,platform=%s,serverGroupID=%s" % (actName, platform, serverGroupID))
+        curServerActIpyDataList = __GetOperationActionServerIpyDataList(ipyDataMgr, platform, serverGroupID, actName)
+        GameWorld.Log("    可处理条数=%s" % (len(curServerActIpyDataList)))
+        actNumDisableWeekIpyDataInfo, disableWeekCfgIDDict = __GetOperationActionDisableWeekIpyDataInfo(actName, curDateTime, curServerActIpyDataList)
+        
         for ipyData in curServerActIpyDataList:
             
+            platformList = [] if not hasattr(ipyData, "GetPlatformList") else ipyData.GetPlatformList()
+            serverGroupIDList = [] if not hasattr(ipyData, "GetServerGroupIDList") else ipyData.GetServerGroupIDList()
+            serverGroupIDListExcept = [] if not hasattr(ipyData, "GetServerGroupIDListExcept") else ipyData.GetServerGroupIDListExcept()
             cfgID = ipyData.GetCfgID()
             startDateStr = ipyData.GetStartDate()
             endDateStr = ipyData.GetEndDate()
-            GameWorld.Log("    cfgID=%s,mark=%s,serverIDList=%s,startDateStr=%s,endDateStr=%s,openServerDay=%s,curDateTime=%s" 
-                          % (cfgID, ipyData.GetActMark(), ipyData.GetServerIDList(), startDateStr, endDateStr, openServerDay, curDateTime))
-            # 按开服天开的
-            if startDateStr.isdigit() and endDateStr.isdigit():
-                startServerDay, endServerDay = int(startDateStr), int(endDateStr)
-                #结束日可能还需要处理广播之类,所以这里需要+1
-                if openServerDay > endServerDay + 1:
-                    GameWorld.Log("        当前开服天超过活动结束开服天,不处理! cfgID=%s,%s ~ %s < openServerDay(%s)" % (cfgID, startDateStr, endDateStr, openServerDay))
+            actNum = GetOperationActNum(actName, ipyData)
+            actType = GetOperationActType(actNum)
+            GameWorld.Log("    cfgID=%s,actNum=%s,startDateStr=%s,endDateStr=%s,openServerDay=%s,isMixServer=%s,mixServerDay=%s,curDateTime=%s,platformList=%s,serverGroupIDList=%s,Except=%s" 
+                          % (cfgID, actNum, startDateStr, endDateStr, openServerDay, isMixServer, mixServerDay, curDateTime, platformList, serverGroupIDList, serverGroupIDListExcept))
+            
+            actIDDateTimeSpec = None # 特殊指定的活动ID日期
+            startDateSync = None # 特殊同步前端显示用的开始日期,一般用于与开服前X天交叉的活动
+            if actName in ShareDefine.MultiActNumOperationActNameList:
+                # 多活动分组编号的需要把所有配置的 actNum 都登记进来,以确保地图能正确进行逻辑
+                if actNum not in mapServerOperationActionDict[actName]:
+                    mapServerOperationActionDict[actName][actNum] = {ShareDefine.ActKey_ActNum:actNum}
+                    
+                curActTodayInfo = operationTodayActionDict.get(actName, {}).get(actNum)
+            else:
+                curActTodayInfo = operationTodayActionDict.get(actName)
+                
+            if not startDateStr:
+                startDateStr = "%d-%d-%d" % (serverTime.year, serverTime.month, serverTime.day)
+                GameWorld.Log("        开始日期为空,默认每天,今日为: startDateStr=%s" % startDateStr)
+            if not endDateStr:
+                endDateStr = "%d-%d-%d" % (serverTime.year, serverTime.month, serverTime.day)
+                GameWorld.Log("        结束日期为空,默认每天,今日为: endDateStr=%s" % endDateStr)
+                
+            # 开服常规:  开服天 > 日期 > 周x   (不受合服天影响,合服活动新增一套独立的活动,还是走运营活动配置)
+            if actType == ShareDefine.ActType_OpenComm:
+                actByWeek = (startDateStr.startswith("W") and endDateStr.startswith("W")) # 按周x开
+                actByDate = (not actByWeek and startDateStr.count("-") == 2 and endDateStr.count("-") == 2) # 按日期开
+                
+                # 开服天的
+                if startDateStr.isdigit() and endDateStr.isdigit():
+                    startServerDay, endServerDay = int(startDateStr), int(endDateStr)
+                    #结束日可能还需要处理广播之类,所以这里需要+1
+                    if openServerDay > endServerDay + 1:
+                        GameWorld.Log("        当前开服天超过活动结束开服天,不处理! cfgID=%s,%s ~ %s < openServerDay(%s)" % (cfgID, startDateStr, endDateStr, openServerDay))
+                        continue
+                    openServerDateTime = curDateTime + datetime.timedelta(days=(startServerDay - openServerDay))
+                    endServerDateTime = curDateTime + datetime.timedelta(days=(endServerDay - openServerDay))
+                    startDateStr = "%d-%d-%d" % (openServerDateTime.year, openServerDateTime.month, openServerDateTime.day)
+                    endDateStr = "%d-%d-%d" % (endServerDateTime.year, endServerDateTime.month, endServerDateTime.day)
+                    GameWorld.Log("        开服天转化为日期: %s ~ %s" % (startDateStr, endDateStr))
+                    
+                # 常规配置: 开服前X天不开,不受合服影响,功能配置表可配置 开服前X天后交叉可开,每日重置的活动默认可开
+                elif actByWeek or actByDate:
+                    if openServerDay <= customMaxServerDay:
+                        GameWorld.Log("        按日期/周开的在开服定制限制天内,不处理! cfgID=%s,%s ~ %s,openServerDay=%s" % (cfgID, startDateStr, endDateStr, openServerDay))
+                        continue
+                    
+                    disableWeekIpyDataInfo = actNumDisableWeekIpyDataInfo.get(actNum, {})
+                    if cfgID in disableWeekIpyDataInfo:
+                        startWeekDate, endWeekDate, ymdCfgID, ymdStartDate, ymdEndDate = disableWeekIpyDataInfo[cfgID]
+                        GameWorld.Log("        常规活动,按星期开启的在按日期开启的时间内,不处理! cfgID=%s,%s(%s) ~ %s(%s) in ymdCfgID=%s,%s ~ %s" 
+                                      % (cfgID, startWeekDate, startDateStr, endWeekDate, endDateStr, ymdCfgID, ymdStartDate, ymdEndDate))
+                        continue
+                    
+                    if cfgID in disableWeekCfgIDDict:
+                        GameWorld.Log("        常规活动,按星期开启的未到开启循环日期或已结束循环日期,不处理! cfgID=%s,startDateStr=%s,endDateStr=%s, %s" 
+                                      % (cfgID, startDateStr, endDateStr, disableWeekCfgIDDict[cfgID]))
+                        continue
+                    
+                    if actByWeek:
+                        startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)
+                        GameWorld.Log("        星期X转化为日期: %s ~ %s" % (startDateStr, endDateStr))
+                        
+                    curServerOpenDateTime = curDateTime + datetime.timedelta(days=(1 - openServerDay)) # 开服第一天的日期
+                    customMaxServerDateTime = curDateTime + datetime.timedelta(days=(customMaxServerDay - openServerDay))
+                    curStartDateTime = datetime.datetime.strptime("%s %02d:%02d:%02d" % (startDateStr, customMaxServerDateTime.hour, customMaxServerDateTime.minute,
+                                                                                         customMaxServerDateTime.second), ChConfig.TYPE_Time_Format)
+                    if curServerOpenDateTime <= curStartDateTime <= customMaxServerDateTime:
+                        # 每日重置的默认交叉后可开启
+                        isDayRest = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()
+                        if not isDayRest and actName not in startDateInCustomCanOpenList:
+                            GameWorld.Log("        按日期/周开的开始日期在开服定制限制天内,不处理! cfgID=%s,curServerOpenDateTime=%s<=curStartDateTime=%s<=customMaxServerDateTime=%s" % (cfgID, curServerOpenDateTime, curStartDateTime, customMaxServerDateTime))
+                            continue
+                        
+                        # 非每日重置的 且 开始天在定制天内在定制天结束后可继续开启的活动
+                        # 注: 为防止开始日期与开服天内的活动开始天对应日期刚好同一天导致活动ID一样,所以这里默认将开始日期改为定制天后一天
+                        if not isDayRest and actName in startDateInCustomCanOpenList:
+                            actIDDateTimeSpec = datetime.datetime.strptime("%d-%d-%d 00:00:00" 
+                                                                           % (customMaxServerDateTime.year, customMaxServerDateTime.month, customMaxServerDateTime.day), 
+                                                                           ChConfig.TYPE_Time_Format) + datetime.timedelta(days=1)
+                            GameWorld.Log("        开服天后可开启的非每日重置活动! 活动ID日期特殊设置为开服定制天结束后一天! cfgID=%s,actIDDateTimeSpec=%s" % (cfgID, actIDDateTimeSpec))
+                            
+                        # 特殊同步的开始日期,无视是否每日重置
+                        if actName in startDateInCustomCanOpenList:
+                            startDateSync = datetime.datetime.strptime("%d-%d-%d 00:00:00" 
+                                                                       % (customMaxServerDateTime.year, customMaxServerDateTime.month, customMaxServerDateTime.day), 
+                                                                       ChConfig.TYPE_Time_Format) + datetime.timedelta(days=1)
+                            startDateSync = "%d-%d-%d" % (startDateSync.year, startDateSync.month, startDateSync.day)
+                            
+                else:
+                    GameWorld.Log("        开服常规活动,配置时间格式不支持,不处理! cfgID=%s,startDateStr=%s,endDateStr=%s" % (cfgID, startDateStr, endDateStr))
                     continue
-                openServerDateTime = curDateTime + datetime.timedelta(days=(startServerDay-openServerDay))
-                endServerDateTime = curDateTime + datetime.timedelta(days=(endServerDay-openServerDay))
+                
+            # 合服活动: 只受合服天影响
+            elif actType == ShareDefine.ActType_MixServer:
+                if not startDateStr.startswith("Mix") or not endDateStr.startswith("Mix"):
+                    GameWorld.Log("        合服活动,配置非合服天,不处理! cfgID=%s,startDateStr=%s,endDateStr=%s" % (cfgID, startDateStr, endDateStr))
+                    continue
+                if not isMixServer:
+                    GameWorld.Log("        非合服服务器,不处理! cfgID=%s,%s ~ %s" % (cfgID, startDateStr, endDateStr))
+                    continue
+                startMixServerDay, endMixServerDay = int(startDateStr[3:]), int(endDateStr[3:])
+                #结束日可能还需要处理广播之类,所以这里需要+1
+                if mixServerDay > endMixServerDay + 1:
+                    GameWorld.Log("        当前合服天超过活动结束合服天,不处理! cfgID=%s,%s ~ %s < mixServerDay(%s)" % (cfgID, startDateStr, endDateStr, mixServerDay))
+                    continue
+                openServerDateTime = curDateTime + datetime.timedelta(days=(startMixServerDay - mixServerDay))
+                endServerDateTime = curDateTime + datetime.timedelta(days=(endMixServerDay - mixServerDay))
                 startDateStr = "%d-%d-%d" % (openServerDateTime.year, openServerDateTime.month, openServerDateTime.day)
                 endDateStr = "%d-%d-%d" % (endServerDateTime.year, endServerDateTime.month, endServerDateTime.day)
-                GameWorld.Log("        开服天转化为日期: %s ~ %s" % (startDateStr, endDateStr))
-            elif actName not in ShareDefine.FeastOperationActionNameList:
-                if openServerDay <= customMaxServerDay:
-                    GameWorld.Log("        按日期开的在开服定制限制天内,不处理! cfgID=%s,%s ~ %s,openServerDay=%s" % (cfgID, startDateStr, endDateStr, openServerDay))
+                GameWorld.Log("        合服天转化为日期: %s ~ %s" % (startDateStr, endDateStr))
+                
+            # 节日活动:只受日期影响
+            elif actType == ShareDefine.ActType_Feast:
+                if startDateStr.count("-") != 2 or endDateStr.count("-") != 2:
+                    GameWorld.Log("        节日活动,配置非日期,不处理! cfgID=%s,startDateStr=%s,endDateStr=%s" % (cfgID, startDateStr, endDateStr))
                     continue
-                customMaxServerDateTime = curDateTime + datetime.timedelta(days=(customMaxServerDay-openServerDay))
-                curStartDateTime = datetime.datetime.strptime("%s %02d:%02d:%02d" % (startDateStr, customMaxServerDateTime.hour, customMaxServerDateTime.minute, 
-                                                                                     customMaxServerDateTime.second), ChConfig.TYPE_Time_Format)
-                if curStartDateTime <= customMaxServerDateTime:
-                    GameWorld.Log("        按日期开的开始日期在开服定制限制天内,不处理! cfgID=%s,curStartDateTime=%s,customMaxServerDateTime=%s" % (cfgID, curStartDateTime, customMaxServerDateTime))
-                    continue
+                
+            else:
+                GameWorld.Log("        非法配置,未知活动类型,不处理! cfgID=%s,actNum=%s" % (cfgID, actNum))
+                continue
+            
+            if hasattr(ipyData, "GetJoinStartTime") and hasattr(ipyData, "GetJoinEndTime"):
+                joinStartTimeStr = ipyData.GetJoinStartTime()
+                joinEndTimeStr = ipyData.GetJoinEndTime()
+            else:
+                joinStartTimeStr = ""
+                joinEndTimeStr = ""
                 
             if hasattr(ipyData, "GetStartTimeList") and hasattr(ipyData, "GetEndTimeList"):
                 startHMStrList = ipyData.GetStartTimeList()
@@ -198,6 +399,7 @@
                                  % (actName, cfgID, startHMStrList, endHMStrList))
                 continue
             
+            isDayRest = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()
             resetType = 0 if not hasattr(ipyData, "GetResetType") else ipyData.GetResetType() # 重置类型,0-0点重置;1-5点重置
             if resetType == 1:
                 startDayDate = datetime.datetime.strptime("%s 05:00:00" % (startDateStr), ChConfig.TYPE_Time_Format)
@@ -212,58 +414,109 @@
             advanceMinutes = 0 if not hasattr(ipyData, "GetAdvanceMinutes") else ipyData.GetAdvanceMinutes() # 提前通知时间,分钟,暂只支持按天的
             GameWorld.Log("        resetType=%s,startDayDate=%s,endDayDate=%s,startHMStrList=%s,endHMStrList=%s,advanceMinutes=%s" 
                           % (resetType, startDayDate, endDayDate, startHMStrList, endHMStrList, advanceMinutes))
+                
+            advanceNoticeDateTime = None
+            startDayDateJudge = startDayDate # 用于判断是否需要处理的起始时间,一般是活动开始时间,如果有提前广播或预告则时间会提前
+            # 提前预告
+            if advanceMinutes:
+                advanceNoticeDateTime = startDayDate + datetime.timedelta(minutes= -advanceMinutes)
+                startDayDateJudge = advanceNoticeDateTime
+            # 提前广播
+            minNotifyStartMinute = 0 if not notifyInfoDictStart else min(notifyInfoDictStart.keys())
+            if minNotifyStartMinute < 0:
+                minNotifyStartDateTime = startDayDate + datetime.timedelta(minutes=minNotifyStartMinute)
+                if minNotifyStartDateTime < startDayDateJudge:
+                    startDayDateJudge = minNotifyStartDateTime
+            if curDateTime < startDayDateJudge or curDateTime > endDayDate: # 结束时间点的时候可能需要处理广播之类的
+                GameWorld.Log("        非活动时间!不处理!")
+                continue
             
+            #注: 同个活动编号可配置多个时间不交叉的活动,如果多个时间配置同时满足条件,则只会以最后一个为准,提前预告、广播除外
+            if curActTodayInfo and curDateTime < startDayDate:
+                activityIpyData = curActTodayInfo[0]
+                ## 防止未真正开始的活动需要提前预告,而导致覆盖掉了实际正在进行中的活动,一般是活动时间配置连续的时候可能出现该情况
+                GameWorld.Log("        已经存在需要处理的配置ID(%s)! 当前需要提前通知或广播的活动未达到活动开始时间,不处理!cfgID=%s,advanceMinutes=%s,minNotifyStartMinute=%s,startDayDateJudge=%s" 
+                              % (activityIpyData.GetCfgID(), cfgID, advanceMinutes, minNotifyStartMinute, startDayDateJudge))
+                continue
+            
+            #注:刚好是结束的时间点,防范已经有需要处理的配置被覆盖
+            if curActTodayInfo and curDateTime == endDayDate:
+                activityIpyData = curActTodayInfo[0]
+                GameWorld.Log("        已经存在需要处理的配置ID(%s)! 当前刚好结束的时间点,不处理!cfgID=%s" % (activityIpyData.GetCfgID(), cfgID))
+                continue
+            
+            # 在需要处理的时间内附加世界等级开启限制,未达到最低世界等级要求的不开,活动时间从未达到到达到也不开
+            limitWorldLV = 0 if not hasattr(ipyData, "GetLimitWorldLV") else ipyData.GetLimitWorldLV() # 限制开启世界等级
+            if limitWorldLV:
+                GameWorld.Log("        limitWorldLV=%s,curWorldLV=%s" % (limitWorldLV, curWorldLV))
+                recInfoType = ""
+                worldLVLimitInfo = actWorldLVLimitInfoOld.get(actName, {})
+                # 注: 该逻辑是在活动时间内的额外处理,所以需要判断此逻辑的前提理论上都在活动时间内,故只要有记录则以当时的记录为准
+                if cfgID in worldLVLimitInfo:
+                    recInfoType = "Old"
+                    recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV = worldLVLimitInfo[cfgID]
+                else:
+                    recInfoType = "New"
+                    recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV = startDateStr, endDateStr, limitWorldLV, curWorldLV
+                    
+                if actName not in actWorldLVLimitInfoNew:
+                    actWorldLVLimitInfoNew[actName] = {}
+                actWorldLVLimitInfoNew[actName][cfgID] = [recStartDateStr, recEndDateStr, recLimitWorldLV, recWorldLV]
+                
+                if recLimitWorldLV > recWorldLV:
+                    GameWorld.Log("        活动时间内,但服务器世界等级未达到开启活动世界等级,不处理!recLimitWorldLV=%s > recWorldLV=%s %s" 
+                                  % (recLimitWorldLV, recWorldLV, recInfoType))
+                    continue
+                
             startList = [] # [startDateTime, ...]
             endList = [] # [endDateTime, ...]
             startNotifyDict = {} # {notifyDateTime:notifyInfo, ...}
             endNotifyDict = {} # {notifyDateTime:notifyInfo, ...}
             loopNotifyDict = {} # {notifyDateTime:notifyInfo, ...}
-            isActivity = False # 有需要处理开关时间的(开始、结束)
+            notifyDict = {}
+            
+            isActTime = (startDayDate <= curDateTime < endDayDate)
+            isEnd = (curDateTime == endDayDate)
             isNotify = False
             isAdvanceNotice = False
-            isEnd = False
+            
             # 没配置时分的代表全天, 只要开始或结束时分没配都算
             if not startHMStrList or not endHMStrList:
                 startDateTime = startDayDate
                 endDateTime = endDayDate
                 startList.append(startDateTime)
                 endList.append(endDateTime)
-                # 同一个活动类型是不允许时间上配置有重叠的,所以一个活动类型满足活动中的时间的有且仅有一条配置
-                # 策划可能同时配置多个时间,但是活动中的有且仅有一条配置
-                if startDayDate <= curDateTime <= endDayDate:
-                    needStartList.append(startDateTime)
-                    needEndList.append(endDateTime)
-                    isActivity = True
-                    isEnd = (curDateTime == endDayDate)
-                    
+                
             # 每天按时段开启的,支持多时段
             else:
-                if startDayDate <= curDateTime <= endDayDate:
-                    isEnd = (curDateTime == endDayDate)
-                    for hmIndex, startHMStr in enumerate(startHMStrList):
-                        endHMStr = endHMStrList[hmIndex]
-                        # 每天开的, 实际开关时间只取今天的日期; 这里有个问题,全服广播的时间不是今天的, 暂不做支持,之后真有这种需求再说
-                        startTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, startHMStr)
-                        endTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, endHMStr)
-                        startDateTime = datetime.datetime.strptime(startTimeStr, ChConfig.TYPE_Time_Format)
-                        endDateTime = datetime.datetime.strptime(endTimeStr, ChConfig.TYPE_Time_Format)
-                        
-                        startList.append(startDateTime)
-                        endList.append(endDateTime)
-                        
-                        needStartList.append(startDateTime)
-                        needEndList.append(endDateTime)
-                        isActivity = True
-                        
-            if advanceMinutes and startDayDate:
-                advanceNoticeDateTime = startDayDate + datetime.timedelta(minutes=-advanceMinutes)
+                for hmIndex, startHMStr in enumerate(startHMStrList):
+                    endHMStr = endHMStrList[hmIndex]
+                    # 每天开的, 实际开关时间只取今天的日期; 这里有个问题,全服广播的时间不是今天的, 暂不做支持,之后真有这种需求再说
+                    startTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, startHMStr)
+                    endTimeStr = "%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, endHMStr)
+                    startDateTime = datetime.datetime.strptime(startTimeStr, ChConfig.TYPE_Time_Format)
+                    endDateTime = datetime.datetime.strptime(endTimeStr, ChConfig.TYPE_Time_Format)
+                    
+                    startList.append(startDateTime)
+                    endList.append(endDateTime)
+                    
+            if advanceNoticeDateTime:
                 if advanceNoticeDateTime.year == curDateTime.year and advanceNoticeDateTime.month == curDateTime.month and advanceNoticeDateTime.day == curDateTime.day:
                     isAdvanceNotice = True
                 GameWorld.Log("        advanceNoticeDateTime=%s,isAdvanceNotice=%s" % (advanceNoticeDateTime, isAdvanceNotice))
             GameWorld.Log("        startList=%s" % (startList))
             GameWorld.Log("        end  List=%s" % (endList))
-            GameWorld.Log("        needStartList=%s" % (needStartList))
-            GameWorld.Log("        need  EndList=%s" % (needEndList))
+            
+            joinStartTimeList, joinEndTimeList = [], [] # 可指定活动可参与的时间点,不影响活动状态,只影响活动某些功能的参与时机,如上榜类
+            if joinStartTimeStr:
+                if isDayRest:
+                    joinStartTimeList.append(datetime.datetime.strptime("%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, joinStartTimeStr), ChConfig.TYPE_Time_Format))
+                    joinEndTimeList.append(datetime.datetime.strptime("%d-%d-%d %s:00" % (curDateTime.year, curDateTime.month, curDateTime.day, joinEndTimeStr), ChConfig.TYPE_Time_Format))
+                else:
+                    joinStartTimeList.append(datetime.datetime.strptime("%s %s:00" % (startDateStr, joinStartTimeStr), ChConfig.TYPE_Time_Format))
+                    joinEndTimeList.append(datetime.datetime.strptime("%s %s:00" % (endDateStr, joinEndTimeStr), ChConfig.TYPE_Time_Format))                    
+            GameWorld.Log("        joinStartTimeList=%s" % (joinStartTimeList))
+            GameWorld.Log("        joinEndTime  List=%s" % (joinEndTimeList))
             
             for dtIndex, startDateTime in enumerate(startList):
                 endDateTime = endList[dtIndex]
@@ -289,7 +542,7 @@
                     loopCount, loopMaxCount = 0, 100
                     while loopMinutes and loopNotifyKey and loopCount < loopMaxCount:
                         loopCount += 1
-                        notifyDateTime = startDateTime + datetime.timedelta(minutes=loopMinutes*loopCount)
+                        notifyDateTime = startDateTime + datetime.timedelta(minutes=loopMinutes * loopCount)
                         if notifyDateTime >= endDateTime:
                             break
                         if notifyDateTime.year == curDateTime.year and notifyDateTime.month == curDateTime.month and notifyDateTime.day == curDateTime.day:
@@ -300,50 +553,54 @@
                 GameWorld.Log("        startNotifyDict: minutes=%s, %s" % (notifyInfoDictStart.keys(), startNotifyDict))
                 GameWorld.Log("        end  NotifyDict: minutes=%s, %s" % (notifyInfoDictEnd.keys(), endNotifyDict))
                 GameWorld.Log("        loop NotifyDict: lopInfo=%s, %s" % (notifyInfoLoopInfo, loopNotifyDict.keys()))
-                needNotifyDict.update(startNotifyDict)
-                needNotifyDict.update(endNotifyDict)
-                needNotifyDict.update(loopNotifyDict)
+                notifyDict.update(startNotifyDict)
+                notifyDict.update(endNotifyDict)
+                notifyDict.update(loopNotifyDict)
                 
-            if not isActivity and not isNotify and not isAdvanceNotice:
-                continue
+            GameWorld.Log("        需要处理的运营活动信息: cfgID=%s,isActTime=%s,isEnd=%s,isNotify=%s,isAdvanceNotice=%s" % (cfgID, isActTime, isEnd, isNotify, isAdvanceNotice))
             
-            GameWorld.Log("        需要处理的运营活动信息: cfgID=%s,isAdvanceNotice=%s,isActivity=%s,isEnd=%s,isNotify=%s" % (cfgID, isAdvanceNotice, isActivity, isEnd, isNotify))
-            # 当天有需要激活活动或者提前预告活动的取非结束的为准,如果有多个非结束的一般就是策划在活动时间上配置交叉,这种是不允许的
-            if isActivity or isAdvanceNotice:
-                if not activityIpyData or (isActivity and not isEnd):
-                    activityIpyData = ipyData
-                    activityInfoDict = {ShareDefine.ActKey_CfgID:cfgID}
-                    if actName == ShareDefine.OperationActionName_LoginAward:
-                        #活动每天的世界等级
-                        activityInfoDict[ShareDefine.ActKey_WorldLVList] = GameWorldAverageLv.GetWorldLVListByTime(startDayDate, (endDayDate - startDayDate).days)
+            # 兼容新旧运营活动逻辑处理数据
+            if actName in ShareDefine.MultiActNumOperationActNameList:
+                if actName not in operationTodayActionDict:
+                    operationTodayActionDict[actName] = {} # 今日有需要处理的才初始化
+                operationTodayActionDict[actName][actNum] = [ipyData, startList, endList, notifyDict, joinStartTimeList, joinEndTimeList]
+            else:
+                operationTodayActionDict[actName] = [ipyData, startList, endList, notifyDict, joinStartTimeList, joinEndTimeList]
+                
+            if isActTime:
+                activityInfoDict = {ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_ActNum:actNum}
+                if actName == ShareDefine.OperationActionName_LoginAward:
+                    #活动每天的世界等级
+                    activityInfoDict[ShareDefine.ActKey_WorldLVList] = GameWorldAverageLv.GetWorldLVListByTime(startDayDate, (endDayDate - startDayDate).days)
                     
-                    if startDayDate <= curDateTime < endDayDate:
-                        dayIndex = 0
-                        actIDDateTime = startDayDate
-                        isDayRest = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()
-                        # 按时段开的默认每天重置
-                        if isDayRest or (startHMStrList and endHMStrList):
-                            dayIndex = (curDateTime - startDayDate).days
-                            actIDDateTime += datetime.timedelta(days=dayIndex)
-                        actID = int(time.mktime(actIDDateTime.timetuple())) # 默认取开始时间点的time值作为活动ID
-                        activityInfoDict[ShareDefine.ActKey_DayIndex] = dayIndex
-                        activityInfoDict[ShareDefine.ActKey_ID] = actID
-                        GameWorld.Log("        isDayRest=%s,actIDDateTime=%s,actID=%s" % (isDayRest, actIDDateTime, actID))
-                        
-                    needStartList.sort()
-                    needEndList.sort()
+                if startDateSync:
+                    activityInfoDict[ShareDefine.ActKey_StartDateSync] = startDateSync
+                    GameWorld.Log("        startDateSync=%s" % (startDateSync))
                     
+                dayIndex = (curDateTime - startDayDate).days
+                actIDDateTime = startDayDate
+                # 按时段开的默认每天重置
+                if isDayRest or (startHMStrList and endHMStrList):
+                    actIDDateTime += datetime.timedelta(days=dayIndex)
+                if actIDDateTimeSpec:
+                    actIDDateTime = actIDDateTimeSpec
+                actID = int(time.mktime(actIDDateTime.timetuple())) # 默认取开始时间点的time值作为活动ID
+                activityInfoDict[ShareDefine.ActKey_DayIndex] = dayIndex
+                activityInfoDict[ShareDefine.ActKey_ID] = actID
+                GameWorld.Log("        isDayRest=%s,actIDDateTime=%s,actID=%s" % (isDayRest, actIDDateTime, actID))
+                GameWorld.Log("        activityInfoDict=%s" % (activityInfoDict))
+                
+                # 兼容新旧运营活动逻辑处理数据
+                if actName in ShareDefine.MultiActNumOperationActNameList:
+                    mapServerOperationActionDict[actName][actNum] = activityInfoDict
+                else:
                     mapServerOperationActionDict[actName] = activityInfoDict
-                    GameWorld.Log("        activityInfoDict=%s" % (activityInfoDict))
                     
-        if activityIpyData or needStartList or needEndList or needNotifyDict:
-            # activityIpyData 可能为None
-            operationActionDict[actName] = [activityIpyData, needStartList, needEndList, needNotifyDict]
-            
-    OperationActionInfo = IpyGameDataPY.SetConfigEx(key, [reloadSign, operationActionDict, mapServerOperationActionDict])
+    OperationActionInfo = IpyGameDataPY.SetConfigEx(key, [reloadSign, operationTodayActionDict, mapServerOperationActionDict])
+    __SaveActWorldLVLimitInfo(actWorldLVLimitInfoNew)
     
     GameWorld.Log("本日运营活动信息加载完毕!reloadSign=%s,isRefreshState=%s" % (reloadSign, isRefreshState))
-    GameWorld.Log("    operationActionDict=%s" % operationActionDict)
+    GameWorld.Log("    operationTodayActionDict=%s" % operationTodayActionDict)
     GameWorld.Log("    mapServerOperationActionDict=%s" % mapServerOperationActionDict)
     GameWorld.Log("=============================================================")
     if isRefreshState:
@@ -351,58 +608,118 @@
         
     return True, OperationActionInfo
 
-def __GetOperationActionServerIpyDataList(ipyDataMgr, serverID, actName):
+def __GetOperationActionServerIpyDataList(ipyDataMgr, platform, serverGroupID, actName):
     ## 获取运营活动本服务器对应的配置数据列表
     
     if not hasattr(ipyDataMgr, "Get%sCount" % actName):
         GameWorld.ErrLog("没有该运营活动类型对应活动时间表! actName=%s" % actName)
         return []
     
-    # 所有配置先按活动标识归组
-    platform = GameWorld.GetPlatform()
-    actGroupDict = {} # {ActMark:{ServerIDTuple:[ipyData, ...], ...}, ...}
+    curServerActIpyDataList = []
     actCfgCount = getattr(ipyDataMgr, "Get%sCount" % actName)()
     for cfgIndex in xrange(actCfgCount):
-        ipyData = getattr(ipyDataMgr, "Get%sByIndex" % actName)(cfgIndex)
-        actMark = ipyData.GetActMark()
+        ipyData = getattr(ipyDataMgr, "Get%sByIndex" % actName)(cfgIndex)            
         platformList = [] if not hasattr(ipyData, "GetPlatformList") else ipyData.GetPlatformList()
+        serverGroupIDList = [] if not hasattr(ipyData, "GetServerGroupIDList") else ipyData.GetServerGroupIDList()
+        serverGroupIDListExcept = [] if not hasattr(ipyData, "GetServerGroupIDListExcept") else ipyData.GetServerGroupIDListExcept()
+        
         if platformList and platform not in platformList:
-            GameWorld.Log("非本平台活动,不取!platform=%s,platformList=%s,actName=%s,cfgID=%s" % (platform, platformList, actName, ipyData.GetCfgID()))
             continue
-        serverIDTuple = tuple(ipyData.GetServerIDList())
         
-        serverIpyDataDict = actGroupDict.get(actMark, {})
-        ipyDataList = serverIpyDataDict.get(serverIDTuple, [])
-        ipyDataList.append(ipyData)
-        serverIpyDataDict[serverIDTuple] = ipyDataList
-        actGroupDict[actMark] = serverIpyDataDict
-        
-    # 取出所属本服ID的所有配置
-    curServerActIpyDataList = []
-    for actMark, serverIpyDataDict in actGroupDict.items():
-        generalIpyDataList = []
-        isGeneral = True
-        for serverIDTuple, ipyDataList in serverIpyDataDict.items():
-            if not serverIDTuple:
-                generalIpyDataList = ipyDataList
-                continue
-            for serverIDInfo in serverIDTuple:
-                if (isinstance(serverIDInfo, int) and serverIDInfo == serverID) \
-                    or ((isinstance(serverIDInfo, list) or isinstance(serverIDInfo, tuple)) \
-                        and len(serverIDInfo) == 2 and serverIDInfo[0] <= serverID <= serverIDInfo[1]):
-                    curServerActIpyDataList += ipyDataList
-                    isGeneral = False
+        # 排除的服务器组ID列表
+        if serverGroupIDListExcept:
+            isExcept = False
+            for serverGroupIDInfo in serverGroupIDListExcept:
+                if (isinstance(serverGroupIDInfo, int) and serverGroupIDInfo == serverGroupID) \
+                    or ((isinstance(serverGroupIDInfo, list) or isinstance(serverGroupIDInfo, tuple)) \
+                        and len(serverGroupIDInfo) == 2 and serverGroupIDInfo[0] <= serverGroupID <= serverGroupIDInfo[1]):
+                    isExcept = True
                     break
-        if isGeneral:
-            curServerActIpyDataList += generalIpyDataList
+            if isExcept:
+                continue
+            
+        if not serverGroupIDList:
+            curServerActIpyDataList.append(ipyData)
+        else:
+            for serverGroupIDInfo in serverGroupIDList:
+                if (isinstance(serverGroupIDInfo, int) and serverGroupIDInfo == serverGroupID) \
+                    or ((isinstance(serverGroupIDInfo, list) or isinstance(serverGroupIDInfo, tuple)) \
+                        and len(serverGroupIDInfo) == 2 and serverGroupIDInfo[0] <= serverGroupID <= serverGroupIDInfo[1]):
+                    curServerActIpyDataList.append(ipyData)
+                    break
+                
     return curServerActIpyDataList
+
+def __GetOperationActionDisableWeekIpyDataInfo(actName, curDateTime, curServerActIpyDataList):
+    ## 获取不可用的按星期X开启的配置数据信息,按星期X开启的 活动优先级小于按日期的,当有重叠时以日期的为准
+    #curWeekday = curDateTime.weekday() + 1 # 今天星期几, 1代表星期1
+    actNumWeekYMDIpyDataInfo = {} # {actNum:[weekIpyDataList, ymdIpyDatList], ...}
+    disableWeekCfgIDDict = {} # {cfgID:[startDateStr, endDateStr], ...}
+    
+    curDateTimeYmdStr = "%d-%d-%d" % (curDateTime.year, curDateTime.month, curDateTime.day)
+    curDateTimeYmd = GameWorld.ChangeStrToDatetime(curDateTimeYmdStr, ChConfig.TYPE_Time_YmdFormat)
+    
+    for ipyData in curServerActIpyDataList:
+        cfgID = ipyData.GetCfgID()
+        startDateStr = ipyData.GetStartDate()
+        endDateStr = ipyData.GetEndDate()
+        actNum = GetOperationActNum(actName, ipyData)
+        actType = GetOperationActType(actNum)
+        # 这里只处理常规运营活动,日期优先级大于周
+        if actType != ShareDefine.ActType_OpenComm:
+            continue
+        
+        if actNum not in actNumWeekYMDIpyDataInfo:
+            weekIpyDataList, ymdIpyDatList = [], []
+            actNumWeekYMDIpyDataInfo[actNum] = [weekIpyDataList, ymdIpyDatList]
+        weekIpyDataList, ymdIpyDatList = actNumWeekYMDIpyDataInfo[actNum]
+        
+        # 按星期X的
+        if startDateStr.startswith("W"):
+            startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)
+            startWeekDate = GameWorld.ChangeStrToDatetime(startDateStr, ChConfig.TYPE_Time_YmdFormat)
+            endWeekDate = GameWorld.ChangeStrToDatetime(endDateStr, ChConfig.TYPE_Time_YmdFormat)
+            if startWeekDate > curDateTimeYmd or curDateTimeYmd > endWeekDate: # 还未开始的循环 or 已经强制结束的循环
+                disableWeekCfgIDDict[cfgID] = [startDateStr, endDateStr]
+            else:
+                weekIpyDataList.append([ipyData, startWeekDate, endWeekDate])
+            
+        # 按日期的
+        elif startDateStr.count("-") == 2:
+            ymdIpyData = ipyData
+            ymdStartDate = datetime.datetime.strptime("%s %02d:%02d:00" % (startDateStr, curDateTime.hour, curDateTime.minute), ChConfig.TYPE_Time_Format)
+            ymdEndDate = datetime.datetime.strptime("%s %02d:%02d:00" % (endDateStr, curDateTime.hour, curDateTime.minute), ChConfig.TYPE_Time_Format)
+            ymdIpyDatList.append([ymdIpyData, ymdStartDate, ymdEndDate])
+            
+        else:
+            # 只处理按星期、按日期的,其他的不处理
+            pass
+        
+    actNumDisableWeekIpyDataInfo = {} # {actNum:{cfgID:[info], ...}, ...}
+    for actNum, weekYMDIpyDataInfo in actNumWeekYMDIpyDataInfo.items():
+        weekIpyDataList, ymdIpyDatList = weekYMDIpyDataInfo
+        for ipyData, startWeekDate, endWeekDate in weekIpyDataList:
+            cfgID = ipyData.GetCfgID()
+            for ymdIpyData, ymdStartDate, ymdEndDate in ymdIpyDatList:
+                if ymdStartDate <= startWeekDate <= ymdEndDate or ymdStartDate <= endWeekDate <= ymdEndDate:
+                    if actNum not in actNumDisableWeekIpyDataInfo:
+                        actNumDisableWeekIpyDataInfo[actNum] = {}
+                    ymdCfgID = ymdIpyData.GetCfgID()
+                    actNumDisableWeekIpyDataInfo[actNum][cfgID] = [startWeekDate, endWeekDate, ymdCfgID, ymdStartDate, ymdEndDate]
+                    
+    return actNumDisableWeekIpyDataInfo, disableWeekCfgIDDict
 
 def Dispose_OperationActionState(reloadRefresh=False):
     # 运营活动状态处理, 每天0点会强制同步当天的运营活动详情到地图服务器
     
+    if GameWorld.IsCrossServer():
+        # 跨服不处理运营活动
+        CrossActionControl.Dispose_CrossActState(reloadRefresh)
+        return
+    
     isReload, OperationActionInfo = __GetOperationActionInfo(False) # 这里必须传False
     isReload = isReload or reloadRefresh
-    operationActionDict = OperationActionInfo[OperationAction_TodayInfo]
+    operationTodayActionDict = OperationActionInfo[OperationAction_TodayInfo]
     mapServerInfoDict = OperationActionInfo[OperationAction_MapServerInfo]
     
     gameWorld = GameWorld.GetGameWorld()
@@ -414,113 +731,195 @@
     
     for actName in ShareDefine.OperationActionNameList:
         
-        state = 0 # 默认关闭
-        ipyData = None
-        
-        if actName in operationActionDict:
-            
-            #startList = [] # [startDateTime, ...]
-            #endList = [] # [endDateTime, ...]
-            #notifyDict = {} # {notifyDateTime:[notifyKey, [参数]], ...}
-            #ipyData 可能为 None
-            ipyData, startList, endList, notifyDict = operationActionDict[actName]
-            # 精确匹配开启
-            if curDateTime in startList:
-                state = startList.index(curDateTime) + 1 # 也是代表第几个时间段
-            # 精确匹配关闭
-            elif curDateTime in endList:
-                state = 0
-            # goon 状态
-            else:
-                for dIndex, startDateTime in enumerate(startList):
-                    endDateTime = endList[dIndex]
-                    if startDateTime < curDateTime < endDateTime:
-                        state = dIndex + 1
-                        break
-                    
-            # 全服广播提示信息
-            if curDateTime in notifyDict:
-                notifyKey, paramList = notifyDict[curDateTime]
-                PlayerControl.WorldNotify(0, notifyKey, paramList)
-                
-        dictName = ChConfig.Def_WorldKey_OperationActionState % actName
-        preState = gameWorld.GetDictByKey(dictName)
-        if not isReload and preState == state:
-            #已经是这个状态了
+        if actName not in mapServerInfoDict:
             continue
-        #更新字典值
-        gameWorld.SetDict(dictName, state)
-        sendMapServerMsgDict = mapServerInfoDict.get(actName, {})
         
-        dbOperationActIDKey = PlayerDBGSEvent.Def_OperationActID % actName
-        curActID = sendMapServerMsgDict.get(ShareDefine.ActKey_ID)
-        dayIndex = sendMapServerMsgDict.get(ShareDefine.ActKey_DayIndex, 0)
-        if curActID and PlayerDBGSEvent.GetDBGSTrig_ByKey(dbOperationActIDKey) != curActID:
-            PlayerDBGSEvent.SetDBGSTrig_ByKey(dbOperationActIDKey, curActID)
-            if actName in ShareDefine.NeedWorldLVOperationActNameList:
-                #记录开启时世界等级
-                worldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
-                PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_OActWorldLV % actName, worldLV)
+        if actName in ShareDefine.MultiActNumOperationActNameList:
+            curActMapInfoDictList = mapServerInfoDict[actName].values()
+        else:
+            curActMapInfoDictList = [mapServerInfoDict[actName]]
+            
+        for sendMapServerMsgDict in curActMapInfoDictList:
+            
+            state = 0 # 默认关闭
+            stateJoin = ShareDefine.ActStateJoin_None # 可参与状态,0-参与前;1-可参与;2-参与结束
+            ipyData = None
+            
+            actNum = sendMapServerMsgDict.get(ShareDefine.ActKey_ActNum, 0)
+            
+            if actName in operationTodayActionDict:
+                todayActInfoList = []
+                if actName in ShareDefine.MultiActNumOperationActNameList:
+                    if actNum in operationTodayActionDict[actName]:
+                        todayActInfoList = operationTodayActionDict[actName][actNum]
+                else:
+                    todayActInfoList = operationTodayActionDict[actName]
+                    
+                if isinstance(todayActInfoList, list) and len(todayActInfoList) == 6:
+                    #startList = [] # [startDateTime, ...]
+                    #endList = [] # [endDateTime, ...]
+                    #notifyDict = {} # {notifyDateTime:[notifyKey, [参数]], ...}
+                    #ipyData 可能为 None
+                    ipyData, startList, endList, notifyDict, joinStartTimeList, joinEndTimeList = todayActInfoList
+                    
+                    # 状态
+                    for dIndex, startDateTime in enumerate(startList):
+                        endDateTime = endList[dIndex]
+                        if startDateTime <= curDateTime < endDateTime:
+                            state = dIndex + 1 # 代表第几个时间段
+                            break
+                        
+                    if joinStartTimeList:
+                        for jIndex, joinStartDateTime in enumerate(joinStartTimeList):
+                            endJoinDateTime = joinEndTimeList[jIndex]
+                            if joinStartDateTime <= curDateTime < endJoinDateTime:
+                                stateJoin = ShareDefine.ActStateJoin_Start
+                                break
+                            elif curDateTime >= endJoinDateTime:
+                                stateJoin = ShareDefine.ActStateJoin_End
+                    else:
+                        stateJoin = ShareDefine.ActStateJoin_Start if state else ShareDefine.ActStateJoin_None
+                        
+                    # 全服广播提示信息
+                    if curDateTime in notifyDict:
+                        notifyKey, paramList = notifyDict[curDateTime]
+                        PlayerControl.WorldNotify(0, notifyKey, paramList)
+                        
+            dictName = ChConfig.Def_WorldKey_OperationActionState % actName
+            if actName in ShareDefine.MultiActNumOperationActNameList:
+                dictName += "_%s" % actNum
+            preState = gameWorld.GetDictByKey(dictName)
+            
+            dictNameJoin = ChConfig.Def_WorldKey_OperationActionStateJoin % actName
+            if actName in ShareDefine.MultiActNumOperationActNameList:
+                dictNameJoin += "_%s" % actNum
+            preStateJoin = gameWorld.GetDictByKey(dictNameJoin)
+            
+            if not isReload and preState == state and preStateJoin == stateJoin:
+                #已经是这个状态了
+                continue
+            GameWorld.Log("运营活动变更: actName=%s,actNum=%s,preState=%s,state=%s,preStateJoin=%s,stateJoin=%s" % (actName, actNum, preState, state, preStateJoin, stateJoin))
+            #更新字典值
+            gameWorld.SetDict(dictName, state)
+            gameWorld.SetDict(dictNameJoin, stateJoin)
+            
+            dbOperationActIDKey = PlayerDBGSEvent.Def_OperationActID % actName
+            dbOperationActWorldLVKey = PlayerDBGSEvent.Def_OActWorldLV % actName
+            if actName in ShareDefine.MultiActNumOperationActNameList:         
+                dbOperationActIDKey += "_%s" % actNum
+                dbOperationActWorldLVKey += "_%s" % actNum
                 
-            #此处为活动开启时
-            if actName == ShareDefine.OperationActionName_BossReborn:
-                #重置BOSS复活点
-                GameWorldBoss.ResetBossRebornPoint()
+            dbActID = PlayerDBGSEvent.GetDBGSTrig_ByKey(dbOperationActIDKey)
+            curActID = sendMapServerMsgDict.get(ShareDefine.ActKey_ID, 0)
+            dayIndex = sendMapServerMsgDict.get(ShareDefine.ActKey_DayIndex, 0)
+            if dbActID != curActID:
+                GameWorld.Log("    dbActID变更: dbActID=%s,curActID=%s" % (dbActID, curActID))
+                PlayerDBGSEvent.SetDBGSTrig_ByKey(dbOperationActIDKey, curActID)
+                
+                # 结束旧的
+                if dbActID:
+                    if actName == ShareDefine.OperationActionName_BossTrial:
+                        PlayerActBossTrial.OnActEnd(actNum, ipyData, dayIndex)
+                        
+                if curActID:
+                    if actName in ShareDefine.NeedWorldLVOperationActNameList:
+                        #记录开启时世界等级
+                        worldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
+                        PlayerDBGSEvent.SetDBGSTrig_ByKey(dbOperationActWorldLVKey, worldLV)
+                        GameWorld.Log("    记录活动开启时世界等级: worldLV=%s" % (worldLV))
+                        
+                    #此处为活动开启时
+                    if actName == ShareDefine.OperationActionName_BossReborn:
+                        #重置BOSS复活点
+                        GameWorldBoss.ResetBossRebornPoint()
+                    elif actName == ShareDefine.OperationActionName_FairyCeremony:
+                        #重置仙界盛典
+                        PlayerFairyCeremony.ResetFairyCeremony()
+                    elif actName == ShareDefine.OperationActionName_NewFairyCeremony:
+                        #重置仙界盛典
+                        PlayerNewFairyCeremony.ResetNewFairyCeremony()
+                    elif actName == ShareDefine.OperationActionName_FeastRedPacket:
+                        #重置节日红包
+                        if ipyData:
+                            PlayerFamilyRedPacket.OnResetFeastRedPacket(ipyData, dayIndex)
+                    elif actName == ShareDefine.OperationActionName_FlashSale:
+                        #限时抢购重置购买次数 本次活动每场不能重复
+                        #dayIndex = sendMapServerMsgDict.get(ShareDefine.ActKey_DayIndex, 0)
+                        PlayerStore.ResetFlashSaleBuyCnt(ipyData)
+                    elif actName == ShareDefine.OperationActionName_GarbageSorting:
+                        PlayerActGarbageSorting.OnActStart(actNum)
+                    elif actName == ShareDefine.OperationActionName_BossTrial:
+                        PlayerActBossTrial.OnActStart(actNum)
+                    elif actName == ShareDefine.OperationActionName_FamilyCTGAssist:
+                        PlayerActFamilyCTGAssist.OnActStart(actNum)
+                else:
+                    if actName == ShareDefine.OperationActionName_GarbageSorting:
+                        PlayerActGarbageSorting.OnActEnd(actNum)
+                        
+            else:
+                GameWorld.Log("    dbActID不变: dbActID=%s,curActID=%s" % (dbActID, curActID))
+                
+            # 仅活动有配置参与时间段的会触发
+            if curActID and dbActID == curActID and preStateJoin != stateJoin:
+                GameWorld.Log("    参与状态变更: preStateJoin=%s,stateJoin=%s" % (preStateJoin, stateJoin))
+                # 参与开始
+                if stateJoin == ShareDefine.ActStateJoin_Start:
+                    pass
+                # 参与结束
+                elif stateJoin == ShareDefine.ActStateJoin_End:
+                    if actName == ShareDefine.OperationActionName_BossTrial:
+                        PlayerActBossTrial.OnActJoinEnd(actNum, ipyData, dayIndex)
+                        
+            if ipyData and actName in ShareDefine.NeedWorldLVOperationActNameList:
+                actWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(dbOperationActWorldLVKey)
+                sendMapServerMsgDict[ShareDefine.ActKey_WorldLV] = actWorldLV
+                GameWorld.Log("    活动世界等级: actWorldLV=%s" % (actWorldLV))
+                
+            if actName == ShareDefine.OperationActionName_ExpRate:
+                if isReload and ipyData:
+                    Sync_OperationAction_ExpRate(ipyData)
+                    
+            elif actName == ShareDefine.OperationActionName_BossReborn:
+                if isReload and ipyData:
+                    GameWorldBoss.SetBossRebornNeedPoint(True)
+                    
+            elif actName == ShareDefine.OperationActionName_HorsePetFeast:
+                if preState != state and state:
+                    relatedID = "%s|%s" % (actName, actNum)
+                    GameWorld.Log("    骑宠盛宴开始: relatedID=%s" % (relatedID))
+                    GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_ActionBossRebornSign % relatedID, int(time.time()))
+                    
             elif actName == ShareDefine.OperationActionName_FairyCeremony:
-                #重置仙界盛典
-                PlayerFairyCeremony.ResetFairyCeremony()
+                if isReload and ipyData:
+                    PlayerFairyCeremony.Sync_OperationAction_FairyCeremony(ipyData)
+                if preState != state and state == 0:
+                    PlayerFairyCeremony.OnFairyCeremonyEnd()
             elif actName == ShareDefine.OperationActionName_NewFairyCeremony:
-                #重置仙界盛典
-                PlayerNewFairyCeremony.ResetNewFairyCeremony()
+                if isReload and ipyData:
+                    PlayerNewFairyCeremony.Sync_OperationAction_NewFairyCeremony(ipyData)
+                if preState != state and state == 0:
+                    PlayerNewFairyCeremony.OnNewFairyCeremonyEnd()
+            
+            elif actName == ShareDefine.OperationActionName_RealmPoint:
+                if isReload and ipyData:
+                    Sync_OperationAction_RealmPoint(ipyData)
             elif actName == ShareDefine.OperationActionName_FeastRedPacket:
-                #重置节日红包
-                if ipyData:
-                    PlayerFamilyRedPacket.OnResetFeastRedPacket(ipyData, dayIndex)
-            elif actName == ShareDefine.OperationActionName_FlashSale:
-                #限时抢购重置购买次数 本次活动每场不能重复
-                #dayIndex = sendMapServerMsgDict.get(ShareDefine.ActKey_DayIndex, 0)
-                PlayerStore.ResetFlashSaleBuyCnt(ipyData)
-                
-        if actName in ShareDefine.NeedWorldLVOperationActNameList:
-            actWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_OActWorldLV % actName)
-            sendMapServerMsgDict[ShareDefine.ActKey_WorldLV] = actWorldLV
-        
-        if actName == ShareDefine.OperationActionName_ExpRate:
-            if isReload and ipyData:
-                Sync_OperationAction_ExpRate(ipyData)
-                
-        elif actName == ShareDefine.OperationActionName_CostRebate:
-            if isReload and ipyData:
-                pass
-        elif actName == ShareDefine.OperationActionName_BossReborn:
-            if isReload and ipyData:
-                GameWorldBoss.SetBossRebornNeedPoint(True)
-
-        elif actName == ShareDefine.OperationActionName_FairyCeremony:
-            if isReload and ipyData:
-                PlayerFairyCeremony.Sync_OperationAction_FairyCeremony(ipyData)
-            if preState != state and state == 0:
-                PlayerFairyCeremony.OnFairyCeremonyEnd()
-        elif actName == ShareDefine.OperationActionName_NewFairyCeremony:
-            if isReload and ipyData:
-                PlayerNewFairyCeremony.Sync_OperationAction_NewFairyCeremony(ipyData)
-            if preState != state and state == 0:
-                PlayerNewFairyCeremony.OnNewFairyCeremonyEnd()
-        
-        elif actName == ShareDefine.OperationActionName_RealmPoint:
-            if isReload and ipyData:
-                Sync_OperationAction_RealmPoint(ipyData)
-        elif actName == ShareDefine.OperationActionName_FeastRedPacket:
-            if isReload and ipyData:
-                PlayerFamilyRedPacket.Sync_FeastRedPacket(ipyData)
-                
-        #通知Mapserver,设置字典
-        #GameWorld.SendMapServerMsgEx(dictName, state) # 运营活动不单独通知活动状态,需与活动信息整合后一起通知
-        
-        sendMapServerMsgDict[ShareDefine.ActKey_State] = state
-        GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_OperationActionInfo % actName, sendMapServerMsgDict)
-        
-        GameWorld.Log("运营活动变更: actName=%s,preState=%s,state=%s,dictName=%s, %s" % (actName, preState, state, dictName, sendMapServerMsgDict))
+                if isReload and ipyData:
+                    PlayerFamilyRedPacket.Sync_FeastRedPacket(ipyData)
+                    
+            #通知Mapserver,设置字典
+            #GameWorld.SendMapServerMsgEx(dictName, state) # 运营活动不单独通知活动状态,需与活动信息整合后一起通知
+            
+            sendMapServerMsgDict[ShareDefine.ActKey_State] = state
+            sendMapServerMsgDict[ShareDefine.ActKey_StateJoin] = stateJoin
+            GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_OperationActionInfo % actName, sendMapServerMsgDict)
+            
+            GameWorld.Log("    sendMapServerMsgDict: %s" % (sendMapServerMsgDict))
+            
+            if actName in ShareDefine.MultiActNumOperationActNameList:
+                mapServerInfoDict[actName][actNum] = sendMapServerMsgDict
+            else:
+                mapServerInfoDict[actName] = sendMapServerMsgDict
     return
 
 def Sync_OperationAction_ExpRate(ipyData, curPlayer=None):
@@ -528,11 +927,11 @@
         return
     if len(ipyData.GetStartTimeList()) != len(ipyData.GetEndTimeList()):
         return
-    openServerDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ServerDay) + 1
+    startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)
     multiExpRateInfo = ChPyNetSendPack.tagGCMultiExpRateInfo()
     multiExpRateInfo.Clear()
-    multiExpRateInfo.StartDate = GameWorld.GetOperationActionDateStr(ipyData.GetStartDate(), openServerDay)
-    multiExpRateInfo.EndtDate = GameWorld.GetOperationActionDateStr(ipyData.GetEndDate(), openServerDay)
+    multiExpRateInfo.StartDate = startDateStr
+    multiExpRateInfo.EndtDate = endDateStr
     multiExpRateInfo.ActivityTime = []
     for i, startTime in enumerate(ipyData.GetStartTimeList()):
         endTime = ipyData.GetEndTimeList()[i]
@@ -561,11 +960,11 @@
     ##多倍修行点活动信息通知
     if not ipyData:
         return
-    openServerDay = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ServerDay) + 1
+    startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)
     multiRealmPointInfo = ChPyNetSendPack.tagGCMultiRealmPointInfo()
     multiRealmPointInfo.Clear()
-    multiRealmPointInfo.StartDate = GameWorld.GetOperationActionDateStr(ipyData.GetStartDate(), openServerDay)
-    multiRealmPointInfo.EndtDate = GameWorld.GetOperationActionDateStr(ipyData.GetEndDate(), openServerDay)
+    multiRealmPointInfo.StartDate = startDateStr
+    multiRealmPointInfo.EndtDate = endDateStr
     multiRealmPointInfo.Multiple = ipyData.GetMultiple()
     multiRealmPointInfo.LimitLV = ipyData.GetLVLimit()
     multiRealmPointInfo.LimitPoint = ipyData.GetPointLimit()
@@ -636,19 +1035,21 @@
         GameWorld.Log("    本周定制的开服日常活动ID列表: %s" % (customDailyIDList))
         GameWorld.Log("    今天定制的开服日常表ID列表=%s" % (todayCustomIDList))
     elif isMixServer and mixServerDay <= maxCustomServerDayMix:
-        customIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("DailyActionCustomMix", mixServerDay)
-        if not customIpyDataList:
-            customIpyDataList = []
-        GameWorld.Log("    今天定制的合服日常活动条数: %s" % len(customIpyDataList))
-        for customIpyData in customIpyDataList:
+        todayCustomIDList = [] # 今天定制的数据表ID
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for i in xrange(ipyDataMgr.GetDailyActionCustomMixCount()):
+            customIpyData = ipyDataMgr.GetDailyActionCustomMixByIndex(i)
             dataID = customIpyData.GetID()
             dailyID = customIpyData.GetDailyID()
             if dailyID not in customDailyIDList:
                 customDailyIDList.append(dailyID)
-            customType = 2
-            dailyTimeInfoList.append([customType, customIpyData.GetOpenTimeList(), customIpyData])
-            GameWorld.Log("    增加本日合服日常活动信息: customType=%s,dailyID=%s,dataID=%s" % (customType, dailyID, dataID))
-        GameWorld.Log("    今天定制的合服日常活动ID列表: %s" % (customDailyIDList))
+            if customIpyData.GetMixServerDay() == mixServerDay:
+                todayCustomIDList.append(dataID)
+                customType = 2
+                dailyTimeInfoList.append([customType, customIpyData.GetOpenTimeList(), customIpyData])
+                GameWorld.Log("    增加本日合服日常活动信息: customType=%s,dailyID=%s,dataID=%s" % (customType, dailyID, dataID))
+        GameWorld.Log("    定制的合服日常活动ID列表: %s" % (customDailyIDList))
+        GameWorld.Log("    今天定制的合服日常表ID列表=%s" % (todayCustomIDList))
     else:
         GameWorld.Log("    超过最大定制开服天,不定制,走常规日常配置!")
     
@@ -658,6 +1059,10 @@
     for i in xrange(dailyActionCount):
         dailyIpyData = ipyDataMgr.GetDailyActionByIndex(i)
         dailyID = dailyIpyData.GetDailyID()
+        
+        if dailyID in [ShareDefine.DailyActionID_CrossBattlefield]:
+            GameWorld.Log("    不需要处理的日常活动! dailyID=%s" % dailyID)
+            continue
         
         # 是当天开服天定制活动的不处理常规活动
         if dailyID in customDailyIDList:
@@ -726,6 +1131,9 @@
 def Dispose_DailyActionState():
     # 日常活动状态变更检查处理
     
+    if GameWorld.IsCrossServer():
+        CrossActionControl.Dispose_CrossDailyActionState()
+    
     todayDailyActionInfo = __GetTodayDailyActionInfo()
     if not todayDailyActionInfo:
         return
@@ -768,7 +1176,8 @@
                 PlayerControl.WorldNotify(0, notifyKey, paramList)
                 
         dictName = ShareDefine.Def_Notify_WorldKey_DailyActionState % dailyActionID
-        if gameWorld.GetDictByKey(dictName) == state:
+        beforeState = gameWorld.GetDictByKey(dictName)
+        if beforeState == state:
             #已经是这个状态了
             continue
         
@@ -776,24 +1185,34 @@
             # 骑宠争夺活动开始前同步有效人数到地图
             if dailyActionID == ShareDefine.DailyActionID_FamilyRobBoss:
                 GameWorldBoss.SyncMapServer_HorsePetRobBossPlayerCount()
+                GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_ActionBossRebornSign % dailyActionID, int(time.time()))
                 
         #通知Mapserver,设置字典
         GameWorld.SendMapServerMsgEx(dictName, state)
         #更新字典值
         gameWorld.SetDict(dictName, state)
         GameWorld.Log("日常活动状态变更: dailyActionID=%s,state=%s,dictName=%s" % (dailyActionID, state, dictName))
-        __DoLogic_GameServer_ActionState(dictName, state)
+        __DoLogic_GameServer_ActionState(dictName, state, beforeState)
         
     return
 
 def SendMapServerDailyActionState():
     # 地图启动成功时通知本日进行中的日常活动状态
     
+    gameWorld = GameWorld.GetGameWorld()
+    if GameWorld.IsCrossServer():
+        CrossActionControl.SendMapServerCrossDailyActionState()
+    else:
+        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 
@@ -936,19 +1355,21 @@
         GameWorld.Log("    本周定制的开服副本地图列表: %s" % (customMapIDList))
         GameWorld.Log("    今天定制的开服副本表ID列表=%s" % (todayCustomIDList))
     elif isMixServer and mixServerDay <= maxCustomServerDayMix:
-        customIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("FBStateTimeCustomMix", mixServerDay)
-        if not customIpyDataList:
-            customIpyDataList = []
-        GameWorld.Log("    本日定制的合服副本活动条数: %s" % len(customIpyDataList))
-        for customIpyData in customIpyDataList:
+        todayCustomIDList = [] # 今天定制的数据表ID
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for i in xrange(ipyDataMgr.GetFBStateTimeCustomMixCount()):
+            customIpyData = ipyDataMgr.GetFBStateTimeCustomMixByIndex(i)
             dataID = customIpyData.GetID()
             dataMapID = customIpyData.GetDataMapID()
             if dataMapID not in customMapIDList:
                 customMapIDList.append(dataMapID)
-            customType, startWeekDay, endWeekDay = 2, curWeekDay, curWeekDay
-            fbStateTimeInfoList.append([customType, startWeekDay, endWeekDay, customIpyData])
-            GameWorld.Log("    今天要处理的合服副本状态配置: customType=%s,dataID=%s" % (customType, dataID))
-        GameWorld.Log("    本日定制的合服副本地图列表: %s" % (customMapIDList))
+            if customIpyData.GetMixServerDay() == mixServerDay:
+                todayCustomIDList.append(dataID)
+                customType, startWeekDay, endWeekDay = 2, curWeekDay, curWeekDay
+                fbStateTimeInfoList.append([customType, startWeekDay, endWeekDay, customIpyData])
+                GameWorld.Log("    今天要处理的合服副本状态配置: customType=%s,dataID=%s" % (customType, dataID))
+        GameWorld.Log("    定制的合服副本地图列表: %s" % (customMapIDList))
+        GameWorld.Log("    今天定制的合服副本表ID列表=%s" % (todayCustomIDList))
     else:
         GameWorld.Log("    超过最大定制开服天,不定制,走常规副本状态时间!")
         
@@ -1065,11 +1486,12 @@
         #    GameWorld.DebugLog("        副本可否进入已经是该值: dataMapID=%s,updCanEnter=%s,canEnterKey=%s" % (dataMapID, updCanEnter, canEnterKey))            
             
         fbFuncStateKey = ShareDefine.Def_Notify_WorldKey_FBFuncState % dataMapID
-        if gameWorld.GetDictByKey(fbFuncStateKey) != updStateValue:
+        beforeState = gameWorld.GetDictByKey(fbFuncStateKey)
+        if beforeState != updStateValue:
             GameWorld.SendMapServerMsgEx(fbFuncStateKey, updStateValue) #通知Mapserver,设置字典
             gameWorld.SetDict(fbFuncStateKey, updStateValue) #更新字典值
             GameWorld.Log("副本状态变更: dataMapID=%s,updStateValue=%s,fbFuncStateKey=%s" % (dataMapID, updStateValue, fbFuncStateKey))
-            __DoLogic_GameServer_ActionState(fbFuncStateKey, updStateValue)
+            __DoLogic_GameServer_ActionState(fbFuncStateKey, updStateValue, beforeState)
         #else:
         #    GameWorld.DebugLog("        副本状态已经是该值: dataMapID=%s,updStateValue=%s,fbFuncStateKey=%s" % (dataMapID, updStateValue, fbFuncStateKey))
             
@@ -1215,12 +1637,13 @@
 ##处理GameServer活动状态
 # @param dictName 字典名
 # @param isOpen 是否开启
+# @param beforeState 状态变更前的值,部分判断处理
 # @return 返回值无意义
 # @remarks 
-def __DoLogic_GameServer_ActionState(dictName, isOpen):
+def __DoLogic_GameServer_ActionState(dictName, isOpen, beforeState=0):
     #仙盟宴会 
-    if dictName == ShareDefine.Def_Notify_WorldKey_FBFuncState % ChConfig.Def_FBMapID_FamilyParty:
-        PlayerFamilyParty.FamilyPartyStateChange(isOpen)
+    if dictName == ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_FamilyParty:
+        PlayerFamilyParty.FamilyPartyStateChange(isOpen, beforeState)
     #仙盟联赛
     elif dictName == ShareDefine.Def_Notify_WorldKey_FBFuncState % ChConfig.Def_FBMapID_FamilyWar:
         GameWorldFamilyWar.OnFamilyWarStateChange(isOpen)
@@ -1236,6 +1659,13 @@
     #跨服PK
     elif dictName == ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_CrossReamPK:
         CrossRealmPK.OnCrossRealmPKDailyActionStateChange(isOpen)
+    #仙盟BOSS
+    elif dictName in [ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_FamilyBoss1]:
+        PlayerFamilyBoss.OnAllFamilyBossStateChange(isOpen)
+    #骑宠BOSS
+    elif dictName in [ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_HorsePetBoss]:
+        PlayerHorsePetBoss.OnHorsePetBossStateChange(isOpen)
+    
     return
 
 #-------------------------------------------------------------------------------

--
Gitblit v1.8.0