From cc1dc60daab5a6a9c2f1aa23c10736af2227d521 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 04 三月 2021 14:05:52 +0800
Subject: [PATCH] 8650 【主干】【BT2】活动规则优化(多活动支持的改为单表模式,增加活动分组编号字段区分不同的活动编号;常规活动改为不受合服影响,合服活动独立出来;累计充值活动、集字活动适配为新模式);

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py             |  743 ++++++++++++++++++++++--------------
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                     |  141 ------
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py                   |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                |  105 -----
 ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py                                          |    2 
 PySysDB/PySysDBPY.h                                                                                 |   39 -
 PySysDB/PySysDBG.h                                                                                  |   51 --
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActCollectWords.py |   75 +--
 8 files changed, 490 insertions(+), 668 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index 3261164..72573a5 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -456,24 +456,9 @@
 struct tagActCollectWords
 {
 	DWORD		_CfgID;	//配置ID
-	char		ActMark;	//活动组标记
 	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
 	list		ServerGroupIDList;	//服务器ID列表
-	char		StartDate;	//开启日期
-	char		EndDate;	//结束日期
-	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
-	dict		NotifyInfoEnd;	//全服提示信息 - 相对结束时间
-	list		NotifyInfoLoop;	//全服提示信息 - 循环广播[间隔分钟, 广播key]
-};
-
-//集字活动时间表2
-
-struct tagActCollectWords2
-{
-	DWORD		_CfgID;	//配置ID
-	char		ActMark;	//活动组标记
-	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
-	list		ServerGroupIDList;	//服务器ID列表
+	BYTE		ActNum;	//活动分组编号, 活动类型 * 10 + 不同界面编号
 	char		StartDate;	//开启日期
 	char		EndDate;	//结束日期
 	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
@@ -625,41 +610,9 @@
 struct tagActTotalRecharge
 {
 	DWORD		_CfgID;	//配置ID
-	char		ActMark;	//活动组标记
 	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
 	list		ServerGroupIDList;	//服务器ID列表
-	char		StartDate;	//开启日期
-	char		EndDate;	//结束日期
-	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
-	dict		NotifyInfoEnd;	//全服提示信息 - 相对结束时间
-	list		NotifyInfoLoop;	//全服提示信息 - 循环广播[间隔分钟, 广播key]
-	BYTE		IsDayReset;	//是否每天重置
-};
-
-//累计充值活动表2
-
-struct tagActTotalRecharge2
-{
-	DWORD		_CfgID;	//配置ID
-	char		ActMark;	//活动组标记
-	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
-	list		ServerGroupIDList;	//服务器ID列表
-	char		StartDate;	//开启日期
-	char		EndDate;	//结束日期
-	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
-	dict		NotifyInfoEnd;	//全服提示信息 - 相对结束时间
-	list		NotifyInfoLoop;	//全服提示信息 - 循环广播[间隔分钟, 广播key]
-	BYTE		IsDayReset;	//是否每天重置
-};
-
-//累计充值活动表3 - 节日充值
-
-struct tagActTotalRecharge3
-{
-	DWORD		_CfgID;	//配置ID
-	char		ActMark;	//活动组标记
-	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
-	list		ServerGroupIDList;	//服务器ID列表
+	BYTE		ActNum;	//活动分组编号, 活动类型 * 10 + 不同界面编号
 	char		StartDate;	//开启日期
 	char		EndDate;	//结束日期
 	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 5d66d89..10f62a8 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1418,21 +1418,6 @@
 	list		DropItemRateListBoss;	//Boss掉落饼图概率
 };
 
-//集字活动时间表2
-
-struct tagActCollectWords2
-{
-	DWORD		_CfgID;	//配置ID
-	char		StartDate;	//开启日期
-	char		EndDate;	//结束日期
-	WORD		LVLimit;	//限制等级
-	BYTE		LastDayOnlyExchange;	//最后一天是否仅兑换
-	WORD		TemplateID;	//兑换模板编号
-	WORD		DropDiffLVLimit;	//掉落等级差值限制
-	list		DropItemRateList;	//小怪掉落饼图概率
-	list		DropItemRateListBoss;	//Boss掉落饼图概率
-};
-
 //集字活动兑换模板表
 
 struct tagCollectWordsExchange
@@ -1610,30 +1595,6 @@
 	WORD		CTGID;	//充值表充值ID
 	DWORD		GoldPrize;		//返利仙玉数
 	BYTE		PrizeCountLimit;	//最大赠送次数
-};
-
-//累计充值活动表3 - 节日充值
-
-struct tagActTotalRecharge3
-{
-	DWORD		_CfgID;	//配置ID
-	char		StartDate;	//开启日期
-	char		EndDate;	//结束日期
-	WORD		LVLimit;	//限制等级
-	BYTE		IsDayReset;	//是否每天重置
-	list		TemplateIDList;	//模板ID列表
-};
-
-//累计充值活动表2
-
-struct tagActTotalRecharge2
-{
-	DWORD		_CfgID;	//配置ID
-	char		StartDate;	//开启日期
-	char		EndDate;	//结束日期
-	WORD		LVLimit;	//限制等级
-	BYTE		IsDayReset;	//是否每天重置
-	list		TemplateIDList;	//模板ID列表
 };
 
 //累计充值活动表
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
index ef72280..5224cac 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -369,7 +369,7 @@
 Def_WorldKey_BossIsAlive = 'BossIsAlive_%s'                  #boss是否活着
 Def_WorldKey_IsGameWorldInit = 'IsGameWorldInit'             #GameWold是否初始化完成
 Def_WorldKey_BossIsGeTui = "BossGeTui%s"                     #当前复活通知
-Def_WorldKey_OperationActionState = "OperationActState_%s"   #运营活动状态,参数为运营活动名
+Def_WorldKey_OperationActionState = "State_%s"               #运营活动状态,参数为(运营活动名)
 Def_WorldKey_BossRebornNeedPoint = "BossRebornNeedPoint"     #boss复活需要总点数
 Def_WorldKey_CrossBossIsAlive = 'CrossBossIsAlive_%s_%s'     #跨服boss是否活着,参数(zoneID, bossID)
 Def_WorldKey_GameWorldInitOK = 'GameWorldInitOK'             #GameWold是否初始化完成OK
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
index 087a71b..efd3f40 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -116,16 +116,40 @@
         # 如果是重读的,则在内层已经同步了,此处不重复同步
         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 GetOperationActNum(actName, ipyData=None):
+    ''' 获取运营活动分组编号
+        加入了分组编号概念,但由于有些活动配表还是旧规则配置,为了做规则兼容旧配表,减少配置表改动及代码改动这里做下自适应分配默认分组编号
+        活动类型定义:
+        1-默认(仅可配置开服天、日期、周循环W开头+数字,优先级 开服天 > 日期 > 周x)
+                                        非开服配置的开服前X天不开,不受合服影响,功能配置表可配置前X天后交叉可开,每日重置的活动前X天后默认可开
+        2-合服(仅可配置Mix开头+数字,如Mix1代表合服第1天,以此类推)
+        3-节日(仅可配置日期,不受开服、合服影响)
+        
+        活动分组编号 = 活动类型 * 10 + 不同界面编号
+    '''
+    if ipyData and hasattr(ipyData, "ActNum"):
+        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 __GetOperationActionInfo(isRefreshState=True):
     # @return: isReload, OperationActionInfo
@@ -150,8 +174,9 @@
     startDateInCustomCanOpenList = IpyGameDataPY.GetFuncEvalCfg("OperationAction", 2) # 开始天在定制天内在定制天结束后可继续开启的活动列表
     customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1) # 定制运营活动最大开服天
     maxCustomServerDayMix = IpyGameDataPY.GetFuncCfg("MixServer", 1) # 定制运营活动最大合服天
-    operationActionDict = {}
+    operationTodayActionDict = {}
     mapServerOperationActionDict = {}
+    platform = GameWorld.GetPlatform()
     serverGroupID = GameWorld.GetServerGroupID()
     ipyDataMgr = IpyGameDataPY.IPY_Data()
     curWeekday = curDateTime.weekday() + 1 # 今天星期几, 1代表星期1
@@ -162,51 +187,103 @@
     
     for actName in ShareDefine.OperationActionNameList:
         
+        if actName not in mapServerOperationActionDict:
+            mapServerOperationActionDict[actName] = {}
+            
         # 取出本活动所属本服ID的所有配置
-        GameWorld.Log("加载运营活动: actName=%s" % (actName))
-        curServerActIpyDataList = __GetOperationActionServerIpyDataList(ipyDataMgr, serverGroupID, actName)
+        GameWorld.Log("加载运营活动: actName=%s,platform=%s,serverGroupID=%s" % (actName, platform, serverGroupID))
+        curServerActIpyDataList = __GetOperationActionServerIpyDataList(ipyDataMgr, platform, serverGroupID, actName)
         GameWorld.Log("    可处理条数=%s" % (len(curServerActIpyDataList)))
-        disableWeekIpyDataInfo, customOpenServerDayState, customMixServerDayState = __GetOperationActionDisableWeekIpyDataInfo(actName, curDateTime, curServerActIpyDataList)
-        GameWorld.Log("    是否有配开服天活动=%s, 是否有配合服天活动=%s" % (customOpenServerDayState, customMixServerDayState))
-        needStartList = [] # [startDateTime, ...]
-        needEndList = [] # [endDateTime, ...]
-        needNotifyDict = {} # {notifyDateTime:[notifyKey, [参数]], ...}
-        activityIpyData = None # 活动中的的配置,取需要处理的配置中开始时间最晚的,反之开关时间头尾相连的时候无法开启后面的活动
-        # 注意:每个活动配置会有多个活动时间点,但是有且只能生效一条活动配置,换句话说就是每个活动配置时间不允许交叉
+        actNumDisableWeekIpyDataInfo = __GetOperationActionDisableWeekIpyDataInfo(actName, curDateTime, curServerActIpyDataList)
+        
         for ipyData in curServerActIpyDataList:
             
+            platformList = [] if not hasattr(ipyData, "PlatformList") else ipyData.GetPlatformList()
             serverGroupIDList = [] if not hasattr(ipyData, "ServerGroupIDList") else ipyData.GetServerGroupIDList()
             serverGroupIDListExcept = [] if not hasattr(ipyData, "ServerGroupIDListExcept") else ipyData.GetServerGroupIDListExcept()
             cfgID = ipyData.GetCfgID()
             startDateStr = ipyData.GetStartDate()
             endDateStr = ipyData.GetEndDate()
-            GameWorld.Log("    cfgID=%s,serverGroupIDList=%s,Except=%s,startDateStr=%s,endDateStr=%s,openServerDay=%s,isMixServer=%s,mixServerDay=%s,maxCustomServerDayMix=%s,curDateTime=%s" 
-                          % (cfgID, serverGroupIDList, serverGroupIDListExcept, startDateStr, endDateStr, openServerDay, isMixServer, mixServerDay, maxCustomServerDayMix, curDateTime))
-            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
+            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))
+            
+            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)
-            # 活动优先级为   开服天=合服天>运营日期>运营周天
-            # 按开服天开的
-            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))
+                
+            # 开服常规:  开服天 > 日期 > 周x   (不受合服天影响,合服活动新增一套独立的活动,还是走运营活动配置)
+            if actType == ShareDefine.ActType_OpenComm:
+                actByWeek = (startDateStr.startswith("W") and endDateStr.startswith("W")) # 按周x开
+                actByDate = (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 actByWeek:
+                        startWeekday = int(startDateStr[1:])
+                        endWeekday = int(endDateStr[1:])
+                        startWeekDate = curDateTime + datetime.timedelta(days=(startWeekday - curWeekday))
+                        endWeekDate = curDateTime + datetime.timedelta(days=(endWeekday - curWeekday))
+                        startDateStr = "%d-%d-%d" % (startWeekDate.year, startWeekDate.month, startWeekDate.day)
+                        endDateStr = "%d-%d-%d" % (endWeekDate.year, endWeekDate.month, endWeekDate.day)
+                        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
+                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))
-                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 startDateStr.startswith("Mix") and endDateStr.startswith("Mix"):
+                
+            # 合服活动: 只受合服天影响
+            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
@@ -215,47 +292,22 @@
                 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))
+                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 actType == ShareDefine.ActType_Feast:
+                if startDateStr.count("-") != 2 or endDateStr.count("-") != 2:
+                    GameWorld.Log("        节日活动,配置非日期,不处理! cfgID=%s,startDateStr=%s,endDateStr=%s" % (cfgID, startDateStr, endDateStr))
+                    continue
+                
             else:
-                if startDateStr.startswith("W") and endDateStr.startswith("W"):
-                    startWeekday = int(startDateStr[1:])
-                    endWeekday = int(endDateStr[1:])
-                    startWeekDate = curDateTime + datetime.timedelta(days=(startWeekday-curWeekday))
-                    endWeekDate = curDateTime + datetime.timedelta(days=(endWeekday-curWeekday))
-                    startDateStr = "%d-%d-%d" % (startWeekDate.year, startWeekDate.month, startWeekDate.day)
-                    endDateStr = "%d-%d-%d" % (endWeekDate.year, endWeekDate.month, endWeekDate.day)
-                    GameWorld.Log("        星期X转化为日期: %s ~ %s" % (startDateStr, endDateStr))
-                    
-                if actName not in ShareDefine.FeastOperationActionNameList:
-                    if customOpenServerDayState and openServerDay <= customMaxServerDay:
-                        GameWorld.Log("        按日期/周开的在开服定制限制天内,不处理! cfgID=%s,%s ~ %s,openServerDay=%s" % (cfgID, startDateStr, endDateStr, openServerDay))
-                        continue
-                    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 customOpenServerDayState and curServerOpenDateTime <= curStartDateTime <= customMaxServerDateTime:
-                        if actName not in startDateInCustomCanOpenList:
-                            GameWorld.Log("        按日期/周开的开始日期在开服定制限制天内,不处理! cfgID=%s,curServerOpenDateTime=%s<=curStartDateTime=%s<=customMaxServerDateTime=%s" % (cfgID, curServerOpenDateTime, curStartDateTime, customMaxServerDateTime))
-                            continue
-                    
-                    if isMixServer:
-                        if customMixServerDayState and mixServerDay <= maxCustomServerDayMix:
-                            GameWorld.Log("        按日期/周开的在合服定制限制天内,不处理! cfgID=%s,%s ~ %s,mixServerDay=%s" % (cfgID, startDateStr, endDateStr, mixServerDay))
-                            continue
-                        mixStartServerDateTime = curDateTime + datetime.timedelta(days=(1-mixServerDay)) # 合服第一天的日期
-                        customMaxServerDateTime = curDateTime + datetime.timedelta(days=(maxCustomServerDayMix-mixServerDay))
-                        curStartDateTime = datetime.datetime.strptime("%s %02d:%02d:%02d" % (startDateStr, customMaxServerDateTime.hour, customMaxServerDateTime.minute, 
-                                                                                             customMaxServerDateTime.second), ChConfig.TYPE_Time_Format)
-                        if customMixServerDayState and mixStartServerDateTime <= curStartDateTime <= customMaxServerDateTime:
-                            if actName not in startDateInCustomCanOpenList:
-                                GameWorld.Log("        按日期/周开的开始日期在合服定制限制天内,不处理! cfgID=%s,mixStartServerDateTime=%s<=curStartDateTime=%s<=customMaxServerDateTime=%s" % (cfgID, mixStartServerDateTime, curStartDateTime, customMaxServerDateTime))
-                                continue
-                    
+                GameWorld.Log("        非法配置,未知活动类型,不处理! cfgID=%s,actNum=%s" % (cfgID, actNum))
+                continue
+            
             if hasattr(ipyData, "GetStartTimeList") and hasattr(ipyData, "GetEndTimeList"):
                 startHMStrList = ipyData.GetStartTimeList()
                 endHMStrList = ipyData.GetEndTimeList()
@@ -287,57 +339,68 @@
             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
+            
             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)
-                    
+                
             # 每天按时段开启的,支持多时段
-            elif startDayDate <= curDateTime <= endDayDate:
-                isEnd = (curDateTime == endDayDate)
-                if not isEnd:
-                    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)
+            else:
+                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))
             
             for dtIndex, startDateTime in enumerate(startList):
                 endDateTime = endList[dtIndex]
@@ -363,7 +426,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:
@@ -374,49 +437,48 @@
                 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]
+            else:
+                operationTodayActionDict[actName] = [ipyData, startList, endList, notifyDict]
+                
+            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 = (curDateTime - startDayDate).days
-                        actIDDateTime = startDayDate
-                        isDayRest = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()
-                        # 按时段开的默认每天重置
-                        if isDayRest or (startHMStrList and endHMStrList):
-                            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()
-                    
+                dayIndex = (curDateTime - startDayDate).days
+                actIDDateTime = startDayDate
+                isDayRest = 0 if not hasattr(ipyData, "GetIsDayReset") else ipyData.GetIsDayReset()
+                # 按时段开的默认每天重置
+                if isDayRest or (startHMStrList and endHMStrList):
+                    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))
+                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])
     
     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:
@@ -424,7 +486,7 @@
         
     return True, OperationActionInfo
 
-def __GetOperationActionServerIpyDataList(ipyDataMgr, serverGroupID, actName):
+def __GetOperationActionServerIpyDataList(ipyDataMgr, platform, serverGroupID, actName):
     ## 获取运营活动本服务器对应的配置数据列表
     
     if not hasattr(ipyDataMgr, "Get%sCount" % actName):
@@ -435,8 +497,12 @@
     actCfgCount = getattr(ipyDataMgr, "Get%sCount" % actName)()
     for cfgIndex in xrange(actCfgCount):
         ipyData = getattr(ipyDataMgr, "Get%sByIndex" % actName)(cfgIndex)            
+        platformList = [] if not hasattr(ipyData, "PlatformList") else ipyData.GetPlatformList()
         serverGroupIDList = [] if not hasattr(ipyData, "ServerGroupIDList") else ipyData.GetServerGroupIDList()
         serverGroupIDListExcept = [] if not hasattr(ipyData, "ServerGroupIDListExcept") else ipyData.GetServerGroupIDListExcept()
+        
+        if platformList and platform not in platformList:
+            continue
         
         # 排除的服务器组ID列表
         if serverGroupIDListExcept:
@@ -464,44 +530,136 @@
 
 def __GetOperationActionDisableWeekIpyDataInfo(actName, curDateTime, curServerActIpyDataList):
     ## 获取不可用的按星期X开启的配置数据信息,按星期X开启的 活动优先级小于按日期的,当有重叠时以日期的为准
-    disableWeekIpyDataInfo = {}
     curWeekday = curDateTime.weekday() + 1 # 今天星期几, 1代表星期1
-    customOpenServerDayState, customMixServerDayState = False, False # 是否有配开服天、合服天活动
-    weekIpyDataList, ymdIpyDatList = [], []
+    actNumWeekYMDIpyDataInfo = {} # {actNum:[weekIpyDataList, ymdIpyDatList], ...}
+    
     for ipyData in curServerActIpyDataList:
         startDateStr = ipyData.GetStartDate()
         endDateStr = ipyData.GetEndDate()
-        if startDateStr.isdigit() or startDateStr.startswith("Mix"):
-            # 开服天、合服天的不处理
-            if startDateStr.isdigit():
-                customOpenServerDayState = True
-            else:
-                customMixServerDayState = True                
+        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"):
             startWeekday = int(startDateStr[1:])
             endWeekday = int(endDateStr[1:])
-            startWeekDate = curDateTime + datetime.timedelta(days=(startWeekday-curWeekday))
-            endWeekDate = curDateTime + datetime.timedelta(days=(endWeekday-curWeekday))
+            startWeekDate = curDateTime + datetime.timedelta(days=(startWeekday - curWeekday))
+            endWeekDate = curDateTime + datetime.timedelta(days=(endWeekday - curWeekday))
             weekIpyDataList.append([ipyData, startWeekDate, endWeekDate])
         # 按日期的
-        else:
+        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])
             
-    for ipyData, startWeekDate, endWeekDate in weekIpyDataList:
-        cfgID = ipyData.GetCfgID()
-        for ymdIpyData, ymdStartDate, ymdEndDate in ymdIpyDatList:
-            if ymdStartDate <= startWeekDate <= ymdEndDate or ymdStartDate <= endWeekDate <= ymdEndDate \
-                or (actName in ShareDefine.FeastOperationActionNameList and ymdStartDate <= curDateTime <= ymdEndDate):
-                ymdCfgID = ymdIpyData.GetCfgID()
-                disableWeekIpyDataInfo[cfgID] = [startWeekDate, endWeekDate, ymdCfgID, ymdStartDate, ymdEndDate]
-                
-    return disableWeekIpyDataInfo, customOpenServerDayState, customMixServerDayState
+        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
+
+def TransferOperationActDBKeyValue():
+    '''  服务器启动时调用
+            支持多活动的数据转移,旧版本db活动数据转移到新版本,分两种情况
+    1. 原已支持多活动的:  手动根据原编号规则进行指定转移,这个维护一次后代码可删除
+    2. 原不支持多活动的,自动根据原活动类型进行适配转移即可,由于合服相关的独立出来了,所以只需要处理常规的及节日类型
+                           这个代码可以一直放着,后续增加支持多活动类型的配置到  MultiActNumOperationActNameList 即可
+                           
+           注:不支持多活动的,暂还是用旧的key记录数据
+    '''
+    GameWorld.Log("=== 转移运营活动旧版本数据到新版本 ===")
+    
+    # 1. 原已支持的  - 维护后过一次后可删除或注释掉,目前只有累计充值、集字,线上版本分支 gt_1.100.4
+    transferDict = {
+                    ShareDefine.OperationActionName_TotalRecharge:[
+                            # 原常规每日累充  转移 到 10
+                            [PlayerDBGSEvent.Def_OperationActID % ShareDefine.OperationActionName_TotalRecharge,
+                             PlayerDBGSEvent.Def_OperationActID % ShareDefine.OperationActionName_TotalRecharge + "_%s" % 10,
+                             ],
+                            [PlayerDBGSEvent.Def_OActWorldLV % ShareDefine.OperationActionName_TotalRecharge,
+                             PlayerDBGSEvent.Def_OActWorldLV % ShareDefine.OperationActionName_TotalRecharge + "_%s" % 10,
+                             ],
+                                                                                          
+                            # 原常规多日累充2  转移 到 11
+                            [PlayerDBGSEvent.Def_OperationActID % (ShareDefine.OperationActionName_TotalRecharge + "2"),
+                             PlayerDBGSEvent.Def_OperationActID % ShareDefine.OperationActionName_TotalRecharge + "_%s" % 11,
+                             ],
+                            [PlayerDBGSEvent.Def_OActWorldLV % (ShareDefine.OperationActionName_TotalRecharge + "2"),
+                             PlayerDBGSEvent.Def_OActWorldLV % ShareDefine.OperationActionName_TotalRecharge + "_%s" % 11,
+                             ],
+                                                                                                  
+                            # 原节日多日累充3  转移 到 31
+                            [PlayerDBGSEvent.Def_OperationActID % (ShareDefine.OperationActionName_TotalRecharge + "3"),
+                             PlayerDBGSEvent.Def_OperationActID % ShareDefine.OperationActionName_TotalRecharge + "_%s" % 31,
+                             ],
+                            [PlayerDBGSEvent.Def_OActWorldLV % (ShareDefine.OperationActionName_TotalRecharge + "3"),
+                             PlayerDBGSEvent.Def_OActWorldLV % ShareDefine.OperationActionName_TotalRecharge + "_%s" % 31,
+                             ],
+                                                                   ],
+                    ShareDefine.OperationActionName_CollectWords:[
+                            # 只配置了常规日期的,可不处理
+                                                                  ],
+                    }
+    for actName, transferKeyList in transferDict.items():
+        for oldKey, newKey in transferKeyList:
+            value = PlayerDBGSEvent.GetDBGSTrig_ByKey(oldKey)
+            if not value:
+                continue
+            GameWorld.Log("    转移旧运营活动dbKey值到新key: actName=%s,oldKey=%s,newKey=%s,value=%s" % (actName, oldKey, newKey, value))
+            PlayerDBGSEvent.SetDBGSTrig_ByKey(newKey, value)
+            PlayerDBGSEvent.DelDBGSTrig_ByKey(oldKey)
+            
+    # 2. 新增支持的 - 可当做常规代码一直留着
+    for actName in ShareDefine.MultiActNumOperationActNameList:
+        if actName in transferDict:
+            # 特殊处理转化的活动不进行常规处理
+            continue
+        
+        actIDKeyOld = PlayerDBGSEvent.Def_OperationActID % actName
+        worldLVKeyOld = PlayerDBGSEvent.Def_OActWorldLV % actName
+        
+        actNum = GetOperationActNum(actName)
+        actIDKeyNew = actIDKeyOld + "_%s" % actNum
+        worldLVKeyNew = worldLVKeyOld + "_%s" % actNum
+        
+        dbActID = PlayerDBGSEvent.GetDBGSTrig_ByKey(actIDKeyOld)
+        dbWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(worldLVKeyOld)
+        if not dbActID:
+            continue
+        
+        GameWorld.Log("    转移旧运营活动dbKey值到新key: actName=%s" % actName)
+        PlayerDBGSEvent.SetDBGSTrig_ByKey(actIDKeyNew, dbActID)
+        PlayerDBGSEvent.DelDBGSTrig_ByKey(actIDKeyOld)
+        GameWorld.Log("        actIDKeyOld=%s,actIDKeyNew=%s,dbActID=%s" % (actIDKeyOld, actIDKeyNew, dbActID))
+        
+        if dbWorldLV:
+            PlayerDBGSEvent.SetDBGSTrig_ByKey(worldLVKeyNew, dbWorldLV)
+            PlayerDBGSEvent.DelDBGSTrig_ByKey(worldLVKeyOld)
+            GameWorld.Log("        worldLVKeyOld=%s,worldLVKeyNew=%s,dbWorldLV=%s" % (worldLVKeyOld, worldLVKeyNew, dbWorldLV))
+            
+    GameWorld.Log("===================================")
+    return
 
 def Dispose_OperationActionState(reloadRefresh=False):
     # 运营活动状态处理, 每天0点会强制同步当天的运营活动详情到地图服务器
@@ -513,7 +671,7 @@
     
     isReload, OperationActionInfo = __GetOperationActionInfo(False) # 这里必须传False
     isReload = isReload or reloadRefresh
-    operationActionDict = OperationActionInfo[OperationAction_TodayInfo]
+    operationTodayActionDict = OperationActionInfo[OperationAction_TodayInfo]
     mapServerInfoDict = OperationActionInfo[OperationAction_MapServerInfo]
     
     gameWorld = GameWorld.GetGameWorld()
@@ -523,147 +681,148 @@
     curDateTime = datetime.datetime.strptime("%d-%d-%d %d:%d:00" % (curDateTime.year, curDateTime.month, curDateTime.day,
                                                                     curDateTime.hour, curDateTime.minute), ChConfig.TYPE_Time_Format)
     
-    startDateInCustomCanOpenList = IpyGameDataPY.GetFuncEvalCfg("OperationAction", 2) # 开始天在定制天内在定制天结束后可继续开启的活动列表
-    
     for actName in ShareDefine.OperationActionNameList:
         
-        state = 0 # 默认关闭
-        ipyData = None
+        if actName not in mapServerInfoDict:
+            continue
         
-        if actName in operationActionDict:
+        if actName in ShareDefine.MultiActNumOperationActNameList:
+            curActMapInfoDictList = mapServerInfoDict[actName].values()
+        else:
+            curActMapInfoDictList = [mapServerInfoDict[actName]]
             
-            #startList = [] # [startDateTime, ...]
-            #endList = [] # [endDateTime, ...]
-            #notifyDict = {} # {notifyDateTime:[notifyKey, [参数]], ...}
-            #ipyData 可能为 None
-            ipyData, startList, endList, notifyDict = operationActionDict[actName]
+        for sendMapServerMsgDict in curActMapInfoDictList:
             
-            if actName in startDateInCustomCanOpenList:
-                # 由于某些活动的开始天允许和前定制X天有交叉的情况出现(实际不开,会等定制结束后才接下去开)
-                # 所以会有时间交叉的情况出现,这种活动goon单独判断
-                # 为防止动到其他活动,允许交叉的活动另外处理,理论上可以统一逻辑,为保险起见分开处理
-                
-                # 精确匹配开启
-                if curDateTime in startList:
-                    state = startList.index(curDateTime) + 1 # 也是代表第几个时间段
-                # 精确匹配关闭
-                elif curDateTime in endList:
-                    state = 0
-                    
-                # goon 状态
-                for dIndex, startDateTime in enumerate(startList):
-                    endDateTime = endList[dIndex]
-                    if startDateTime < curDateTime < endDateTime:
-                        state = dIndex + 1
-                        break
-                    
-            else:
-                # 精确匹配开启
-                if curDateTime in startList:
-                    state = startList.index(curDateTime) + 1 # 也是代表第几个时间段
-                # 精确匹配关闭
-                elif curDateTime in endList:
-                    state = 0
-                # goon 状态
+            state = 0 # 默认关闭
+            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) == 4:
+                    #startList = [] # [startDateTime, ...]
+                    #endList = [] # [endDateTime, ...]
+                    #notifyDict = {} # {notifyDateTime:[notifyKey, [参数]], ...}
+                    #ipyData 可能为 None
+                    ipyData, startList, endList, notifyDict = todayActInfoList
+                    
+                    # 状态
                     for dIndex, startDateTime in enumerate(startList):
                         endDateTime = endList[dIndex]
-                        if startDateTime < curDateTime < endDateTime:
-                            state = dIndex + 1
+                        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
+            if actName in ShareDefine.MultiActNumOperationActNameList:         
+                dictName += "_%s" % actNum
+            preState = gameWorld.GetDictByKey(dictName)
+            if not isReload and preState == state:
+                #已经是这个状态了
+                continue
+            GameWorld.Log("运营活动变更: actName=%s,actNum=%s,preState=%s,state=%s,dictName=%s" % (actName, actNum, preState, state, dictName))
+            #更新字典值
+            gameWorld.SetDict(dictName, state)
+            
+            dbOperationActIDKey = PlayerDBGSEvent.Def_OperationActID % actName
+            dbOperationActWorldLVKey = PlayerDBGSEvent.Def_OActWorldLV % actName
+            if actName in ShareDefine.MultiActNumOperationActNameList:         
+                dbOperationActIDKey += "_%s" % actNum
+                dbOperationActWorldLVKey += "_%s" % actNum
+                
+            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 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)
+            else:
+                GameWorld.Log("    dbActID不变: dbActID=%s,curActID=%s" % (dbActID, curActID))
+                
+            if state 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)
                     
-            # 全服广播提示信息
-            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:
-            #已经是这个状态了
-            continue
-        GameWorld.Log("运营活动变更: actName=%s,preState=%s,state=%s,dictName=%s" % (actName, preState, state, dictName))
-        #更新字典值
-        gameWorld.SetDict(dictName, state)
-        sendMapServerMsgDict = mapServerInfoDict.get(actName, {})
-        
-        dbOperationActIDKey = PlayerDBGSEvent.Def_OperationActID % actName
-        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)
+            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()
             
-            if curActID:
-                if actName in ShareDefine.NeedWorldLVOperationActNameList:
-                    #记录开启时世界等级
-                    worldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
-                    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_OActWorldLV % actName, worldLV)
-                    GameWorld.Log("    记录活动开启时世界等级: worldLV=%s" % (worldLV))
+            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)
                     
-                #此处为活动开启时
-                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)
-        else:
-            GameWorld.Log("    dbActID不变: dbActID=%s,curActID=%s" % (dbActID, curActID))
+            #通知Mapserver,设置字典
+            #GameWorld.SendMapServerMsgEx(dictName, state) # 运营活动不单独通知活动状态,需与活动信息整合后一起通知
             
-        if actName in ShareDefine.NeedWorldLVOperationActNameList:
-            actWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_OActWorldLV % actName)
-            sendMapServerMsgDict[ShareDefine.ActKey_WorldLV] = actWorldLV
-            GameWorld.Log("    活动世界等级: actWorldLV=%s" % (actWorldLV))
+            sendMapServerMsgDict[ShareDefine.ActKey_State] = state
+            GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_OperationActionInfo % actName, sendMapServerMsgDict)
             
-        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("    sendMapServerMsgDict: %s" % (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):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
index 4ad6cf0..45f7873 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
@@ -1205,6 +1205,8 @@
     GameWorld.GetGameWorld().SetDict(ChConfig.Def_WorldKey_IsGameWorldInit, int(time.time()))
     #初始化游戏时钟
     GameWorld.GetGameWorld().SetTickTypeCount(ChConfig.TYPE_Tick_Count)
+    #转移运营活动旧db记录key value 到 新记录
+    GameWorldActionControl.TransferOperationActDBKeyValue()
     #初始话开服时间、星期几
     initOpenServerTime = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_InitOpenServerTime)
     openServerWeekday = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_OpenServerWeekday)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index 4d09b1f..c1590b8 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -384,21 +384,9 @@
 
                 "ActCollectWords":(
                         ("DWORD", "CfgID", 1),
-                        ("char", "ActMark", 0),
                         ("list", "PlatformList", 0),
                         ("list", "ServerGroupIDList", 0),
-                        ("char", "StartDate", 0),
-                        ("char", "EndDate", 0),
-                        ("dict", "NotifyInfoStart", 0),
-                        ("dict", "NotifyInfoEnd", 0),
-                        ("list", "NotifyInfoLoop", 0),
-                        ),
-
-                "ActCollectWords2":(
-                        ("DWORD", "CfgID", 1),
-                        ("char", "ActMark", 0),
-                        ("list", "PlatformList", 0),
-                        ("list", "ServerGroupIDList", 0),
+                        ("BYTE", "ActNum", 0),
                         ("char", "StartDate", 0),
                         ("char", "EndDate", 0),
                         ("dict", "NotifyInfoStart", 0),
@@ -519,35 +507,9 @@
 
                 "ActTotalRecharge":(
                         ("DWORD", "CfgID", 1),
-                        ("char", "ActMark", 0),
                         ("list", "PlatformList", 0),
                         ("list", "ServerGroupIDList", 0),
-                        ("char", "StartDate", 0),
-                        ("char", "EndDate", 0),
-                        ("dict", "NotifyInfoStart", 0),
-                        ("dict", "NotifyInfoEnd", 0),
-                        ("list", "NotifyInfoLoop", 0),
-                        ("BYTE", "IsDayReset", 0),
-                        ),
-
-                "ActTotalRecharge2":(
-                        ("DWORD", "CfgID", 1),
-                        ("char", "ActMark", 0),
-                        ("list", "PlatformList", 0),
-                        ("list", "ServerGroupIDList", 0),
-                        ("char", "StartDate", 0),
-                        ("char", "EndDate", 0),
-                        ("dict", "NotifyInfoStart", 0),
-                        ("dict", "NotifyInfoEnd", 0),
-                        ("list", "NotifyInfoLoop", 0),
-                        ("BYTE", "IsDayReset", 0),
-                        ),
-
-                "ActTotalRecharge3":(
-                        ("DWORD", "CfgID", 1),
-                        ("char", "ActMark", 0),
-                        ("list", "PlatformList", 0),
-                        ("list", "ServerGroupIDList", 0),
+                        ("BYTE", "ActNum", 0),
                         ("char", "StartDate", 0),
                         ("char", "EndDate", 0),
                         ("dict", "NotifyInfoStart", 0),
@@ -1461,9 +1423,9 @@
     
     def __init__(self):
         self.CfgID = 0
-        self.ActMark = ""
         self.PlatformList = []
         self.ServerGroupIDList = []
+        self.ActNum = 0
         self.StartDate = ""
         self.EndDate = ""
         self.NotifyInfoStart = {}
@@ -1472,34 +1434,9 @@
         return
         
     def GetCfgID(self): return self.CfgID # 配置ID
-    def GetActMark(self): return self.ActMark # 活动组标记
     def GetPlatformList(self): return self.PlatformList # 活动平台列表["平台A", "平台A", ...],配[]代表所有
     def GetServerGroupIDList(self): return self.ServerGroupIDList # 服务器ID列表
-    def GetStartDate(self): return self.StartDate # 开启日期
-    def GetEndDate(self): return self.EndDate # 结束日期
-    def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
-    def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
-    def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
-
-# 集字活动时间表2
-class IPY_ActCollectWords2():
-    
-    def __init__(self):
-        self.CfgID = 0
-        self.ActMark = ""
-        self.PlatformList = []
-        self.ServerGroupIDList = []
-        self.StartDate = ""
-        self.EndDate = ""
-        self.NotifyInfoStart = {}
-        self.NotifyInfoEnd = {}
-        self.NotifyInfoLoop = []
-        return
-        
-    def GetCfgID(self): return self.CfgID # 配置ID
-    def GetActMark(self): return self.ActMark # 活动组标记
-    def GetPlatformList(self): return self.PlatformList # 活动平台列表["平台A", "平台A", ...],配[]代表所有
-    def GetServerGroupIDList(self): return self.ServerGroupIDList # 服务器ID列表
+    def GetActNum(self): return self.ActNum # 活动分组编号, 活动类型 * 10 + 不同界面编号
     def GetStartDate(self): return self.StartDate # 开启日期
     def GetEndDate(self): return self.EndDate # 结束日期
     def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
@@ -1742,9 +1679,9 @@
     
     def __init__(self):
         self.CfgID = 0
-        self.ActMark = ""
         self.PlatformList = []
         self.ServerGroupIDList = []
+        self.ActNum = 0
         self.StartDate = ""
         self.EndDate = ""
         self.NotifyInfoStart = {}
@@ -1754,63 +1691,9 @@
         return
         
     def GetCfgID(self): return self.CfgID # 配置ID
-    def GetActMark(self): return self.ActMark # 活动组标记
     def GetPlatformList(self): return self.PlatformList # 活动平台列表["平台A", "平台A", ...],配[]代表所有
     def GetServerGroupIDList(self): return self.ServerGroupIDList # 服务器ID列表
-    def GetStartDate(self): return self.StartDate # 开启日期
-    def GetEndDate(self): return self.EndDate # 结束日期
-    def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
-    def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
-    def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
-    def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
-
-# 累计充值活动表2
-class IPY_ActTotalRecharge2():
-    
-    def __init__(self):
-        self.CfgID = 0
-        self.ActMark = ""
-        self.PlatformList = []
-        self.ServerGroupIDList = []
-        self.StartDate = ""
-        self.EndDate = ""
-        self.NotifyInfoStart = {}
-        self.NotifyInfoEnd = {}
-        self.NotifyInfoLoop = []
-        self.IsDayReset = 0
-        return
-        
-    def GetCfgID(self): return self.CfgID # 配置ID
-    def GetActMark(self): return self.ActMark # 活动组标记
-    def GetPlatformList(self): return self.PlatformList # 活动平台列表["平台A", "平台A", ...],配[]代表所有
-    def GetServerGroupIDList(self): return self.ServerGroupIDList # 服务器ID列表
-    def GetStartDate(self): return self.StartDate # 开启日期
-    def GetEndDate(self): return self.EndDate # 结束日期
-    def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
-    def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
-    def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
-    def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
-
-# 累计充值活动表3-节日充值
-class IPY_ActTotalRecharge3():
-    
-    def __init__(self):
-        self.CfgID = 0
-        self.ActMark = ""
-        self.PlatformList = []
-        self.ServerGroupIDList = []
-        self.StartDate = ""
-        self.EndDate = ""
-        self.NotifyInfoStart = {}
-        self.NotifyInfoEnd = {}
-        self.NotifyInfoLoop = []
-        self.IsDayReset = 0
-        return
-        
-    def GetCfgID(self): return self.CfgID # 配置ID
-    def GetActMark(self): return self.ActMark # 活动组标记
-    def GetPlatformList(self): return self.PlatformList # 活动平台列表["平台A", "平台A", ...],配[]代表所有
-    def GetServerGroupIDList(self): return self.ServerGroupIDList # 服务器ID列表
+    def GetActNum(self): return self.ActNum # 活动分组编号, 活动类型 * 10 + 不同界面编号
     def GetStartDate(self): return self.StartDate # 开启日期
     def GetEndDate(self): return self.EndDate # 结束日期
     def GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
@@ -2257,8 +2140,6 @@
         self.ipyActCostRebateLen = len(self.ipyActCostRebateCache)
         self.ipyActCollectWordsCache = self.__LoadFileData("ActCollectWords", IPY_ActCollectWords)
         self.ipyActCollectWordsLen = len(self.ipyActCollectWordsCache)
-        self.ipyActCollectWords2Cache = self.__LoadFileData("ActCollectWords2", IPY_ActCollectWords2)
-        self.ipyActCollectWords2Len = len(self.ipyActCollectWords2Cache)
         self.ipyActBossRebornCache = self.__LoadFileData("ActBossReborn", IPY_ActBossReborn)
         self.ipyActBossRebornLen = len(self.ipyActBossRebornCache)
         self.ipyActFairyCeremonyCache = self.__LoadFileData("ActFairyCeremony", IPY_ActFairyCeremony)
@@ -2279,10 +2160,6 @@
         self.ipyActGrowupBuyLen = len(self.ipyActGrowupBuyCache)
         self.ipyActTotalRechargeCache = self.__LoadFileData("ActTotalRecharge", IPY_ActTotalRecharge)
         self.ipyActTotalRechargeLen = len(self.ipyActTotalRechargeCache)
-        self.ipyActTotalRecharge2Cache = self.__LoadFileData("ActTotalRecharge2", IPY_ActTotalRecharge2)
-        self.ipyActTotalRecharge2Len = len(self.ipyActTotalRecharge2Cache)
-        self.ipyActTotalRecharge3Cache = self.__LoadFileData("ActTotalRecharge3", IPY_ActTotalRecharge3)
-        self.ipyActTotalRecharge3Len = len(self.ipyActTotalRecharge3Cache)
         self.ipyCrossZoneCommCache = self.__LoadFileData("CrossZoneComm", IPY_CrossZoneComm)
         self.ipyCrossZoneCommLen = len(self.ipyCrossZoneCommCache)
         self.ipyCrossZonePKCache = self.__LoadFileData("CrossZonePK", IPY_CrossZonePK)
@@ -2553,8 +2430,6 @@
     def GetActCostRebateByIndex(self, index): return self.ipyActCostRebateCache[index]
     def GetActCollectWordsCount(self): return self.ipyActCollectWordsLen
     def GetActCollectWordsByIndex(self, index): return self.ipyActCollectWordsCache[index]
-    def GetActCollectWords2Count(self): return self.ipyActCollectWords2Len
-    def GetActCollectWords2ByIndex(self, index): return self.ipyActCollectWords2Cache[index]
     def GetActBossRebornCount(self): return self.ipyActBossRebornLen
     def GetActBossRebornByIndex(self, index): return self.ipyActBossRebornCache[index]
     def GetActFairyCeremonyCount(self): return self.ipyActFairyCeremonyLen
@@ -2575,10 +2450,6 @@
     def GetActGrowupBuyByIndex(self, index): return self.ipyActGrowupBuyCache[index]
     def GetActTotalRechargeCount(self): return self.ipyActTotalRechargeLen
     def GetActTotalRechargeByIndex(self, index): return self.ipyActTotalRechargeCache[index]
-    def GetActTotalRecharge2Count(self): return self.ipyActTotalRecharge2Len
-    def GetActTotalRecharge2ByIndex(self, index): return self.ipyActTotalRecharge2Cache[index]
-    def GetActTotalRecharge3Count(self): return self.ipyActTotalRecharge3Len
-    def GetActTotalRecharge3ByIndex(self, index): return self.ipyActTotalRecharge3Cache[index]
     def GetCrossZoneCommCount(self): return self.ipyCrossZoneCommLen
     def GetCrossZoneCommByIndex(self, index): return self.ipyCrossZoneCommCache[index]
     def GetCrossZonePKCount(self): return self.ipyCrossZonePKLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index af7733c..5aaa761 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1132,18 +1132,6 @@
                         ("list", "DropItemRateListBoss", 0),
                         ),
 
-                "ActCollectWords2":(
-                        ("DWORD", "CfgID", 1),
-                        ("char", "StartDate", 0),
-                        ("char", "EndDate", 0),
-                        ("WORD", "LVLimit", 0),
-                        ("BYTE", "LastDayOnlyExchange", 0),
-                        ("WORD", "TemplateID", 0),
-                        ("WORD", "DropDiffLVLimit", 0),
-                        ("list", "DropItemRateList", 0),
-                        ("list", "DropItemRateListBoss", 0),
-                        ),
-
                 "CollectWordsExchange":(
                         ("DWORD", "TemplateID", 1),
                         ("BYTE", "ExchangeNum", 0),
@@ -1273,24 +1261,6 @@
                         ("WORD", "CTGID", 0),
                         ("DWORD", "GoldPrize", 0),
                         ("BYTE", "PrizeCountLimit", 0),
-                        ),
-
-                "ActTotalRecharge3":(
-                        ("DWORD", "CfgID", 1),
-                        ("char", "StartDate", 0),
-                        ("char", "EndDate", 0),
-                        ("WORD", "LVLimit", 0),
-                        ("BYTE", "IsDayReset", 0),
-                        ("list", "TemplateIDList", 0),
-                        ),
-
-                "ActTotalRecharge2":(
-                        ("DWORD", "CfgID", 1),
-                        ("char", "StartDate", 0),
-                        ("char", "EndDate", 0),
-                        ("WORD", "LVLimit", 0),
-                        ("BYTE", "IsDayReset", 0),
-                        ("list", "TemplateIDList", 0),
                         ),
 
                 "ActTotalRecharge":(
@@ -4060,31 +4030,6 @@
     def GetDropItemRateList(self): return self.DropItemRateList # 小怪掉落饼图概率
     def GetDropItemRateListBoss(self): return self.DropItemRateListBoss # Boss掉落饼图概率
 
-# 集字活动时间表2
-class IPY_ActCollectWords2():
-    
-    def __init__(self):
-        self.CfgID = 0
-        self.StartDate = ""
-        self.EndDate = ""
-        self.LVLimit = 0
-        self.LastDayOnlyExchange = 0
-        self.TemplateID = 0
-        self.DropDiffLVLimit = 0
-        self.DropItemRateList = []
-        self.DropItemRateListBoss = []
-        return
-        
-    def GetCfgID(self): return self.CfgID # 配置ID
-    def GetStartDate(self): return self.StartDate # 开启日期
-    def GetEndDate(self): return self.EndDate # 结束日期
-    def GetLVLimit(self): return self.LVLimit # 限制等级
-    def GetLastDayOnlyExchange(self): return self.LastDayOnlyExchange # 最后一天是否仅兑换
-    def GetTemplateID(self): return self.TemplateID # 兑换模板编号
-    def GetDropDiffLVLimit(self): return self.DropDiffLVLimit # 掉落等级差值限制
-    def GetDropItemRateList(self): return self.DropItemRateList # 小怪掉落饼图概率
-    def GetDropItemRateListBoss(self): return self.DropItemRateListBoss # Boss掉落饼图概率
-
 # 集字活动兑换模板表
 class IPY_CollectWordsExchange():
     
@@ -4362,44 +4307,6 @@
     def GetCTGID(self): return self.CTGID # 充值表充值ID
     def GetGoldPrize(self): return self.GoldPrize # 返利仙玉数
     def GetPrizeCountLimit(self): return self.PrizeCountLimit # 最大赠送次数
-
-# 累计充值活动表3-节日充值
-class IPY_ActTotalRecharge3():
-    
-    def __init__(self):
-        self.CfgID = 0
-        self.StartDate = ""
-        self.EndDate = ""
-        self.LVLimit = 0
-        self.IsDayReset = 0
-        self.TemplateIDList = []
-        return
-        
-    def GetCfgID(self): return self.CfgID # 配置ID
-    def GetStartDate(self): return self.StartDate # 开启日期
-    def GetEndDate(self): return self.EndDate # 结束日期
-    def GetLVLimit(self): return self.LVLimit # 限制等级
-    def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
-    def GetTemplateIDList(self): return self.TemplateIDList # 模板ID列表
-
-# 累计充值活动表2
-class IPY_ActTotalRecharge2():
-    
-    def __init__(self):
-        self.CfgID = 0
-        self.StartDate = ""
-        self.EndDate = ""
-        self.LVLimit = 0
-        self.IsDayReset = 0
-        self.TemplateIDList = []
-        return
-        
-    def GetCfgID(self): return self.CfgID # 配置ID
-    def GetStartDate(self): return self.StartDate # 开启日期
-    def GetEndDate(self): return self.EndDate # 结束日期
-    def GetLVLimit(self): return self.LVLimit # 限制等级
-    def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
-    def GetTemplateIDList(self): return self.TemplateIDList # 模板ID列表
 
 # 累计充值活动表
 class IPY_ActTotalRecharge():
@@ -5613,8 +5520,6 @@
         self.ipyCostRebateTemplateLen = len(self.ipyCostRebateTemplateCache)
         self.ipyActCollectWordsCache = self.__LoadFileData("ActCollectWords", IPY_ActCollectWords)
         self.ipyActCollectWordsLen = len(self.ipyActCollectWordsCache)
-        self.ipyActCollectWords2Cache = self.__LoadFileData("ActCollectWords2", IPY_ActCollectWords2)
-        self.ipyActCollectWords2Len = len(self.ipyActCollectWords2Cache)
         self.ipyCollectWordsExchangeCache = self.__LoadFileData("CollectWordsExchange", IPY_CollectWordsExchange)
         self.ipyCollectWordsExchangeLen = len(self.ipyCollectWordsExchangeCache)
         self.ipyActBossRebornCache = self.__LoadFileData("ActBossReborn", IPY_ActBossReborn)
@@ -5647,10 +5552,6 @@
         self.ipyActRechargePrizeLen = len(self.ipyActRechargePrizeCache)
         self.ipyRechargePrizeTemplateCache = self.__LoadFileData("RechargePrizeTemplate", IPY_RechargePrizeTemplate)
         self.ipyRechargePrizeTemplateLen = len(self.ipyRechargePrizeTemplateCache)
-        self.ipyActTotalRecharge3Cache = self.__LoadFileData("ActTotalRecharge3", IPY_ActTotalRecharge3)
-        self.ipyActTotalRecharge3Len = len(self.ipyActTotalRecharge3Cache)
-        self.ipyActTotalRecharge2Cache = self.__LoadFileData("ActTotalRecharge2", IPY_ActTotalRecharge2)
-        self.ipyActTotalRecharge2Len = len(self.ipyActTotalRecharge2Cache)
         self.ipyActTotalRechargeCache = self.__LoadFileData("ActTotalRecharge", IPY_ActTotalRecharge)
         self.ipyActTotalRechargeLen = len(self.ipyActTotalRechargeCache)
         self.ipyTotalRechargeTemplateCache = self.__LoadFileData("TotalRechargeTemplate", IPY_TotalRechargeTemplate)
@@ -6137,8 +6038,6 @@
     def GetCostRebateTemplateByIndex(self, index): return self.ipyCostRebateTemplateCache[index]
     def GetActCollectWordsCount(self): return self.ipyActCollectWordsLen
     def GetActCollectWordsByIndex(self, index): return self.ipyActCollectWordsCache[index]
-    def GetActCollectWords2Count(self): return self.ipyActCollectWords2Len
-    def GetActCollectWords2ByIndex(self, index): return self.ipyActCollectWords2Cache[index]
     def GetCollectWordsExchangeCount(self): return self.ipyCollectWordsExchangeLen
     def GetCollectWordsExchangeByIndex(self, index): return self.ipyCollectWordsExchangeCache[index]
     def GetActBossRebornCount(self): return self.ipyActBossRebornLen
@@ -6171,10 +6070,6 @@
     def GetActRechargePrizeByIndex(self, index): return self.ipyActRechargePrizeCache[index]
     def GetRechargePrizeTemplateCount(self): return self.ipyRechargePrizeTemplateLen
     def GetRechargePrizeTemplateByIndex(self, index): return self.ipyRechargePrizeTemplateCache[index]
-    def GetActTotalRecharge3Count(self): return self.ipyActTotalRecharge3Len
-    def GetActTotalRecharge3ByIndex(self, index): return self.ipyActTotalRecharge3Cache[index]
-    def GetActTotalRecharge2Count(self): return self.ipyActTotalRecharge2Len
-    def GetActTotalRecharge2ByIndex(self, index): return self.ipyActTotalRecharge2Cache[index]
     def GetActTotalRechargeCount(self): return self.ipyActTotalRechargeLen
     def GetActTotalRechargeByIndex(self, index): return self.ipyActTotalRechargeCache[index]
     def GetTotalRechargeTemplateCount(self): return self.ipyTotalRechargeTemplateLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActCollectWords.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActCollectWords.py
index 5cad453..522eaae 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActCollectWords.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActCollectWords.py
@@ -26,19 +26,22 @@
 import ItemControler
 import IPY_GameWorld
 
-ActCollectWordsNameDict = {
-                           1:ShareDefine.OperationActionName_CollectWords,
-                           2:ShareDefine.OperationActionName_CollectWords2,
-                           }
+
+def GetActInfo(actNum):
+    if ShareDefine.OperationActionName_CollectWords not in PyGameData.g_operationActionDict:
+        return {}
+    actNumDict = PyGameData.g_operationActionDict[ShareDefine.OperationActionName_CollectWords]
+    if actNum not in actNumDict:
+        return {}
+    return actNumDict[actNum]
 
 def OnPlayerLogin(curPlayer):
     ## 玩家登录
     
-    for actNum, actName in ActCollectWordsNameDict.items():
-        
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_CollectWords, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
         isReset = __CheckPlayerCollectWordsAction(curPlayer, actNum)
         if not isReset:
-            actInfo = PyGameData.g_operationActionDict.get(actName, {})
             # 活动中同步活动信息
             if actInfo.get(ShareDefine.ActKey_State):
                 SyncCollectWordsActionInfo(curPlayer, actNum)
@@ -60,12 +63,8 @@
 def __CheckPlayerCollectWordsAction(curPlayer, actNum):
     ## 检查玩活动数据信息
     
-    if actNum not in ActCollectWordsNameDict:
-        return
-    actName = ActCollectWordsNameDict[actNum]
-    
     playerID = curPlayer.GetPlayerID()
-    actInfo = PyGameData.g_operationActionDict.get(actName, {})
+    actInfo = GetActInfo(actNum)
     actID = actInfo.get(ShareDefine.ActKey_ID, 0)
     state = actInfo.get(ShareDefine.ActKey_State, 0)
     
@@ -79,7 +78,7 @@
     templateID = 0
     cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
     if cfgID:
-        actIpyData = IpyGameDataPY.GetIpyGameData(actName, cfgID)
+        actIpyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)
         templateID = 0 if not actIpyData else actIpyData.GetTemplateID()
         exchangeList = IpyGameDataPY.GetIpyGameDataList("CollectWordsExchange", templateID)
         if not exchangeList:
@@ -104,14 +103,15 @@
     if curNPC.GetType() in [ChConfig.ntPriWoodPilePVP]:
         return
     
-    for actNum, actName in ActCollectWordsNameDict.items():
-        randList = __GetDropWordsItemRateList(curPlayer, actName, curNPC)
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_CollectWords, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        randList = __GetDropWordsItemRateList(curPlayer, curNPC, actInfo)
         if not randList:
             continue
         dropItemID = GameWorld.GetResultByRandomList(randList)
         if not dropItemID:
             continue
-        GameWorld.DebugLog("    集字活动掉落物品! actNum=%s,actName=%s,npcID=%s,dropItemID=%s" % (actNum, actName, curNPC.GetNPCID(), dropItemID))
+        GameWorld.DebugLog("    集字活动掉落物品! actNum=%s,npcID=%s,dropItemID=%s" % (actNum, curNPC.GetNPCID(), dropItemID))
         
         itemCount = 1 # 默认1个
         isAuctionItem = 0 # 非拍品
@@ -119,18 +119,14 @@
         
     return
 
-def __GetDropWordsItemRateList(curPlayer, actName, npcData):
+def __GetDropWordsItemRateList(curPlayer, npcData, actInfo):
     ## 获取掉字饼图列表
-    
-    actInfo = PyGameData.g_operationActionDict.get(actName, {})
-    if not actInfo:
-        return
     
     if not actInfo.get(ShareDefine.ActKey_State):
         return
     
     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
-    ipyData = IpyGameDataPY.GetIpyGameData(actName, cfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)
     if not ipyData:
         return
     
@@ -171,9 +167,10 @@
     ## 获取脱机掉落物品
     
     dropItemCountDict = {}
-    for actNum, actName in ActCollectWordsNameDict.items():
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_CollectWords, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
         
-        dropRateList = __GetDropWordsItemRateList(curPlayer, actName, npcData)
+        dropRateList = __GetDropWordsItemRateList(curPlayer, npcData, actInfo)
         if not dropRateList:
             continue
         
@@ -196,7 +193,7 @@
                 continue
             
             dropItemCountDict[dropItemID] = dropItemCountDict.get(dropItemID, 0) + dropCount
-            GameWorld.DebugLog("    脱机集字活动掉字: actNum=%s,actName=%s,dropItemID=%s,dropCount=%s" % (actNum, actName, dropItemID, dropCount))
+            GameWorld.DebugLog("    脱机集字活动掉字: actNum=%s,dropItemID=%s,dropCount=%s" % (actNum, dropItemID, dropCount))
             
     return dropItemCountDict
 
@@ -215,20 +212,14 @@
     
     GameWorld.DebugLog("集字活动兑换!actNum=%s,exchangeNum=%s" % (actNum, exchangeNum))
     
-    if actNum not in ActCollectWordsNameDict:
-        return
-    actName = ActCollectWordsNameDict[actNum]
-    
-    actInfo = PyGameData.g_operationActionDict.get(actName, {})
-    if not actInfo:
-        return
+    actInfo = GetActInfo(actNum)
     
     if not actInfo.get(ShareDefine.ActKey_State):
         GameWorld.DebugLog("非集字活动中,无法兑换!actNum=%s" % actNum)
         return
     
     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
-    ipyData = IpyGameDataPY.GetIpyGameData(actName, cfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)
     if not ipyData:
         return
     
@@ -301,19 +292,13 @@
 def SyncCollectWordsActionInfo(curPlayer, actNum):
     ## 同步活动信息
     
-    if actNum not in ActCollectWordsNameDict:
-        return
-    actName = ActCollectWordsNameDict[actNum]
-    
-    actInfo = PyGameData.g_operationActionDict.get(actName, {})
-    if not actInfo:
-        return
+    actInfo = GetActInfo(actNum)
     
     if not actInfo.get(ShareDefine.ActKey_State):
         return
     
     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
-    ipyData = IpyGameDataPY.GetIpyGameData(actName, cfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)
     if not ipyData:
         return
     
@@ -360,11 +345,7 @@
 def SyncCollectWordsPlayerInfo(curPlayer, actNum, exchangeNum=0):
     ## 同步活动玩家数据
     
-    if actNum not in ActCollectWordsNameDict:
-        return
-    actName = ActCollectWordsNameDict[actNum]
-    
-    actInfo = PyGameData.g_operationActionDict.get(actName, {})
+    actInfo = GetActInfo(actNum)
     if not actInfo:
         return
     
@@ -372,7 +353,7 @@
         return
     
     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
-    ipyData = IpyGameDataPY.GetIpyGameData(actName, cfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)
     if not ipyData:
         return
     

--
Gitblit v1.8.0