hxp
2021-05-06 e386ca47903c63b59e0db877423c565e295d2cb9
8721 【主干】【BT2】【后端】H.活动-合服庆典(转盘)

# Conflicts:
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
13个文件已修改
1个文件已添加
1606 ■■■■■ 已修改文件
PySysDB/PySysDBG.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTurntable.py 541 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBG.h
@@ -638,6 +638,19 @@
    BYTE        IsDayReset;    //是否每天重置
};
//转盘活动表
struct tagActTurntable
{
    DWORD        _CfgID;    //配置ID
    list        PlatformList;    //活动平台列表["平台A", "平台A", ...],配[]代表所有
    list        ServerGroupIDList;    //服务器ID列表
    BYTE        ActNum;    //活动分组编号, 活动类型 * 10 + 不同界面编号
    char        StartDate;    //开启日期
    char        EndDate;    //结束日期
    BYTE        IsDayReset;    //是否每天重置
};
//多日连充活动表
struct tagActManyDayRecharge
PySysDB/PySysDBPY.h
@@ -1679,6 +1679,26 @@
    char         NotifyKey;    //广播
};
//转盘活动表
struct tagActTurntable
{
    DWORD        _CfgID;    //配置ID
    char        StartDate;    //开启日期
    char        EndDate;    //结束日期
    WORD        LVLimit;    //限制等级
    BYTE        IsDayReset;    //是否每天重置
    BYTE        CTGTypeEffValue;    //充值有效类型值
    list        CTGPrizeList;    //累计充值奖励次数
    list        UseGoldPrizeList;    //累计消费X仙玉奖励次数
    list        LibChooseCountList;    //各道具库选择个数
    list        SuperItemLimitRule;    //终极库产出万分率|至少X次后可产出
    dict        CommItemLib;    //普通道具库 {(世界等级A,世界等级B):[[可选物品ID, 个数, 是否拍品], ...], ...}
    dict        GoodItemLib;    //极品道具库 {(世界等级A,世界等级B):[[可选物品ID, 个数, 是否拍品], ...], ...}
    dict        SuperItemLib;    //超级道具库 {(世界等级A,世界等级B):[[可选物品ID, 个数, 是否拍品], ...], ...}
    char        WorldNotifyKey;    //好物品全服广播mark,极品及超级道具默认全服广播
};
//单笔累充活动表
struct tagActSingleRecharge
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -13321,6 +13321,149 @@
#------------------------------------------------------
# AA 12 选择转盘活动物品 #tagCMActTurntableChooseItem
class  tagCMActTurntableChooseItem(Structure):
    Head = tagHead()
    ActNum = 0    #(BYTE ActNum)// 活动编号
    GoodItemNumCount = 0    #(BYTE GoodItemNumCount)
    GoodItemNumList = list()    #(vector<BYTE> GoodItemNumList)// 选择的极品物品编号列表
    SuperItemNumCount = 0    #(BYTE SuperItemNumCount)
    SuperItemNumList = list()    #(vector<BYTE> SuperItemNumList)// 选择的终极物品编号列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x12
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.GoodItemNumCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.GoodItemNumCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.GoodItemNumList.append(value)
        self.SuperItemNumCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SuperItemNumCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.SuperItemNumList.append(value)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x12
        self.ActNum = 0
        self.GoodItemNumCount = 0
        self.GoodItemNumList = list()
        self.SuperItemNumCount = 0
        self.SuperItemNumList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 1
        length += 1 * self.GoodItemNumCount
        length += 1
        length += 1 * self.SuperItemNumCount
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.ActNum)
        data = CommFunc.WriteBYTE(data, self.GoodItemNumCount)
        for i in range(self.GoodItemNumCount):
            data = CommFunc.WriteBYTE(data, self.GoodItemNumList[i])
        data = CommFunc.WriteBYTE(data, self.SuperItemNumCount)
        for i in range(self.SuperItemNumCount):
            data = CommFunc.WriteBYTE(data, self.SuperItemNumList[i])
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                ActNum:%d,
                                GoodItemNumCount:%d,
                                GoodItemNumList:%s,
                                SuperItemNumCount:%d,
                                SuperItemNumList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.ActNum,
                                self.GoodItemNumCount,
                                "...",
                                self.SuperItemNumCount,
                                "..."
                                )
        return DumpString
m_NAtagCMActTurntableChooseItem=tagCMActTurntableChooseItem()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActTurntableChooseItem.Head.Cmd,m_NAtagCMActTurntableChooseItem.Head.SubCmd))] = m_NAtagCMActTurntableChooseItem
#------------------------------------------------------
# AA 13 启动转盘 #tagCMActTurntableStart
class  tagCMActTurntableStart(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ActNum", c_ubyte),    # 活动编号
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xAA
        self.SubCmd = 0x13
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xAA
        self.SubCmd = 0x13
        self.ActNum = 0
        return
    def GetLength(self):
        return sizeof(tagCMActTurntableStart)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AA 13 启动转盘 //tagCMActTurntableStart:
                                Cmd:%s,
                                SubCmd:%s,
                                ActNum:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ActNum
                                )
        return DumpString
m_NAtagCMActTurntableStart=tagCMActTurntableStart()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActTurntableStart.Cmd,m_NAtagCMActTurntableStart.SubCmd))] = m_NAtagCMActTurntableStart
#------------------------------------------------------
# AA 07 许愿池活动刷新奖池 #tagCMActWishingRefresh
class  tagCMActWishingRefresh(Structure):
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -26533,6 +26533,315 @@
#------------------------------------------------------
# AA 52 转盘活动信息 #tagMCActTurntableInfo
class  tagMCActTurntableItem(Structure):
    _pack_ = 1
    _fields_ = [
                  ("ItemNum", c_ubyte),    #物品编号 1~n;注意转盘已确定物品编号 与 极品终极物品待选择库编号可能相同,但并不代表同一物品
                  ("ItemLibType", c_ubyte),    #物品库类型;1-常规,2-极品,3-终极
                  ("ItemID", c_int),
                  ("ItemCount", c_ushort),
                  ]
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.ItemNum = 0
        self.ItemLibType = 0
        self.ItemID = 0
        self.ItemCount = 0
        return
    def GetLength(self):
        return sizeof(tagMCActTurntableItem)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AA 52 转盘活动信息 //tagMCActTurntableInfo:
                                ItemNum:%d,
                                ItemLibType:%d,
                                ItemID:%d,
                                ItemCount:%d
                                '''\
                                %(
                                self.ItemNum,
                                self.ItemLibType,
                                self.ItemID,
                                self.ItemCount
                                )
        return DumpString
class  tagMCActTurntableInfo(Structure):
    Head = tagHead()
    ActNum = 0    #(BYTE ActNum)// 活动编号
    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
    IsDayReset = 0    #(BYTE IsDayReset)// 是否每天重置
    LimitLV = 0    #(WORD LimitLV)// 限制等级
    CTGPrizeCount = 0    #(BYTE CTGPrizeCount)
    CTGPrizeList = list()    #(vector<DWORD> CTGPrizeList)// 累计充值额度奖励次数列表 [奖励第1次所需累计充值额度, 第2次, ...]
    UseGoldPrizeCount = 0    #(BYTE UseGoldPrizeCount)
    UseGoldPrizeList = list()    #(vector<DWORD> UseGoldPrizeList)// 累计消费仙玉奖励次数列表 [奖励第1次所需累计消费仙玉, 第2次, ...]
    TurnItemCount = 0    #(BYTE TurnItemCount)
    TurnItemList = list()    #(vector<tagMCActTurntableItem> TurnItemList)// 转盘已确定的物品列表,包含常规物品+极品物品+终极物品,活动开始时,后端直接随机生成常规物品,已确定的物品不包含极品、终极物品时需要先选择才能使用转盘;
    GoodItemCount = 0    #(BYTE GoodItemCount)
    GoodItemList = list()    #(vector<tagMCActTurntableItem> GoodItemList)// 极品物品待选择库,由玩家从库中选择放入转盘的物品;注意此库中的物品编号仅表示在该库中的编号,可能与转盘已确定的物品编号重复,但并不代表同一物品;
    GoodItemCanChooseCount = 0    #(BYTE GoodItemCanChooseCount)// 极品物品可选择个数
    SuperItemCount = 0    #(BYTE SuperItemCount)
    SuperItemList = list()    #(vector<tagMCActTurntableItem> SuperItemList)// 终极物品待选择库,由玩家从库中选择放入转盘的物品;注意此库中的物品编号仅表示在该库中的编号,可能与转盘已确定的物品编号重复,但并不代表同一物品;
    SuperItemCanChooseCount = 0    #(BYTE SuperItemCanChooseCount)// 终极物品可选择个数
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x52
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
        self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
        self.IsDayReset,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.CTGPrizeCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.CTGPrizeCount):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.CTGPrizeList.append(value)
        self.UseGoldPrizeCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.UseGoldPrizeCount):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.UseGoldPrizeList.append(value)
        self.TurnItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.TurnItemCount):
            temTurnItemList = tagMCActTurntableItem()
            _pos = temTurnItemList.ReadData(_lpData, _pos)
            self.TurnItemList.append(temTurnItemList)
        self.GoodItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.GoodItemCount):
            temGoodItemList = tagMCActTurntableItem()
            _pos = temGoodItemList.ReadData(_lpData, _pos)
            self.GoodItemList.append(temGoodItemList)
        self.GoodItemCanChooseCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.SuperItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SuperItemCount):
            temSuperItemList = tagMCActTurntableItem()
            _pos = temSuperItemList.ReadData(_lpData, _pos)
            self.SuperItemList.append(temSuperItemList)
        self.SuperItemCanChooseCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x52
        self.ActNum = 0
        self.StartDate = ""
        self.EndtDate = ""
        self.IsDayReset = 0
        self.LimitLV = 0
        self.CTGPrizeCount = 0
        self.CTGPrizeList = list()
        self.UseGoldPrizeCount = 0
        self.UseGoldPrizeList = list()
        self.TurnItemCount = 0
        self.TurnItemList = list()
        self.GoodItemCount = 0
        self.GoodItemList = list()
        self.GoodItemCanChooseCount = 0
        self.SuperItemCount = 0
        self.SuperItemList = list()
        self.SuperItemCanChooseCount = 0
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 10
        length += 10
        length += 1
        length += 2
        length += 1
        length += 4 * self.CTGPrizeCount
        length += 1
        length += 4 * self.UseGoldPrizeCount
        length += 1
        for i in range(self.TurnItemCount):
            length += self.TurnItemList[i].GetLength()
        length += 1
        for i in range(self.GoodItemCount):
            length += self.GoodItemList[i].GetLength()
        length += 1
        length += 1
        for i in range(self.SuperItemCount):
            length += self.SuperItemList[i].GetLength()
        length += 1
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.ActNum)
        data = CommFunc.WriteString(data, 10, self.StartDate)
        data = CommFunc.WriteString(data, 10, self.EndtDate)
        data = CommFunc.WriteBYTE(data, self.IsDayReset)
        data = CommFunc.WriteWORD(data, self.LimitLV)
        data = CommFunc.WriteBYTE(data, self.CTGPrizeCount)
        for i in range(self.CTGPrizeCount):
            data = CommFunc.WriteDWORD(data, self.CTGPrizeList[i])
        data = CommFunc.WriteBYTE(data, self.UseGoldPrizeCount)
        for i in range(self.UseGoldPrizeCount):
            data = CommFunc.WriteDWORD(data, self.UseGoldPrizeList[i])
        data = CommFunc.WriteBYTE(data, self.TurnItemCount)
        for i in range(self.TurnItemCount):
            data = CommFunc.WriteString(data, self.TurnItemList[i].GetLength(), self.TurnItemList[i].GetBuffer())
        data = CommFunc.WriteBYTE(data, self.GoodItemCount)
        for i in range(self.GoodItemCount):
            data = CommFunc.WriteString(data, self.GoodItemList[i].GetLength(), self.GoodItemList[i].GetBuffer())
        data = CommFunc.WriteBYTE(data, self.GoodItemCanChooseCount)
        data = CommFunc.WriteBYTE(data, self.SuperItemCount)
        for i in range(self.SuperItemCount):
            data = CommFunc.WriteString(data, self.SuperItemList[i].GetLength(), self.SuperItemList[i].GetBuffer())
        data = CommFunc.WriteBYTE(data, self.SuperItemCanChooseCount)
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                ActNum:%d,
                                StartDate:%s,
                                EndtDate:%s,
                                IsDayReset:%d,
                                LimitLV:%d,
                                CTGPrizeCount:%d,
                                CTGPrizeList:%s,
                                UseGoldPrizeCount:%d,
                                UseGoldPrizeList:%s,
                                TurnItemCount:%d,
                                TurnItemList:%s,
                                GoodItemCount:%d,
                                GoodItemList:%s,
                                GoodItemCanChooseCount:%d,
                                SuperItemCount:%d,
                                SuperItemList:%s,
                                SuperItemCanChooseCount:%d
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.ActNum,
                                self.StartDate,
                                self.EndtDate,
                                self.IsDayReset,
                                self.LimitLV,
                                self.CTGPrizeCount,
                                "...",
                                self.UseGoldPrizeCount,
                                "...",
                                self.TurnItemCount,
                                "...",
                                self.GoodItemCount,
                                "...",
                                self.GoodItemCanChooseCount,
                                self.SuperItemCount,
                                "...",
                                self.SuperItemCanChooseCount
                                )
        return DumpString
m_NAtagMCActTurntableInfo=tagMCActTurntableInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActTurntableInfo.Head.Cmd,m_NAtagMCActTurntableInfo.Head.SubCmd))] = m_NAtagMCActTurntableInfo
#------------------------------------------------------
# AA 53 转盘活动玩家信息 #tagMCActTurntablePlayerInfo
class  tagMCActTurntablePlayerInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ActNum", c_ubyte),    #活动编号
                  ("CanUseCount", c_ubyte),    #可转盘次数
                  ("CTGTotal", c_int),    #累计充值额度
                  ("UseGoldTotal", c_int),    #累计消费仙玉额度
                  ("TurnItemState", c_int),    #转盘物品已抽中记录,按转盘物品编号二进制位代表是否已抽中
                  ("GetItemNum", c_ubyte),    #本次抽中的物品编号,非转盘结果时为0,大于0时为通知本次转到的物品编号
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xAA
        self.SubCmd = 0x53
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xAA
        self.SubCmd = 0x53
        self.ActNum = 0
        self.CanUseCount = 0
        self.CTGTotal = 0
        self.UseGoldTotal = 0
        self.TurnItemState = 0
        self.GetItemNum = 0
        return
    def GetLength(self):
        return sizeof(tagMCActTurntablePlayerInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AA 53 转盘活动玩家信息 //tagMCActTurntablePlayerInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                ActNum:%d,
                                CanUseCount:%d,
                                CTGTotal:%d,
                                UseGoldTotal:%d,
                                TurnItemState:%d,
                                GetItemNum:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ActNum,
                                self.CanUseCount,
                                self.CTGTotal,
                                self.UseGoldTotal,
                                self.TurnItemState,
                                self.GetItemNum
                                )
        return DumpString
m_NAtagMCActTurntablePlayerInfo=tagMCActTurntablePlayerInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActTurntablePlayerInfo.Cmd,m_NAtagMCActTurntablePlayerInfo.SubCmd))] = m_NAtagMCActTurntablePlayerInfo
#------------------------------------------------------
# AA 1B 许愿池拖动结果 #tagMCActWishingDragResult
class  tagMCPlayerWishingDragInfo(Structure):
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -532,6 +532,16 @@
                        ("BYTE", "IsDayReset", 0),
                        ),
                "ActTurntable":(
                        ("DWORD", "CfgID", 1),
                        ("list", "PlatformList", 0),
                        ("list", "ServerGroupIDList", 0),
                        ("BYTE", "ActNum", 0),
                        ("char", "StartDate", 0),
                        ("char", "EndDate", 0),
                        ("BYTE", "IsDayReset", 0),
                        ),
                "ActManyDayRecharge":(
                        ("DWORD", "CfgID", 1),
                        ("list", "PlatformList", 0),
@@ -1768,6 +1778,27 @@
    def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
    def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
# 转盘活动表
class IPY_ActTurntable():
    def __init__(self):
        self.CfgID = 0
        self.PlatformList = []
        self.ServerGroupIDList = []
        self.ActNum = 0
        self.StartDate = ""
        self.EndDate = ""
        self.IsDayReset = 0
        return
    def GetCfgID(self): return self.CfgID # 配置ID
    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 GetIsDayReset(self): return self.IsDayReset # 是否每天重置
# 多日连充活动表
class IPY_ActManyDayRecharge():
    
@@ -2279,6 +2310,8 @@
        self.ipyActGrowupBuyLen = len(self.ipyActGrowupBuyCache)
        self.ipyActSingleRechargeCache = self.__LoadFileData("ActSingleRecharge", IPY_ActSingleRecharge)
        self.ipyActSingleRechargeLen = len(self.ipyActSingleRechargeCache)
        self.ipyActTurntableCache = self.__LoadFileData("ActTurntable", IPY_ActTurntable)
        self.ipyActTurntableLen = len(self.ipyActTurntableCache)
        self.ipyActManyDayRechargeCache = self.__LoadFileData("ActManyDayRecharge", IPY_ActManyDayRecharge)
        self.ipyActManyDayRechargeLen = len(self.ipyActManyDayRechargeCache)
        self.ipyActTotalRechargeCache = self.__LoadFileData("ActTotalRecharge", IPY_ActTotalRecharge)
@@ -2575,6 +2608,8 @@
    def GetActGrowupBuyByIndex(self, index): return self.ipyActGrowupBuyCache[index]
    def GetActSingleRechargeCount(self): return self.ipyActSingleRechargeLen
    def GetActSingleRechargeByIndex(self, index): return self.ipyActSingleRechargeCache[index]
    def GetActTurntableCount(self): return self.ipyActTurntableLen
    def GetActTurntableByIndex(self, index): return self.ipyActTurntableCache[index]
    def GetActManyDayRechargeCount(self): return self.ipyActManyDayRechargeLen
    def GetActManyDayRechargeByIndex(self, index): return self.ipyActManyDayRechargeCache[index]
    def GetActTotalRechargeCount(self): return self.ipyActTotalRechargeLen
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -234,6 +234,7 @@
OperationActionName_FeastTravel = "ActFeastTravel" # 节日游历活动
OperationActionName_ManyDayRecharge = "ActManyDayRecharge" # 多日连充活动
OperationActionName_SingleRecharge = "ActSingleRecharge" # 单笔累充活动
OperationActionName_Turntable = "ActTurntable" # 转盘活动
#节日活动类型列表 - 该类型无视开服天,日期到了就开启
FeastOperationActionNameList = [OperationActionName_FeastWeekParty, OperationActionName_FeastRedPacket,
                                OperationActionName_RechargeRebateGold, OperationActionName_GrowupBuy,
@@ -251,6 +252,7 @@
                           OperationActionName_NewFairyCeremony, OperationActionName_LuckyTreasure,
                           OperationActionName_DailyGiftbag, OperationActionName_SingleRecharge,
                           OperationActionName_CollectWords, OperationActionName_ManyDayRecharge,
                           OperationActionName_Turntable,
                           ] + FeastOperationActionNameList
#需要记录开启活动时的世界等级的运营活动
NeedWorldLVOperationActNameList = [OperationActionName_FairyCeremony, OperationActionName_WishingWell, 
@@ -259,7 +261,7 @@
                                   OperationActionName_CostRebate, OperationActionName_FlashGiftbag,
                                   OperationActionName_SpringSale, OperationActionName_LuckyTreasure,
                                   OperationActionName_DailyGiftbag, OperationActionName_GrowupBuy,
                                   OperationActionName_WeekParty,
                                   OperationActionName_WeekParty, OperationActionName_Turntable,
                                   OperationActionName_CollectWords,
                                   OperationActionName_FeastLogin,
                                   OperationActionName_FeastWish, OperationActionName_FeastTravel,
@@ -271,6 +273,7 @@
                                   OperationActionName_FlashGiftbag, OperationActionName_CostRebate,
                                   OperationActionName_SpringSale, OperationActionName_FlashSale,
                                   OperationActionName_ManyDayRecharge, OperationActionName_SingleRecharge,
                                   OperationActionName_Turntable,
                                   ]
#跨服运营活动表名定义
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3872,6 +3872,17 @@
Def_PDict_SingleRechargeWorldLV = "SingleRechargeWorldLV_%s" #玩家身上的活动世界等级,参数:(活动编号)
Def_PDict_SingleRechargeValue = "SingleRechargeValue_%s"  # 领奖奖励值,按奖励索引二进制位代表是否可领奖,参数:(活动编号)
Def_PDict_SingleRechargeAward = "SingleRechargeAward_%s"  # 领奖记录值,按奖励索引二进制位代表是否已领奖,参数:(活动编号)
#转盘活动
Def_PDict_TurntableID = "TurntableID_%s"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值,参数:(活动编号)
Def_PDict_TurntableWorldLV = "TurntableWorldLV_%s" #玩家身上的活动世界等级,参数:(活动编号)
Def_PDict_TurntableLoginState = "TurntableLoginState_%s"  # 登录加次数状态,参数:(活动编号)
Def_PDict_TurntableCTGValue = "TurntableCTGValue_%s"  # 累计充值,参数:(活动编号)
Def_PDict_TurntableUseGold = "TurntableUseGold_%s"  # 累计消费仙玉,参数:(活动编号)
Def_PDict_TurntableCanUseCount = "TurntableCanUseCount_%s"  # 可使用转盘次数,参数:(活动编号)
Def_PDict_TurntableItemID = "TurntableItemID_%s_%s"  # 转盘物品ID*10+物品库类型,参数:(活动编号, 物品编号)
Def_PDict_TurntableItemCount = "TurntableCount_%s_%s"  # 转盘物品个数,参数:(活动编号, 物品编号)
Def_PDict_TurntableItemState = "TurntableItemState_%s"  # 转盘物品是否已抽中,按物品编号二进制位代表是否已抽中,参数:(活动编号)
#-------------------------------------------------------------------------------
#开服活动,Def_PDictType_OpenServerCampaign
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -13321,6 +13321,149 @@
#------------------------------------------------------
# AA 12 选择转盘活动物品 #tagCMActTurntableChooseItem
class  tagCMActTurntableChooseItem(Structure):
    Head = tagHead()
    ActNum = 0    #(BYTE ActNum)// 活动编号
    GoodItemNumCount = 0    #(BYTE GoodItemNumCount)
    GoodItemNumList = list()    #(vector<BYTE> GoodItemNumList)// 选择的极品物品编号列表
    SuperItemNumCount = 0    #(BYTE SuperItemNumCount)
    SuperItemNumList = list()    #(vector<BYTE> SuperItemNumList)// 选择的终极物品编号列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x12
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.GoodItemNumCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.GoodItemNumCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.GoodItemNumList.append(value)
        self.SuperItemNumCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SuperItemNumCount):
            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
            self.SuperItemNumList.append(value)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x12
        self.ActNum = 0
        self.GoodItemNumCount = 0
        self.GoodItemNumList = list()
        self.SuperItemNumCount = 0
        self.SuperItemNumList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 1
        length += 1 * self.GoodItemNumCount
        length += 1
        length += 1 * self.SuperItemNumCount
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.ActNum)
        data = CommFunc.WriteBYTE(data, self.GoodItemNumCount)
        for i in range(self.GoodItemNumCount):
            data = CommFunc.WriteBYTE(data, self.GoodItemNumList[i])
        data = CommFunc.WriteBYTE(data, self.SuperItemNumCount)
        for i in range(self.SuperItemNumCount):
            data = CommFunc.WriteBYTE(data, self.SuperItemNumList[i])
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                ActNum:%d,
                                GoodItemNumCount:%d,
                                GoodItemNumList:%s,
                                SuperItemNumCount:%d,
                                SuperItemNumList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.ActNum,
                                self.GoodItemNumCount,
                                "...",
                                self.SuperItemNumCount,
                                "..."
                                )
        return DumpString
m_NAtagCMActTurntableChooseItem=tagCMActTurntableChooseItem()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActTurntableChooseItem.Head.Cmd,m_NAtagCMActTurntableChooseItem.Head.SubCmd))] = m_NAtagCMActTurntableChooseItem
#------------------------------------------------------
# AA 13 启动转盘 #tagCMActTurntableStart
class  tagCMActTurntableStart(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ActNum", c_ubyte),    # 活动编号
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xAA
        self.SubCmd = 0x13
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xAA
        self.SubCmd = 0x13
        self.ActNum = 0
        return
    def GetLength(self):
        return sizeof(tagCMActTurntableStart)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AA 13 启动转盘 //tagCMActTurntableStart:
                                Cmd:%s,
                                SubCmd:%s,
                                ActNum:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ActNum
                                )
        return DumpString
m_NAtagCMActTurntableStart=tagCMActTurntableStart()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActTurntableStart.Cmd,m_NAtagCMActTurntableStart.SubCmd))] = m_NAtagCMActTurntableStart
#------------------------------------------------------
# AA 07 许愿池活动刷新奖池 #tagCMActWishingRefresh
class  tagCMActWishingRefresh(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -26533,6 +26533,315 @@
#------------------------------------------------------
# AA 52 转盘活动信息 #tagMCActTurntableInfo
class  tagMCActTurntableItem(Structure):
    _pack_ = 1
    _fields_ = [
                  ("ItemNum", c_ubyte),    #物品编号 1~n;注意转盘已确定物品编号 与 极品终极物品待选择库编号可能相同,但并不代表同一物品
                  ("ItemLibType", c_ubyte),    #物品库类型;1-常规,2-极品,3-终极
                  ("ItemID", c_int),
                  ("ItemCount", c_ushort),
                  ]
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.ItemNum = 0
        self.ItemLibType = 0
        self.ItemID = 0
        self.ItemCount = 0
        return
    def GetLength(self):
        return sizeof(tagMCActTurntableItem)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AA 52 转盘活动信息 //tagMCActTurntableInfo:
                                ItemNum:%d,
                                ItemLibType:%d,
                                ItemID:%d,
                                ItemCount:%d
                                '''\
                                %(
                                self.ItemNum,
                                self.ItemLibType,
                                self.ItemID,
                                self.ItemCount
                                )
        return DumpString
class  tagMCActTurntableInfo(Structure):
    Head = tagHead()
    ActNum = 0    #(BYTE ActNum)// 活动编号
    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
    IsDayReset = 0    #(BYTE IsDayReset)// 是否每天重置
    LimitLV = 0    #(WORD LimitLV)// 限制等级
    CTGPrizeCount = 0    #(BYTE CTGPrizeCount)
    CTGPrizeList = list()    #(vector<DWORD> CTGPrizeList)// 累计充值额度奖励次数列表 [奖励第1次所需累计充值额度, 第2次, ...]
    UseGoldPrizeCount = 0    #(BYTE UseGoldPrizeCount)
    UseGoldPrizeList = list()    #(vector<DWORD> UseGoldPrizeList)// 累计消费仙玉奖励次数列表 [奖励第1次所需累计消费仙玉, 第2次, ...]
    TurnItemCount = 0    #(BYTE TurnItemCount)
    TurnItemList = list()    #(vector<tagMCActTurntableItem> TurnItemList)// 转盘已确定的物品列表,包含常规物品+极品物品+终极物品,活动开始时,后端直接随机生成常规物品,已确定的物品不包含极品、终极物品时需要先选择才能使用转盘;
    GoodItemCount = 0    #(BYTE GoodItemCount)
    GoodItemList = list()    #(vector<tagMCActTurntableItem> GoodItemList)// 极品物品待选择库,由玩家从库中选择放入转盘的物品;注意此库中的物品编号仅表示在该库中的编号,可能与转盘已确定的物品编号重复,但并不代表同一物品;
    GoodItemCanChooseCount = 0    #(BYTE GoodItemCanChooseCount)// 极品物品可选择个数
    SuperItemCount = 0    #(BYTE SuperItemCount)
    SuperItemList = list()    #(vector<tagMCActTurntableItem> SuperItemList)// 终极物品待选择库,由玩家从库中选择放入转盘的物品;注意此库中的物品编号仅表示在该库中的编号,可能与转盘已确定的物品编号重复,但并不代表同一物品;
    SuperItemCanChooseCount = 0    #(BYTE SuperItemCanChooseCount)// 终极物品可选择个数
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x52
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.ActNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
        self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
        self.IsDayReset,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.CTGPrizeCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.CTGPrizeCount):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.CTGPrizeList.append(value)
        self.UseGoldPrizeCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.UseGoldPrizeCount):
            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
            self.UseGoldPrizeList.append(value)
        self.TurnItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.TurnItemCount):
            temTurnItemList = tagMCActTurntableItem()
            _pos = temTurnItemList.ReadData(_lpData, _pos)
            self.TurnItemList.append(temTurnItemList)
        self.GoodItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.GoodItemCount):
            temGoodItemList = tagMCActTurntableItem()
            _pos = temGoodItemList.ReadData(_lpData, _pos)
            self.GoodItemList.append(temGoodItemList)
        self.GoodItemCanChooseCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.SuperItemCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SuperItemCount):
            temSuperItemList = tagMCActTurntableItem()
            _pos = temSuperItemList.ReadData(_lpData, _pos)
            self.SuperItemList.append(temSuperItemList)
        self.SuperItemCanChooseCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xAA
        self.Head.SubCmd = 0x52
        self.ActNum = 0
        self.StartDate = ""
        self.EndtDate = ""
        self.IsDayReset = 0
        self.LimitLV = 0
        self.CTGPrizeCount = 0
        self.CTGPrizeList = list()
        self.UseGoldPrizeCount = 0
        self.UseGoldPrizeList = list()
        self.TurnItemCount = 0
        self.TurnItemList = list()
        self.GoodItemCount = 0
        self.GoodItemList = list()
        self.GoodItemCanChooseCount = 0
        self.SuperItemCount = 0
        self.SuperItemList = list()
        self.SuperItemCanChooseCount = 0
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        length += 10
        length += 10
        length += 1
        length += 2
        length += 1
        length += 4 * self.CTGPrizeCount
        length += 1
        length += 4 * self.UseGoldPrizeCount
        length += 1
        for i in range(self.TurnItemCount):
            length += self.TurnItemList[i].GetLength()
        length += 1
        for i in range(self.GoodItemCount):
            length += self.GoodItemList[i].GetLength()
        length += 1
        length += 1
        for i in range(self.SuperItemCount):
            length += self.SuperItemList[i].GetLength()
        length += 1
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.ActNum)
        data = CommFunc.WriteString(data, 10, self.StartDate)
        data = CommFunc.WriteString(data, 10, self.EndtDate)
        data = CommFunc.WriteBYTE(data, self.IsDayReset)
        data = CommFunc.WriteWORD(data, self.LimitLV)
        data = CommFunc.WriteBYTE(data, self.CTGPrizeCount)
        for i in range(self.CTGPrizeCount):
            data = CommFunc.WriteDWORD(data, self.CTGPrizeList[i])
        data = CommFunc.WriteBYTE(data, self.UseGoldPrizeCount)
        for i in range(self.UseGoldPrizeCount):
            data = CommFunc.WriteDWORD(data, self.UseGoldPrizeList[i])
        data = CommFunc.WriteBYTE(data, self.TurnItemCount)
        for i in range(self.TurnItemCount):
            data = CommFunc.WriteString(data, self.TurnItemList[i].GetLength(), self.TurnItemList[i].GetBuffer())
        data = CommFunc.WriteBYTE(data, self.GoodItemCount)
        for i in range(self.GoodItemCount):
            data = CommFunc.WriteString(data, self.GoodItemList[i].GetLength(), self.GoodItemList[i].GetBuffer())
        data = CommFunc.WriteBYTE(data, self.GoodItemCanChooseCount)
        data = CommFunc.WriteBYTE(data, self.SuperItemCount)
        for i in range(self.SuperItemCount):
            data = CommFunc.WriteString(data, self.SuperItemList[i].GetLength(), self.SuperItemList[i].GetBuffer())
        data = CommFunc.WriteBYTE(data, self.SuperItemCanChooseCount)
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                ActNum:%d,
                                StartDate:%s,
                                EndtDate:%s,
                                IsDayReset:%d,
                                LimitLV:%d,
                                CTGPrizeCount:%d,
                                CTGPrizeList:%s,
                                UseGoldPrizeCount:%d,
                                UseGoldPrizeList:%s,
                                TurnItemCount:%d,
                                TurnItemList:%s,
                                GoodItemCount:%d,
                                GoodItemList:%s,
                                GoodItemCanChooseCount:%d,
                                SuperItemCount:%d,
                                SuperItemList:%s,
                                SuperItemCanChooseCount:%d
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.ActNum,
                                self.StartDate,
                                self.EndtDate,
                                self.IsDayReset,
                                self.LimitLV,
                                self.CTGPrizeCount,
                                "...",
                                self.UseGoldPrizeCount,
                                "...",
                                self.TurnItemCount,
                                "...",
                                self.GoodItemCount,
                                "...",
                                self.GoodItemCanChooseCount,
                                self.SuperItemCount,
                                "...",
                                self.SuperItemCanChooseCount
                                )
        return DumpString
m_NAtagMCActTurntableInfo=tagMCActTurntableInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActTurntableInfo.Head.Cmd,m_NAtagMCActTurntableInfo.Head.SubCmd))] = m_NAtagMCActTurntableInfo
#------------------------------------------------------
# AA 53 转盘活动玩家信息 #tagMCActTurntablePlayerInfo
class  tagMCActTurntablePlayerInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("ActNum", c_ubyte),    #活动编号
                  ("CanUseCount", c_ubyte),    #可转盘次数
                  ("CTGTotal", c_int),    #累计充值额度
                  ("UseGoldTotal", c_int),    #累计消费仙玉额度
                  ("TurnItemState", c_int),    #转盘物品已抽中记录,按转盘物品编号二进制位代表是否已抽中
                  ("GetItemNum", c_ubyte),    #本次抽中的物品编号,非转盘结果时为0,大于0时为通知本次转到的物品编号
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xAA
        self.SubCmd = 0x53
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xAA
        self.SubCmd = 0x53
        self.ActNum = 0
        self.CanUseCount = 0
        self.CTGTotal = 0
        self.UseGoldTotal = 0
        self.TurnItemState = 0
        self.GetItemNum = 0
        return
    def GetLength(self):
        return sizeof(tagMCActTurntablePlayerInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// AA 53 转盘活动玩家信息 //tagMCActTurntablePlayerInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                ActNum:%d,
                                CanUseCount:%d,
                                CTGTotal:%d,
                                UseGoldTotal:%d,
                                TurnItemState:%d,
                                GetItemNum:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.ActNum,
                                self.CanUseCount,
                                self.CTGTotal,
                                self.UseGoldTotal,
                                self.TurnItemState,
                                self.GetItemNum
                                )
        return DumpString
m_NAtagMCActTurntablePlayerInfo=tagMCActTurntablePlayerInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActTurntablePlayerInfo.Cmd,m_NAtagMCActTurntablePlayerInfo.SubCmd))] = m_NAtagMCActTurntablePlayerInfo
#------------------------------------------------------
# AA 1B 许愿池拖动结果 #tagMCActWishingDragResult
class  tagMCPlayerWishingDragInfo(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1324,6 +1324,23 @@
                        ("char", "NotifyKey", 0),
                        ),
                "ActTurntable":(
                        ("DWORD", "CfgID", 1),
                        ("char", "StartDate", 0),
                        ("char", "EndDate", 0),
                        ("WORD", "LVLimit", 0),
                        ("BYTE", "IsDayReset", 0),
                        ("BYTE", "CTGTypeEffValue", 0),
                        ("list", "CTGPrizeList", 0),
                        ("list", "UseGoldPrizeList", 0),
                        ("list", "LibChooseCountList", 0),
                        ("list", "SuperItemLimitRule", 0),
                        ("dict", "CommItemLib", 0),
                        ("dict", "GoodItemLib", 0),
                        ("dict", "SuperItemLib", 0),
                        ("char", "WorldNotifyKey", 0),
                        ),
                "ActSingleRecharge":(
                        ("DWORD", "CfgID", 1),
                        ("char", "StartDate", 0),
@@ -4503,6 +4520,41 @@
    def GetAwardItemInfo(self): return self.AwardItemInfo # 奖励物品信息  {世界等级范围:[[物品ID,个数,是否拍品], ...]}
    def GetNotifyKey(self): return self.NotifyKey # 广播
# 转盘活动表
class IPY_ActTurntable():
    def __init__(self):
        self.CfgID = 0
        self.StartDate = ""
        self.EndDate = ""
        self.LVLimit = 0
        self.IsDayReset = 0
        self.CTGTypeEffValue = 0
        self.CTGPrizeList = []
        self.UseGoldPrizeList = []
        self.LibChooseCountList = []
        self.SuperItemLimitRule = []
        self.CommItemLib = {}
        self.GoodItemLib = {}
        self.SuperItemLib = {}
        self.WorldNotifyKey = ""
        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 GetCTGTypeEffValue(self): return self.CTGTypeEffValue # 充值有效类型值
    def GetCTGPrizeList(self): return self.CTGPrizeList # 累计充值奖励次数
    def GetUseGoldPrizeList(self): return self.UseGoldPrizeList # 累计消费X仙玉奖励次数
    def GetLibChooseCountList(self): return self.LibChooseCountList # 各道具库选择个数
    def GetSuperItemLimitRule(self): return self.SuperItemLimitRule # 终极库产出万分率|至少X次后可产出
    def GetCommItemLib(self): return self.CommItemLib # 普通道具库 {(世界等级A,世界等级B):[[可选物品ID, 个数, 是否拍品], ...], ...}
    def GetGoodItemLib(self): return self.GoodItemLib # 极品道具库 {(世界等级A,世界等级B):[[可选物品ID, 个数, 是否拍品], ...], ...}
    def GetSuperItemLib(self): return self.SuperItemLib # 超级道具库 {(世界等级A,世界等级B):[[可选物品ID, 个数, 是否拍品], ...], ...}
    def GetWorldNotifyKey(self): return self.WorldNotifyKey # 好物品全服广播mark,极品及超级道具默认全服广播
# 单笔累充活动表
class IPY_ActSingleRecharge():
    
@@ -5771,6 +5823,8 @@
        self.ipyActManyDayRechargeLen = len(self.ipyActManyDayRechargeCache)
        self.ipyActManyDayRechargeAwardCache = self.__LoadFileData("ActManyDayRechargeAward", IPY_ActManyDayRechargeAward)
        self.ipyActManyDayRechargeAwardLen = len(self.ipyActManyDayRechargeAwardCache)
        self.ipyActTurntableCache = self.__LoadFileData("ActTurntable", IPY_ActTurntable)
        self.ipyActTurntableLen = len(self.ipyActTurntableCache)
        self.ipyActSingleRechargeCache = self.__LoadFileData("ActSingleRecharge", IPY_ActSingleRecharge)
        self.ipyActSingleRechargeLen = len(self.ipyActSingleRechargeCache)
        self.ipyActSingleRechargeAwardCache = self.__LoadFileData("ActSingleRechargeAward", IPY_ActSingleRechargeAward)
@@ -6303,6 +6357,8 @@
    def GetActManyDayRechargeByIndex(self, index): return self.ipyActManyDayRechargeCache[index]
    def GetActManyDayRechargeAwardCount(self): return self.ipyActManyDayRechargeAwardLen
    def GetActManyDayRechargeAwardByIndex(self, index): return self.ipyActManyDayRechargeAwardCache[index]
    def GetActTurntableCount(self): return self.ipyActTurntableLen
    def GetActTurntableByIndex(self, index): return self.ipyActTurntableCache[index]
    def GetActSingleRechargeCount(self): return self.ipyActSingleRechargeLen
    def GetActSingleRechargeByIndex(self, index): return self.ipyActSingleRechargeCache[index]
    def GetActSingleRechargeAwardCount(self): return self.ipyActSingleRechargeAwardLen
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
@@ -77,7 +77,7 @@
#  @param packindex 背包索引
#  @return None
#  @remarks 函数详细说明.
def CheckPackHasSpace(curPlayer, packindex):
def CheckPackHasSpace(curPlayer, packindex=IPY_GameWorld.rptItem, isNotify=False):
    #物品背包是否有剩余空间
    curPack = curPlayer.GetItemManager().GetPack(packindex)
    for i in range(0, curPack.GetCount()):
@@ -86,6 +86,9 @@
        if item.IsEmpty():
            return True
        
    if isNotify:
        PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_676165", [packindex])
    return False
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTurntable.py
New file
@@ -0,0 +1,541 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.PlayerActTurntable
#
# @todo:转盘活动
# @author hxp
# @date 2021-05-06
# @version 1.0
#
# 详细描述: 转盘活动
#
#-------------------------------------------------------------------------------
#"""Version = 2021-05-06 16:30"""
#-------------------------------------------------------------------------------
import PyGameData
import ShareDefine
import PlayerControl
import IpyGameDataPY
import ItemControler
import ChPyNetSendPack
import IPY_GameWorld
import NetPackCommon
import GameWorld
import ChConfig
import random
# 物品库类型
(
ItemLibType_Comm, # 常规物品
ItemLibType_Good, # 极品物品
ItemLibType_Super, # 终极物品
) = range(1, 3 + 1)
def OnPlayerLogin(curPlayer):
    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_Turntable, {}).values():
        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
        isReset = __CheckPlayerTurntableAction(curPlayer, actNum)
        if not isReset:
            # 活动中同步活动信息
            if actInfo.get(ShareDefine.ActKey_State):
                AddTurntableUseCountByLogin(curPlayer, actNum)
                Sync_TurntableActionInfo(curPlayer, actNum)
                Sync_TurntablePlayerInfo(curPlayer, actNum)
    return
def PlayerOnDay(curPlayer):
    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_Turntable, {}).values():
        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
        if not actInfo.get(ShareDefine.ActKey_State):
            continue
        # 过天重置
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableLoginState % actNum, 0)
        AddTurntableUseCountByLogin(curPlayer, actNum)
        Sync_TurntablePlayerInfo(curPlayer, actNum)
    return
def RefreshTurntableActionInfo(actNum):
    ## 收到GameServer同步的活动信息,刷新活动信息
    playerManager = GameWorld.GetPlayerManager()
    for index in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        if curPlayer.GetID() == 0:
            continue
        __CheckPlayerTurntableAction(curPlayer, actNum)
    return
def __CheckPlayerTurntableAction(curPlayer, actNum):
    ## 检查玩家活动数据信息
    playerID = curPlayer.GetPlayerID()
    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_Turntable, actNum)
    actID = actInfo.get(ShareDefine.ActKey_ID, 0)
    state = actInfo.get(ShareDefine.ActKey_State, 0)
    playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableID % actNum) # 玩家身上的活动ID
    # 活动ID 相同的话不处理
    if actID == playerActID:
        GameWorld.DebugLog("转盘活动ID不变,不处理!actNum=%s,actID=%s" % (actNum, actID), playerID)
        return
    cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
    GameWorld.DebugLog("转盘活动重置! cfgID=%s,actNum=%s,actID=%s,playerActID=%s,state=%s" % (cfgID, actNum, actID, playerActID, state), playerID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableID % actNum, actID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableWorldLV % actNum, actWorldLV)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableLoginState % actNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableCTGValue % actNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableUseGold % actNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableCanUseCount % actNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemState % actNum, 0)
    ipyData = None if not cfgID else IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
    if ipyData:
        numCountList = ipyData.GetLibChooseCountList()
        numCountTotal = sum([numCount for numCount in numCountList])
        for num in xrange(1, numCountTotal + 1):
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemID % (actNum, num), 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemCount % (actNum, num), 0)
        if state:
            # 随机生成常规物品
            commItemCount = numCountList[0]
            commItemLib = GameWorld.GetDictValueByRangeKey(ipyData.GetCommItemLib(), actWorldLV, [])
            random.shuffle(commItemLib) # 打乱下顺序
            commItemList = commItemLib[:commItemCount]
            GameWorld.DebugLog("    随机生成常规物品: %s, %s" % (commItemCount, commItemList))
            for num, itemInfo in enumerate(commItemList, 1):
                itemID, itemCount, _ = itemInfo
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemID % (actNum, num), itemID * 10 + ItemLibType_Comm)
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemCount % (actNum, num), itemCount)
            # 增加登录奖励转盘次数
            AddTurntableUseCountByLogin(curPlayer, actNum)
    Sync_TurntableActionInfo(curPlayer, actNum)
    Sync_TurntablePlayerInfo(curPlayer, actNum)
    return True
def AddTurntableUseCountByLogin(curPlayer, actNum):
    ## 登录增加转盘次数
    if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableLoginState % actNum):
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableLoginState % actNum, 1)
    AddTurntableUseCount(curPlayer, actNum, 1)
    return
def AddTurntableUseCount(curPlayer, actNum, addCount):
    ## 增加转盘次数
    canUseCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableCanUseCount % actNum) + addCount
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableCanUseCount % actNum, canUseCount)
    GameWorld.DebugLog("    增加转盘活动次数: actNum=%s,addCount=%s,canUseCount=%s" % (actNum, addCount, canUseCount))
    return
def OnPlayerRecharge(curPlayer, curRechargeValue, coinType):
    ## 玩家充值
    if curRechargeValue <= 0:
        return
    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_Turntable, {}).values():
        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
        if not actInfo.get(ShareDefine.ActKey_State):
            GameWorld.DebugLog("转盘当前未开启! actNum=%s" % actNum)
            continue
        cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
        if not cfgID:
            continue
        ipyData = IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
        if not ipyData:
            continue
        ctgTypeEffValue = ipyData.GetCTGTypeEffValue()
        if not ctgTypeEffValue & pow(2, coinType):
            GameWorld.DebugLog("转盘活动充值类型对该活动无效! actNum=%s,coinType=%s,ctgTypeEffValue=%s"
                               % (actNum, coinType, ctgTypeEffValue), curPlayer.GetPlayerID())
            continue
        ctgPrizeList = ipyData.GetCTGPrizeList()
        nowCTGValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableCTGValue % actNum)
        if nowCTGValue >= max(ctgPrizeList):
            GameWorld.DebugLog("转盘活动充值已达最大记录,actNum=%s,nowCTGValue=%s,maxCTGValue=%s"
                               % (actNum, nowCTGValue, max(ctgPrizeList)))
            continue
        updCTGValue = nowCTGValue + curRechargeValue
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableCTGValue % actNum, updCTGValue)
        GameWorld.DebugLog("转盘活动充值,actNum=%s,nowCTGValue=%s,updCTGValue=%s,curRechargeValue=%s"
                           % (actNum, nowCTGValue, updCTGValue, curRechargeValue))
        addTurntableCount = 0
        for ctgValue in ctgPrizeList:
            if updCTGValue < ctgValue:
                break
            if nowCTGValue < ctgValue and updCTGValue >= ctgValue:
                addTurntableCount += 1
                GameWorld.DebugLog("    ctgValue=%s,addTurntableCount=%s" % (ctgValue, addTurntableCount))
        if addTurntableCount > 0:
            AddTurntableUseCount(curPlayer, actNum, addTurntableCount)
        Sync_TurntablePlayerInfo(curPlayer, actNum)
    return
def OnPlayerUseGold(curPlayer, addUseGold):
    ## 玩家消耗仙玉
    if addUseGold <= 0:
        return
    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_Turntable, {}).values():
        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
        if not actInfo.get(ShareDefine.ActKey_State):
            GameWorld.DebugLog("转盘当前未开启! actNum=%s" % actNum)
            continue
        cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
        if not cfgID:
            continue
        ipyData = IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
        if not ipyData:
            continue
        useGoldPrizeList = ipyData.GetUseGoldPrizeList()
        nowUseGold = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableUseGold % actNum)
        if nowUseGold >= max(useGoldPrizeList):
            GameWorld.DebugLog("转盘活动消耗仙玉已达最大记录,actNum=%s,nowUseGold=%s,maxUseGoldValue=%s"
                               % (actNum, nowUseGold, max(useGoldPrizeList)))
            continue
        updUseGold = nowUseGold + addUseGold
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableUseGold % actNum, updUseGold)
        GameWorld.DebugLog("转盘活动消耗仙玉,actNum=%s,nowUseGold=%s,updUseGold=%s,addUseGold=%s"
                           % (actNum, nowUseGold, updUseGold, addUseGold))
        addTurntableCount = 0
        for useGold in useGoldPrizeList:
            if updUseGold < useGold:
                break
            if nowUseGold < useGold and updUseGold >= useGold:
                addTurntableCount += 1
                GameWorld.DebugLog("    useGold=%s,addTurntableCount=%s" % (useGold, addTurntableCount))
        if addTurntableCount > 0:
            AddTurntableUseCount(curPlayer, actNum, addTurntableCount)
        Sync_TurntablePlayerInfo(curPlayer, actNum)
    return
#// AA 12 选择转盘活动物品 #tagCMActTurntableChooseItem
#
#struct    tagCMActTurntableChooseItem
#{
#    tagHead        Head;
#    BYTE        ActNum;        // 活动编号
#    BYTE        GoodItemNumCount;
#    BYTE        GoodItemNumList[GoodItemNumCount];    // 选择的极品物品编号列表
#    BYTE        SuperItemNumCount;
#    BYTE        SuperItemNumList[SuperItemNumCount];    // 选择的终极物品编号列表
#};
def OnTurntableChooseItem(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    actNum = clientData.ActNum
    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_Turntable, actNum)
    if not actInfo.get(ShareDefine.ActKey_State):
        return
    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
    if not cfgID:
        return
    ipyData = IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
    if not ipyData:
        return
    numCountList = ipyData.GetLibChooseCountList()
    numCountTotal = sum([numCount for numCount in numCountList])
    if len(numCountList) != 3:
        return
    commCount, goodCount, superCount = numCountList
    canChoose = True
    for num in xrange(1, numCountTotal + 1):
        itemIDInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemID % (actNum, num))
        itemID, itemLibType = itemIDInfo / 10, itemIDInfo % 10
        if itemID and itemLibType != ItemLibType_Comm:
            canChoose = False
            GameWorld.DebugLog("    已经选择过了转盘物品了,无法重复选择!")
            break
    if not canChoose:
        return
    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
    goodItemLib = GameWorld.GetDictValueByRangeKey(ipyData.GetGoodItemLib(), actWorldLV, [])
    chooseGoodItemNumList = clientData.GoodItemNumList
    if not chooseGoodItemNumList or len(chooseGoodItemNumList) != goodCount or min(chooseGoodItemNumList) <= 0 or max(chooseGoodItemNumList) > len(goodItemLib):
        GameWorld.ErrLog("    转盘活动极品物品选择错误!actNum=%s,chooseGoodItemNumList=%s,goodCount=%s,goodItemLibLen=%s"
                         % (actNum, chooseGoodItemNumList, goodCount, len(goodItemLib)))
        return
    superItemLib = GameWorld.GetDictValueByRangeKey(ipyData.GetSuperItemLib(), actWorldLV, [])
    chooseSuperItemNumList = clientData.SuperItemNumList
    if not chooseSuperItemNumList or len(chooseSuperItemNumList) != superCount or min(chooseSuperItemNumList) <= 0 or max(chooseSuperItemNumList) > len(superItemLib):
        GameWorld.ErrLog("    转盘活动终极物品选择错误!actNum=%s,chooseSuperItemNumList=%s,superCount=%s,superItemLibLen=%s"
                         % (actNum, chooseSuperItemNumList, superCount, len(superItemLib)))
        return
    useNum = commCount # 以普通物品个数为编号,递增
    GameWorld.DebugLog("转盘活动选择物品: actNum=%s,chooseGoodItemNumList=%s,chooseSuperItemNumList=%s" % (actNum, chooseGoodItemNumList, chooseSuperItemNumList))
    for chooseGoodNum in chooseGoodItemNumList:
        useNum += 1
        itemID, itemCount, _ = goodItemLib[chooseGoodNum - 1]
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemID % (actNum, useNum), itemID * 10 + ItemLibType_Good)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemCount % (actNum, useNum), itemCount)
        GameWorld.DebugLog("    存储选择极品物品: useNum=%s,itemID=%s,itemCount=%s" % (useNum, itemID, itemCount))
    for chooseSuperNum in chooseSuperItemNumList:
        useNum += 1
        itemID, itemCount, _ = superItemLib[chooseSuperNum - 1]
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemID % (actNum, useNum), itemID * 10 + ItemLibType_Super)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemCount % (actNum, useNum), itemCount)
        GameWorld.DebugLog("    存储选择终极物品: useNum=%s,itemID=%s,itemCount=%s" % (useNum, itemID, itemCount))
    Sync_TurntableActionInfo(curPlayer, actNum)
    return
#// AA 13 启动转盘 #tagCMActTurntableStart
#
#struct    tagCMActTurntableStart
#{
#    tagHead        Head;
#    BYTE        ActNum;        // 活动编号
#};
def OnTurntableStart(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    actNum = clientData.ActNum
    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_Turntable, actNum)
    if not actInfo.get(ShareDefine.ActKey_State):
        return
    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
    if not cfgID:
        return
    ipyData = IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
    if not ipyData:
        return
    canUseCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableCanUseCount % actNum)
    if canUseCount <= 0:
        GameWorld.DebugLog("没有转盘活动次数!actNum=%s" % actNum)
        return
    itemState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemState % actNum)
    numCountList = ipyData.GetLibChooseCountList()
    numCountTotal = sum([numCount for numCount in numCountList])
    canStart = False
    hadGetCount = 0
    isAuctionItem = 0 # 默认非拍品
    canGetItemInfoDict = {} # 还可以获得的物品信息 {itemLibType:{num:itemInfo, ...}, ...}
    for num in xrange(1, numCountTotal + 1):
        itemIDInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemID % (actNum, num))
        itemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemCount % (actNum, num))
        itemID, itemLibType = itemIDInfo / 10, itemIDInfo % 10
        if not itemID or not itemCount:
            continue
        if itemLibType != ItemLibType_Comm:
            canStart = True
        if itemState & pow(2, num):
            hadGetCount += 1
            continue
        if itemLibType not in canGetItemInfoDict:
            canGetItemInfoDict[itemLibType] = {}
        canGetItemInfoDict[itemLibType][num] = [itemID, itemCount, isAuctionItem]
    if not canStart:
        GameWorld.DebugLog("未选择转盘活动极品终极物品,无法启动转盘!")
        return
    if not ItemControler.CheckPackHasSpace(curPlayer, isNotify=True):
        return
    superRate, superLimitTurnCount = ipyData.GetSuperItemLimitRule() # 终极库产出万分率|至少X次后可产出
    GameWorld.DebugLog("启动转盘活动! actNum=%s,itemState=%s,hadGetCount=%s, superLimitTurnCount=%s,superRate=%s"
                       % (actNum, itemState, hadGetCount, superLimitTurnCount, superRate))
    GameWorld.DebugLog("    canGetItemInfoDict=%s" % canGetItemInfoDict)
    if not canGetItemInfoDict:
        return
    randNum = 0
    worldNotifyKey = ""
    giveItemInfo = []
    canGetCommNumList = canGetItemInfoDict.get(ItemLibType_Comm, {}).keys()
    canGetGoodNumList = canGetItemInfoDict.get(ItemLibType_Good, {}).keys()
    randNumWithoutSuperList = canGetCommNumList + canGetGoodNumList
    GameWorld.DebugLog("    不含终极物品的编号: %s" % (randNumWithoutSuperList))
    if hadGetCount >= superLimitTurnCount and ItemLibType_Super in canGetItemInfoDict:
        GameWorld.DebugLog("    有机会获得终极物品: superRate=%s" % superRate)
        if not randNumWithoutSuperList or GameWorld.CanHappen(superRate): # 没有其他物品了必出终极
            randNum = random.choice(canGetItemInfoDict[ItemLibType_Super].keys())
            giveItemInfo = canGetItemInfoDict[ItemLibType_Super][randNum]
            GameWorld.DebugLog("    获得终极物品! randNum=%s,giveItemInfo=%s" % (randNum, giveItemInfo))
            worldNotifyKey = ipyData.GetWorldNotifyKey()
    if not giveItemInfo and randNumWithoutSuperList:
        randNum = random.choice(randNumWithoutSuperList)
        if randNum in canGetGoodNumList:
            giveItemInfo = canGetItemInfoDict[ItemLibType_Good][randNum]
            GameWorld.DebugLog("    获得极品物品! randNum=%s,giveItemInfo=%s" % (randNum, giveItemInfo))
            worldNotifyKey = ipyData.GetWorldNotifyKey()
        else:
            giveItemInfo = canGetItemInfoDict[ItemLibType_Comm][randNum]
            GameWorld.DebugLog("    获得常规物品! randNum=%s,giveItemInfo=%s" % (randNum, giveItemInfo))
    if not giveItemInfo or not randNum:
        return
    updItemState = itemState | pow(2, randNum)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableItemState % actNum, updItemState)
    updCanUseCount = canUseCount - 1
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TurntableCanUseCount % actNum, updCanUseCount)
    GameWorld.DebugLog("    randNum=%s,updItemState=%s,updCanUseCount=%s" % (randNum, updItemState, updCanUseCount))
    itemID, itemCount, isAuctionItem = giveItemInfo
    ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem], event=["ActTurntable", False, {}])
    if worldNotifyKey:
        PlayerControl.WorldNotify(0, worldNotifyKey, [curPlayer.GetPlayerName(), itemID, itemCount])
    Sync_TurntablePlayerInfo(curPlayer, actNum, randNum)
    return
def Sync_TurntablePlayerInfo(curPlayer, actNum, getItemNum=0):
    ## 通知玩家数据信息
    # @param getItemNum: 本次转盘获得的对应物品编号
    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_Turntable, actNum)
    if not actInfo.get(ShareDefine.ActKey_State):
        return
    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
    if not cfgID:
        return
    ipyData = IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
    if not ipyData:
        return
    playerActInfo = ChPyNetSendPack.tagMCActTurntablePlayerInfo()
    playerActInfo.ActNum = actNum
    playerActInfo.CanUseCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableCanUseCount % actNum)
    playerActInfo.CTGTotal = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableCTGValue % actNum)
    playerActInfo.UseGoldTotal = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableUseGold % actNum)
    playerActInfo.TurnItemState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemState % actNum)
    playerActInfo.GetItemNum = getItemNum
    NetPackCommon.SendFakePack(curPlayer, playerActInfo)
    return
def Sync_TurntableActionInfo(curPlayer, actNum):
    ## 通知活动信息
    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_Turntable, actNum)
    if not actInfo.get(ShareDefine.ActKey_State):
        return
    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
    if not cfgID:
        return
    ipyData = IpyGameDataPY.GetIpyGameData("ActTurntable", cfgID)
    if not ipyData:
        return
    actWorldLV = actInfo.get(ShareDefine.ActKey_WorldLV, 0)
    openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
    clientPack = ChPyNetSendPack.tagMCActTurntableInfo()
    clientPack.ActNum = actNum
    clientPack.StartDate = GameWorld.GetOperationActionDateStr(ipyData.GetStartDate(), openServerDay)
    clientPack.EndtDate = GameWorld.GetOperationActionDateStr(ipyData.GetEndDate(), openServerDay)
    clientPack.IsDayReset = ipyData.GetIsDayReset()
    clientPack.LimitLV = ipyData.GetLVLimit()
    clientPack.CTGPrizeList = ipyData.GetCTGPrizeList()
    clientPack.CTGPrizeCount = len(clientPack.CTGPrizeList)
    clientPack.UseGoldPrizeList = ipyData.GetUseGoldPrizeList()
    clientPack.UseGoldPrizeCount = len(clientPack.UseGoldPrizeList)
    numCountList = ipyData.GetLibChooseCountList()
    numCountTotal = sum([numCount for numCount in numCountList])
    clientPack.TurnItemList = []
    for num in xrange(1, numCountTotal + 1):
        itemIDInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemID % (actNum, num))
        itemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TurntableItemCount % (actNum, num))
        itemID, itemLibType = itemIDInfo / 10, itemIDInfo % 10
        if not itemID:
            break
        packItem = ChPyNetSendPack.tagMCActTurntableItem()
        packItem.ItemNum = num
        packItem.ItemLibType = itemLibType
        packItem.ItemID = itemID
        packItem.ItemCount = itemCount
        clientPack.TurnItemList.append(packItem)
    clientPack.TurnItemCount = len(clientPack.TurnItemList)
    clientPack.GoodItemCanChooseCount = numCountList[1] if len(numCountList) > 1 else 0
    goodItemLib = GameWorld.GetDictValueByRangeKey(ipyData.GetGoodItemLib(), actWorldLV, [])
    for num, itemInfo in enumerate(goodItemLib, 1):
        itemID, itemCount, _ = itemInfo
        packItem = ChPyNetSendPack.tagMCActTurntableItem()
        packItem.ItemNum = num
        packItem.ItemLibType = ItemLibType_Good
        packItem.ItemID = itemID
        packItem.ItemCount = itemCount
        clientPack.GoodItemList.append(packItem)
    clientPack.GoodItemCount = len(clientPack.GoodItemList)
    clientPack.SuperItemCanChooseCount = numCountList[2] if len(numCountList) > 2 else 0
    superItemLib = GameWorld.GetDictValueByRangeKey(ipyData.GetSuperItemLib(), actWorldLV, [])
    for num, itemInfo in enumerate(superItemLib, 1):
        itemID, itemCount, _ = itemInfo
        packItem = ChPyNetSendPack.tagMCActTurntableItem()
        packItem.ItemNum = num
        packItem.ItemLibType = ItemLibType_Super
        packItem.ItemID = itemID
        packItem.ItemCount = itemCount
        clientPack.SuperItemList.append(packItem)
    clientPack.SuperItemCount = len(clientPack.SuperItemList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -71,6 +71,7 @@
import PyGameData
import PlayerMagicWeapon
import PlayerFeastTravel
import PlayerActTurntable
import GameLogic_SealDemon
import GameLogic_ZhuXianBoss
import GameLogic_CrossDemonKing
@@ -3169,9 +3170,13 @@
    #PlayerGoldAction.PlayerUseGold(curPlayer, price)
    
    # 消费返利
    PlayerCostRebate.AddCostRebateGold(curPlayer, costType, price, infoDict)
    PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_UseGold, price)
    if costType not in ChConfig.CostRebate_DisableType:
        PlayerCostRebate.AddCostRebateGold(curPlayer, costType, price, infoDict)
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_UseGold, price)
        PlayerActTurntable.OnPlayerUseGold(curPlayer, price)
    else:
        GameWorld.DebugLog("不计入消费活动的消费类型!costType=%s" % costType, curPlayer.GetPlayerID())
    # 事件汇报
    #===========================================================================
    # if costType == ChConfig.Def_Cost_BourseBuy:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -234,6 +234,7 @@
OperationActionName_FeastTravel = "ActFeastTravel" # 节日游历活动
OperationActionName_ManyDayRecharge = "ActManyDayRecharge" # 多日连充活动
OperationActionName_SingleRecharge = "ActSingleRecharge" # 单笔累充活动
OperationActionName_Turntable = "ActTurntable" # 转盘活动
#节日活动类型列表 - 该类型无视开服天,日期到了就开启
FeastOperationActionNameList = [OperationActionName_FeastWeekParty, OperationActionName_FeastRedPacket,
                                OperationActionName_RechargeRebateGold, OperationActionName_GrowupBuy,
@@ -251,6 +252,7 @@
                           OperationActionName_NewFairyCeremony, OperationActionName_LuckyTreasure,
                           OperationActionName_DailyGiftbag, OperationActionName_SingleRecharge,
                           OperationActionName_CollectWords, OperationActionName_ManyDayRecharge,
                           OperationActionName_Turntable,
                           ] + FeastOperationActionNameList
#需要记录开启活动时的世界等级的运营活动
NeedWorldLVOperationActNameList = [OperationActionName_FairyCeremony, OperationActionName_WishingWell, 
@@ -259,7 +261,7 @@
                                   OperationActionName_CostRebate, OperationActionName_FlashGiftbag,
                                   OperationActionName_SpringSale, OperationActionName_LuckyTreasure,
                                   OperationActionName_DailyGiftbag, OperationActionName_GrowupBuy,
                                   OperationActionName_WeekParty,
                                   OperationActionName_WeekParty, OperationActionName_Turntable,
                                   OperationActionName_CollectWords,
                                   OperationActionName_FeastLogin,
                                   OperationActionName_FeastWish, OperationActionName_FeastTravel,
@@ -271,6 +273,7 @@
                                   OperationActionName_FlashGiftbag, OperationActionName_CostRebate,
                                   OperationActionName_SpringSale, OperationActionName_FlashSale,
                                   OperationActionName_ManyDayRecharge, OperationActionName_SingleRecharge,
                                   OperationActionName_Turntable,
                                   ]
#跨服运营活动表名定义