From 00b076d0f6fec2844363efba8f75a1a675086e95 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 13 十一月 2023 13:14:42 +0800
Subject: [PATCH] 9912 [BT0.1]BOSS凭证(boss历练活动)

---
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py          |    8 
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                  |   73 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py               |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py               |  112 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py           |  354 +++++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py                                    |  112 ++++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                |  354 +++++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py                      |   78 +++
 ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py                                      |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                       |   16 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py             |   61 ++
 ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py                                       |    1 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py           |    3 
 PySysDB/PySysDBPY.h                                                                              |   23 
 ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardData.py                      |    4 
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                    |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActBossTrial.py |  267 ++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py |    4 
 PySysDB/PySysDBG.h                                                                               |   27 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                  |    5 
 20 files changed, 1,517 insertions(+), 8 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index 2a0c85f..85968ac 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -539,6 +539,33 @@
 	BYTE		ResetType;	//重置类型,0-0点重置;1-5点重置
 };
 
+//Boss历练活动表
+
+struct tagActBossTrial
+{
+	DWORD		_CfgID;	//配置ID
+	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
+	list		ServerGroupIDList;	//服务器ID列表
+	BYTE		ActNum;	//活动分组编号, 活动类型 * 10 + 不同界面编号
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	dict		NotifyInfoStart;	//全服提示信息 - 相对开始时间
+	dict		NotifyInfoEnd;	//全服提示信息 - 相对结束时间
+	list		NotifyInfoLoop;	//全服提示信息 - 循环广播[间隔分钟, 广播key]
+	BYTE		IsDayReset;	//是否每天重置
+	BYTE		ResetType;	//重置类型,0-0点重置;1-5点重置
+	list		TemplateIDList;	//榜单模板编号列表
+};
+
+//Boss历练榜单模版表
+
+struct tagActBossTrialTemplate
+{
+	DWORD		_TemplateID;	//模板编号
+	BYTE		Rank;	//名次
+	list		AwardItemList;	//奖励物品信息列表 [[物品ID,个数,是否拍品], ...]
+};
+
 //仙匣秘境活动时间表
 
 struct tagActXianXiaMJ
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index e45a005..6473b91 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1766,6 +1766,29 @@
 	list		ProduceGarbageRateList;	//随机产生垃圾概率饼图
 };
 
+//Boss历练活动表
+
+struct tagActBossTrial
+{
+	DWORD		_CfgID;	//配置ID
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	WORD		LVLimit;	//限制等级
+	BYTE		IsDayReset;	//是否每天重置
+	BYTE		ResetType;	//重置类型,0-0点重置;1-5点重置
+	dict		SubmitItemAwardInfo;	//提交凭证个数对应奖励
+	list		TemplateIDList;	//榜单模板编号列表
+};
+
+//Boss历练榜单模版表
+
+struct tagActBossTrialTemplate
+{
+	DWORD		_TemplateID;	//模板编号
+	BYTE		Rank;	//名次
+	list		AwardItemList;	//奖励物品信息列表 [[物品ID,个数,是否拍品], ...]
+};
+
 //仙匣秘境活动时间表
 
 struct tagActXianXiaMJ
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
index 23d9e2e..1e8b082 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -595,6 +595,7 @@
             ShareDefine.Def_BT_CharmTotal               : 100,           #魅力总榜
             ShareDefine.Def_BT_CharmWeek                : 100,           #魅力周榜
             ShareDefine.Def_BT_CharmDay                 : 100,           #魅力日榜
+            ShareDefine.Def_BT_BossTrialSubmit          : 20,            #boss凭证 (boss历练活动)
             }
 
 #排行榜保存类型(和BillboardType匹配), 默认保存, 如果不保存,可配置进去
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index cc8227f..3014e24 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -15062,6 +15062,118 @@
 
 
 #------------------------------------------------------
+# AA 24 Boss历练领奖 #tagCMActBossTrialGetAward
+
+class  tagCMActBossTrialGetAward(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("SubmitCount", c_ushort),    #领取凭证个数对应奖励
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x24
+        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 = 0x24
+        self.ActNum = 0
+        self.SubmitCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActBossTrialGetAward)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 24 Boss历练领奖 //tagCMActBossTrialGetAward:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                SubmitCount:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.SubmitCount
+                                )
+        return DumpString
+
+
+m_NAtagCMActBossTrialGetAward=tagCMActBossTrialGetAward()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActBossTrialGetAward.Cmd,m_NAtagCMActBossTrialGetAward.SubCmd))] = m_NAtagCMActBossTrialGetAward
+
+
+#------------------------------------------------------
+# AA 23 Boss历练提交凭证 #tagCMActBossTrialSubmit
+
+class  tagCMActBossTrialSubmit(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("SubmitCount", c_ushort),    #提交凭证个数
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x23
+        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 = 0x23
+        self.ActNum = 0
+        self.SubmitCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActBossTrialSubmit)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 23 Boss历练提交凭证 //tagCMActBossTrialSubmit:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                SubmitCount:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.SubmitCount
+                                )
+        return DumpString
+
+
+m_NAtagCMActBossTrialSubmit=tagCMActBossTrialSubmit()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActBossTrialSubmit.Cmd,m_NAtagCMActBossTrialSubmit.SubCmd))] = m_NAtagCMActBossTrialSubmit
+
+
+#------------------------------------------------------
 # AA 09 集字活动兑换 #tagCMActCollectWordsExchange
 
 class  tagCMActCollectWordsExchange(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index eaf1503..71137b8 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -30633,6 +30633,360 @@
 
 
 #------------------------------------------------------
+# AA 67 Boss历练活动信息 #tagMCActBossTrialInfo
+
+class  tagMCActBossTrialItem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemID", c_int),    
+                  ("ItemCount", c_ushort),    
+                  ("IsBind", c_ubyte),    
+                  ]
+
+    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.ItemID = 0
+        self.ItemCount = 0
+        self.IsBind = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActBossTrialItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 67 Boss历练活动信息 //tagMCActBossTrialInfo:
+                                ItemID:%d,
+                                ItemCount:%d,
+                                IsBind:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount,
+                                self.IsBind
+                                )
+        return DumpString
+
+
+class  tagMCActBossTrialBillard(Structure):
+    Rank = 0    #(DWORD Rank)// 名次,1-代表第一名;支持夸段,如1,3 代表第1名,第2~3名
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCActBossTrialItem> AwardItemList)// 奖励物品列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.Rank,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temAwardItemList = tagMCActBossTrialItem()
+            _pos = temAwardItemList.ReadData(_lpData, _pos)
+            self.AwardItemList.append(temAwardItemList)
+        return _pos
+
+    def Clear(self):
+        self.Rank = 0
+        self.Count = 0
+        self.AwardItemList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 1
+        for i in range(self.Count):
+            length += self.AwardItemList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.Rank)
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Rank:%d,
+                                Count:%d,
+                                AwardItemList:%s
+                                '''\
+                                %(
+                                self.Rank,
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+class  tagMCActBossTrialSubmitInfo(Structure):
+    RecordIndex = 0    #(BYTE RecordIndex)// 记录索引
+    NeedCount = 0    #(WORD NeedCount)// 所需提交个数
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCActBossTrialItem> AwardItemList)// 奖励物品列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.RecordIndex,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.NeedCount,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temAwardItemList = tagMCActBossTrialItem()
+            _pos = temAwardItemList.ReadData(_lpData, _pos)
+            self.AwardItemList.append(temAwardItemList)
+        return _pos
+
+    def Clear(self):
+        self.RecordIndex = 0
+        self.NeedCount = 0
+        self.Count = 0
+        self.AwardItemList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 1
+        length += 2
+        length += 1
+        for i in range(self.Count):
+            length += self.AwardItemList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteBYTE(data, self.RecordIndex)
+        data = CommFunc.WriteWORD(data, self.NeedCount)
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                RecordIndex:%d,
+                                NeedCount:%d,
+                                Count:%d,
+                                AwardItemList:%s
+                                '''\
+                                %(
+                                self.RecordIndex,
+                                self.NeedCount,
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+class  tagMCActBossTrialInfo(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)// 是否每天重置
+    ResetType = 0    #(BYTE ResetType)// 重置类型,0-0点重置;1-5点重置
+    LimitLV = 0    #(WORD LimitLV)// 限制等级
+    SubmitCount = 0    #(BYTE SubmitCount)
+    SubmitInfoList = list()    #(vector<tagMCActBossTrialSubmitInfo> SubmitInfoList)// 提交凭证信息列表
+    BillardCount = 0    #(BYTE BillardCount)
+    BillboardInfoList = list()    #(vector<tagMCActBossTrialBillard> BillboardInfoList)// 榜单信息列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x67
+        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.ResetType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.SubmitCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SubmitCount):
+            temSubmitInfoList = tagMCActBossTrialSubmitInfo()
+            _pos = temSubmitInfoList.ReadData(_lpData, _pos)
+            self.SubmitInfoList.append(temSubmitInfoList)
+        self.BillardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.BillardCount):
+            temBillboardInfoList = tagMCActBossTrialBillard()
+            _pos = temBillboardInfoList.ReadData(_lpData, _pos)
+            self.BillboardInfoList.append(temBillboardInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x67
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.IsDayReset = 0
+        self.ResetType = 0
+        self.LimitLV = 0
+        self.SubmitCount = 0
+        self.SubmitInfoList = list()
+        self.BillardCount = 0
+        self.BillboardInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 10
+        length += 10
+        length += 1
+        length += 1
+        length += 2
+        length += 1
+        for i in range(self.SubmitCount):
+            length += self.SubmitInfoList[i].GetLength()
+        length += 1
+        for i in range(self.BillardCount):
+            length += self.BillboardInfoList[i].GetLength()
+
+        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.WriteBYTE(data, self.ResetType)
+        data = CommFunc.WriteWORD(data, self.LimitLV)
+        data = CommFunc.WriteBYTE(data, self.SubmitCount)
+        for i in range(self.SubmitCount):
+            data = CommFunc.WriteString(data, self.SubmitInfoList[i].GetLength(), self.SubmitInfoList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.BillardCount)
+        for i in range(self.BillardCount):
+            data = CommFunc.WriteString(data, self.BillboardInfoList[i].GetLength(), self.BillboardInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                IsDayReset:%d,
+                                ResetType:%d,
+                                LimitLV:%d,
+                                SubmitCount:%d,
+                                SubmitInfoList:%s,
+                                BillardCount:%d,
+                                BillboardInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.IsDayReset,
+                                self.ResetType,
+                                self.LimitLV,
+                                self.SubmitCount,
+                                "...",
+                                self.BillardCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCActBossTrialInfo=tagMCActBossTrialInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActBossTrialInfo.Head.Cmd,m_NAtagMCActBossTrialInfo.Head.SubCmd))] = m_NAtagMCActBossTrialInfo
+
+
+#------------------------------------------------------
+# AA 68 Boss历练活动玩家信息 #tagMCActBossTrialPlayerInfo
+
+class  tagMCActBossTrialPlayerInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    # 活动编号
+                  ("SubmitCount", c_ushort),    # 已提交凭证个数
+                  ("SubmitCountAward", c_int),    # 提交凭证奖励领奖状态
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x68
+        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 = 0x68
+        self.ActNum = 0
+        self.SubmitCount = 0
+        self.SubmitCountAward = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActBossTrialPlayerInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 68 Boss历练活动玩家信息 //tagMCActBossTrialPlayerInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                SubmitCount:%d,
+                                SubmitCountAward:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.SubmitCount,
+                                self.SubmitCountAward
+                                )
+        return DumpString
+
+
+m_NAtagMCActBossTrialPlayerInfo=tagMCActBossTrialPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActBossTrialPlayerInfo.Cmd,m_NAtagMCActBossTrialPlayerInfo.SubCmd))] = m_NAtagMCActBossTrialPlayerInfo
+
+
+#------------------------------------------------------
 # AA 65 买一送多活动信息 #tagMCActBuyOneInfo
 
 class  tagMCActBuyOneInfoFreeItem(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardData.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardData.py
index 00735e4..62f6ba8 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/BillboardData.py
@@ -27,8 +27,8 @@
     GameWorld.DebugAnswer(curPlayer, "删除榜单假数据: BillboardData 类型")
     GameWorld.DebugAnswer(curPlayer, "榜单类型:0-战力,1-龙魂,2-灵瑶,4-等级,5-坐骑,6-灵宠,7-符印,8-脱机,9-境界,19-助战")
     GameWorld.DebugAnswer(curPlayer, "开服活动榜类型:11-强化,12-坐骑,13-宝石,14-冲级,15-境界,16-战力,18-符印,20-神兵,21-充值,22-灵宠,24-灵根,25-升星")
-    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:17-仙界盛典,23-仙界盛典2")
-    GameWorld.DebugAnswer(curPlayer, "魅力榜单类型:30-总榜,31-周榜,31-日榜")
+    GameWorld.DebugAnswer(curPlayer, "运营活动榜类型:17-仙界盛典,23-仙界盛典2,33-boss凭证")
+    GameWorld.DebugAnswer(curPlayer, "魅力榜单类型:30-总榜,31-周榜,32-日榜")
     return
 
 ## 执行逻辑
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
index 721975c..c6504ef 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -538,6 +538,13 @@
 
 #---------------------------------------------------------------------
 
+def GetTemplateID(ipyData, cfgID, dayIndex):
+    if cfgID == None or dayIndex == None or not ipyData:
+        return 0
+    templateIDList = ipyData.GetTemplateIDList()
+    templateID = templateIDList[-1] if dayIndex >= len(templateIDList) else templateIDList[dayIndex]
+    return templateID
+
 def GetOperationActionDateStr(ipyData):
     ## 获取运营活动对应日期,存数字代表开服天配置,需要转化为对应的日期
     curDateTime = datetime.datetime.today()
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
index ae845c1..f8a3320 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -34,6 +34,7 @@
 import PlayerFairyCeremony
 import PlayerNewFairyCeremony
 import PlayerActGarbageSorting
+import PlayerActBossTrial
 import PlayerUniversalGameRec
 import GameWorldAverageLv
 import PlayerFamilyBoss
@@ -776,6 +777,11 @@
                 GameWorld.Log("    dbActID变更: dbActID=%s,curActID=%s" % (dbActID, curActID))
                 PlayerDBGSEvent.SetDBGSTrig_ByKey(dbOperationActIDKey, curActID)
                 
+                # 结束旧的
+                if dbActID:
+                    if actName == ShareDefine.OperationActionName_BossTrial:
+                        PlayerActBossTrial.OnActEnd(actNum, ipyData, dayIndex)
+                        
                 if curActID:
                     if actName in ShareDefine.NeedWorldLVOperationActNameList:
                         #记录开启时世界等级
@@ -803,6 +809,8 @@
                         PlayerStore.ResetFlashSaleBuyCnt(ipyData)
                     elif actName == ShareDefine.OperationActionName_GarbageSorting:
                         PlayerActGarbageSorting.OnActStart(actNum)
+                    elif actName == ShareDefine.OperationActionName_BossTrial:
+                        PlayerActBossTrial.OnActStart(actNum)
                 else:
                     if actName == ShareDefine.OperationActionName_GarbageSorting:
                         PlayerActGarbageSorting.OnActEnd(actNum)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index 2d96800..74c8c16 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -449,6 +449,27 @@
                         ("BYTE", "ResetType", 0),
                         ),
 
+                "ActBossTrial":(
+                        ("DWORD", "CfgID", 1),
+                        ("list", "PlatformList", 0),
+                        ("list", "ServerGroupIDList", 0),
+                        ("BYTE", "ActNum", 0),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("dict", "NotifyInfoStart", 0),
+                        ("dict", "NotifyInfoEnd", 0),
+                        ("list", "NotifyInfoLoop", 0),
+                        ("BYTE", "IsDayReset", 0),
+                        ("BYTE", "ResetType", 0),
+                        ("list", "TemplateIDList", 0),
+                        ),
+
+                "ActBossTrialTemplate":(
+                        ("DWORD", "TemplateID", 1),
+                        ("BYTE", "Rank", 0),
+                        ("list", "AwardItemList", 0),
+                        ),
+
                 "ActXianXiaMJ":(
                         ("DWORD", "CfgID", 1),
                         ("list", "PlatformList", 0),
@@ -1796,6 +1817,50 @@
     def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
     def GetResetType(self): return self.ResetType # 重置类型,0-0点重置;1-5点重置
 
+# Boss历练活动表
+class IPY_ActBossTrial():
+    
+    def __init__(self):
+        self.CfgID = 0
+        self.PlatformList = []
+        self.ServerGroupIDList = []
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndDate = ""
+        self.NotifyInfoStart = {}
+        self.NotifyInfoEnd = {}
+        self.NotifyInfoLoop = []
+        self.IsDayReset = 0
+        self.ResetType = 0
+        self.TemplateIDList = []
+        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 GetNotifyInfoStart(self): return self.NotifyInfoStart # 全服提示信息 - 相对开始时间
+    def GetNotifyInfoEnd(self): return self.NotifyInfoEnd # 全服提示信息 - 相对结束时间
+    def GetNotifyInfoLoop(self): return self.NotifyInfoLoop # 全服提示信息 - 循环广播[间隔分钟, 广播key]
+    def GetIsDayReset(self): return self.IsDayReset # 是否每天重置
+    def GetResetType(self): return self.ResetType # 重置类型,0-0点重置;1-5点重置
+    def GetTemplateIDList(self): return self.TemplateIDList # 榜单模板编号列表
+
+# Boss历练榜单模版表
+class IPY_ActBossTrialTemplate():
+    
+    def __init__(self):
+        self.TemplateID = 0
+        self.Rank = 0
+        self.AwardItemList = []
+        return
+        
+    def GetTemplateID(self): return self.TemplateID # 模板编号
+    def GetRank(self): return self.Rank # 名次
+    def GetAwardItemList(self): return self.AwardItemList # 奖励物品信息列表 [[物品ID,个数,是否拍品], ...]
+
 # 仙匣秘境活动时间表
 class IPY_ActXianXiaMJ():
     
@@ -2886,6 +2951,10 @@
         self.ipyActCollectWordsLen = len(self.ipyActCollectWordsCache)
         self.ipyActGarbageSortingCache = self.__LoadFileData("ActGarbageSorting", IPY_ActGarbageSorting)
         self.ipyActGarbageSortingLen = len(self.ipyActGarbageSortingCache)
+        self.ipyActBossTrialCache = self.__LoadFileData("ActBossTrial", IPY_ActBossTrial)
+        self.ipyActBossTrialLen = len(self.ipyActBossTrialCache)
+        self.ipyActBossTrialTemplateCache = self.__LoadFileData("ActBossTrialTemplate", IPY_ActBossTrialTemplate)
+        self.ipyActBossTrialTemplateLen = len(self.ipyActBossTrialTemplateCache)
         self.ipyActXianXiaMJCache = self.__LoadFileData("ActXianXiaMJ", IPY_ActXianXiaMJ)
         self.ipyActXianXiaMJLen = len(self.ipyActXianXiaMJCache)
         self.ipyActGodGiftCache = self.__LoadFileData("ActGodGift", IPY_ActGodGift)
@@ -3222,6 +3291,10 @@
     def GetActCollectWordsByIndex(self, index): return self.ipyActCollectWordsCache[index]
     def GetActGarbageSortingCount(self): return self.ipyActGarbageSortingLen
     def GetActGarbageSortingByIndex(self, index): return self.ipyActGarbageSortingCache[index]
+    def GetActBossTrialCount(self): return self.ipyActBossTrialLen
+    def GetActBossTrialByIndex(self, index): return self.ipyActBossTrialCache[index]
+    def GetActBossTrialTemplateCount(self): return self.ipyActBossTrialTemplateLen
+    def GetActBossTrialTemplateByIndex(self, index): return self.ipyActBossTrialTemplateCache[index]
     def GetActXianXiaMJCount(self): return self.ipyActXianXiaMJLen
     def GetActXianXiaMJByIndex(self, index): return self.ipyActXianXiaMJCache[index]
     def GetActGodGiftCount(self): return self.ipyActGodGiftLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py
new file mode 100644
index 0000000..b2bce75
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PlayerActBossTrial
+#
+# @todo:boss历练
+# @author hxp
+# @date 2023-10-20
+# @version 1.0
+#
+# 详细描述: boss历练
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2023-10-20 16:00"""
+#-------------------------------------------------------------------------------
+
+import ShareDefine
+import DataRecordPack
+import PlayerCompensation
+import PlayerBillboard
+import IpyGameDataPY
+import GameWorld
+
+BillboardType = ShareDefine.Def_BT_BossTrialSubmit
+
+def OnActStart(actNum):
+    ## 活动开启
+    PlayerBillboard.ClearBillboardByIndex(BillboardType)
+    return
+
+def OnActEnd(actNum, ipyData, dayIndex):
+    ## 活动结束
+    cfgID = ipyData.GetCfgID() if ipyData else 0
+    # 发放排行奖励
+    GameWorld.Log("=== boss历练活动结束!发放榜单奖励! === actNum=%s,cfgID=%s,dayIndex=%s" % (actNum, cfgID, dayIndex))
+    if not cfgID:
+        return
+    billBoard = GameWorld.GetBillboard().FindBillboard(BillboardType)
+    if not billBoard:
+        return
+    templateID = GameWorld.GetTemplateID(ipyData, cfgID, dayIndex)
+    if not templateID:
+        return
+    tempIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActBossTrialTemplate", templateID)
+    if not tempIpyDataList:
+        return
+    
+    rankAwardDict = {}
+    for tempIpyData in tempIpyDataList:
+        rankAwardDict[tempIpyData.GetRank()] = tempIpyData.GetAwardItemList()
+        
+    GameWorld.Log("    templateID=%s,rankAwardDict=%s" % (templateID, rankAwardDict))
+    billBoard.Sort()
+    for index in xrange(billBoard.GetCount()):
+        billBoardData = billBoard.At(index)
+        if not billBoardData:
+            continue
+        
+        rank = index + 1
+        
+        awardItemList = GameWorld.GetOrderValueByDict(rankAwardDict, rank, False)
+        if not awardItemList:
+            break
+        
+        playerID = billBoardData.GetID()
+        name2 = billBoardData.GetName2()
+        cmpValue = billBoardData.GetCmpValue()
+        
+        GameWorld.Log("    发放boss历练榜单奖励: rank=%s,playerID=%s,cmpValue=%s,awardItemList=%s, %s" 
+                      % (rank, playerID, cmpValue, awardItemList, name2))
+        
+        PlayerCompensation.SendMailByKey("BossTrialMail%s" % actNum, [playerID], awardItemList, [rank])
+        
+    DataRecordPack.DR_BillboardData(BillboardType, "BossTrial", {"actNum":actNum, "cfgID":cfgID, "dayIndex":dayIndex, "templateID":templateID})
+    PlayerBillboard.ClearBillboardByIndex(BillboardType)
+    GameWorld.Log("=================================================================================")
+    return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 90b0787..1e462d0 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -286,6 +286,7 @@
 OperationActionName_XianXiaMJ = "ActXianXiaMJ" # 仙匣秘境活动
 OperationActionName_GodGift = "ActGodGift" # 天帝礼包活动
 OperationActionName_BuyOne = "ActBuyOne" # 买一送多活动
+OperationActionName_BossTrial = "ActBossTrial" # Boss历练
 #节日活动类型列表 - 该类型无视开服天,日期到了就开启
 FeastOperationActionNameList = [OperationActionName_FeastWeekParty, OperationActionName_FeastRedPacket,
                                 OperationActionName_RechargeRebateGold, OperationActionName_GrowupBuy,
@@ -305,7 +306,7 @@
                            OperationActionName_CollectWords, OperationActionName_ManyDayRecharge,
                            OperationActionName_Turntable, OperationActionName_HorsePetFeast, OperationActionName_GarbageSorting,
                            OperationActionName_XianXiaMJ, OperationActionName_GodGift,
-                           OperationActionName_BuyOne,
+                           OperationActionName_BuyOne, OperationActionName_BossTrial,
                            ] + FeastOperationActionNameList
 #需要记录开启活动时的世界等级的运营活动
 NeedWorldLVOperationActNameList = [OperationActionName_FairyCeremony, OperationActionName_WishingWell, 
@@ -329,7 +330,7 @@
                                    OperationActionName_ManyDayRecharge, OperationActionName_SingleRecharge,
                                    OperationActionName_Turntable, OperationActionName_HorsePetFeast, OperationActionName_GarbageSorting,
                                    OperationActionName_XianXiaMJ, OperationActionName_GodGift,
-                                   OperationActionName_BuyOne,
+                                   OperationActionName_BuyOne, OperationActionName_BossTrial,
                                    ]
 
 #跨服运营活动表名定义
@@ -794,9 +795,10 @@
     Def_BT_CharmTotal, #魅力总榜 30
     Def_BT_CharmWeek, #魅力周榜
     Def_BT_CharmDay, #魅力日榜
+    Def_BT_BossTrialSubmit,                   #提交boss凭证榜 (boss历练活动)
     
     Def_BT_Max, #排行榜最大类型
-) = range(0, 32 + 2) 
+) = range(0, 33 + 2) 
 
 ''' 跨服排行榜类型, 从 150 开始
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index bc2e56f..07ad34e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1553,6 +1553,22 @@
 PacketSubCMD_2=0x06
 PacketCallFunc_2=OnActWishingDrag
 
+;boss历练活动
+[PlayerActBossTrial]
+ScriptName = Player\PlayerActBossTrial.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 2
+
+PacketCMD_1=0xAA
+PacketSubCMD_1=0x23
+PacketCallFunc_1=OnActBossTrialSubmit
+
+PacketCMD_2=0xAA
+PacketSubCMD_2=0x24
+PacketCallFunc_2=OnActBossTrialGetAward
+
 ;垃圾分类活动
 [PlayerActGarbageSorting]
 ScriptName = Player\PlayerActGarbageSorting.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 813fe93..7533117 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3964,6 +3964,11 @@
 #诛仙BOSS
 Def_PDict_ZhuXianBossHelpCnt = "ZhuXianBossHelpCnt"  # 协助次数
 
+#boss历练
+Def_PDict_BossTrialID = "BossTrialID_%s"  # 玩家身上的活动ID,唯一标识,取活动开始日期time,参数(活动编号)
+Def_PDict_BossTrialSubmitCount = "BossTrialSubmitCount_%s"  # 提交凭证物品个数,参数(活动编号)
+Def_PDict_BossTrialSubmitAward = "BossTrialSubmitAward_%s"  # 提交凭证奖励状态,参数(活动编号)
+
 #幸运鉴宝
 Def_PDict_LuckyTreasureID = "LuckyTreasureID"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值
 Def_PDict_LuckyTreasureFree = "LuckyTreasureFree" #是否免费过
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index cc8227f..3014e24 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -15062,6 +15062,118 @@
 
 
 #------------------------------------------------------
+# AA 24 Boss历练领奖 #tagCMActBossTrialGetAward
+
+class  tagCMActBossTrialGetAward(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("SubmitCount", c_ushort),    #领取凭证个数对应奖励
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x24
+        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 = 0x24
+        self.ActNum = 0
+        self.SubmitCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActBossTrialGetAward)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 24 Boss历练领奖 //tagCMActBossTrialGetAward:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                SubmitCount:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.SubmitCount
+                                )
+        return DumpString
+
+
+m_NAtagCMActBossTrialGetAward=tagCMActBossTrialGetAward()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActBossTrialGetAward.Cmd,m_NAtagCMActBossTrialGetAward.SubCmd))] = m_NAtagCMActBossTrialGetAward
+
+
+#------------------------------------------------------
+# AA 23 Boss历练提交凭证 #tagCMActBossTrialSubmit
+
+class  tagCMActBossTrialSubmit(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    #活动编号
+                  ("SubmitCount", c_ushort),    #提交凭证个数
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x23
+        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 = 0x23
+        self.ActNum = 0
+        self.SubmitCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMActBossTrialSubmit)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 23 Boss历练提交凭证 //tagCMActBossTrialSubmit:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                SubmitCount:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.SubmitCount
+                                )
+        return DumpString
+
+
+m_NAtagCMActBossTrialSubmit=tagCMActBossTrialSubmit()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMActBossTrialSubmit.Cmd,m_NAtagCMActBossTrialSubmit.SubCmd))] = m_NAtagCMActBossTrialSubmit
+
+
+#------------------------------------------------------
 # AA 09 集字活动兑换 #tagCMActCollectWordsExchange
 
 class  tagCMActCollectWordsExchange(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index eaf1503..71137b8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -30633,6 +30633,360 @@
 
 
 #------------------------------------------------------
+# AA 67 Boss历练活动信息 #tagMCActBossTrialInfo
+
+class  tagMCActBossTrialItem(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemID", c_int),    
+                  ("ItemCount", c_ushort),    
+                  ("IsBind", c_ubyte),    
+                  ]
+
+    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.ItemID = 0
+        self.ItemCount = 0
+        self.IsBind = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActBossTrialItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 67 Boss历练活动信息 //tagMCActBossTrialInfo:
+                                ItemID:%d,
+                                ItemCount:%d,
+                                IsBind:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount,
+                                self.IsBind
+                                )
+        return DumpString
+
+
+class  tagMCActBossTrialBillard(Structure):
+    Rank = 0    #(DWORD Rank)// 名次,1-代表第一名;支持夸段,如1,3 代表第1名,第2~3名
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCActBossTrialItem> AwardItemList)// 奖励物品列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.Rank,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temAwardItemList = tagMCActBossTrialItem()
+            _pos = temAwardItemList.ReadData(_lpData, _pos)
+            self.AwardItemList.append(temAwardItemList)
+        return _pos
+
+    def Clear(self):
+        self.Rank = 0
+        self.Count = 0
+        self.AwardItemList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 1
+        for i in range(self.Count):
+            length += self.AwardItemList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.Rank)
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Rank:%d,
+                                Count:%d,
+                                AwardItemList:%s
+                                '''\
+                                %(
+                                self.Rank,
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+class  tagMCActBossTrialSubmitInfo(Structure):
+    RecordIndex = 0    #(BYTE RecordIndex)// 记录索引
+    NeedCount = 0    #(WORD NeedCount)// 所需提交个数
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCActBossTrialItem> AwardItemList)// 奖励物品列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.RecordIndex,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.NeedCount,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temAwardItemList = tagMCActBossTrialItem()
+            _pos = temAwardItemList.ReadData(_lpData, _pos)
+            self.AwardItemList.append(temAwardItemList)
+        return _pos
+
+    def Clear(self):
+        self.RecordIndex = 0
+        self.NeedCount = 0
+        self.Count = 0
+        self.AwardItemList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 1
+        length += 2
+        length += 1
+        for i in range(self.Count):
+            length += self.AwardItemList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteBYTE(data, self.RecordIndex)
+        data = CommFunc.WriteWORD(data, self.NeedCount)
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.AwardItemList[i].GetLength(), self.AwardItemList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                RecordIndex:%d,
+                                NeedCount:%d,
+                                Count:%d,
+                                AwardItemList:%s
+                                '''\
+                                %(
+                                self.RecordIndex,
+                                self.NeedCount,
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+class  tagMCActBossTrialInfo(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)// 是否每天重置
+    ResetType = 0    #(BYTE ResetType)// 重置类型,0-0点重置;1-5点重置
+    LimitLV = 0    #(WORD LimitLV)// 限制等级
+    SubmitCount = 0    #(BYTE SubmitCount)
+    SubmitInfoList = list()    #(vector<tagMCActBossTrialSubmitInfo> SubmitInfoList)// 提交凭证信息列表
+    BillardCount = 0    #(BYTE BillardCount)
+    BillboardInfoList = list()    #(vector<tagMCActBossTrialBillard> BillboardInfoList)// 榜单信息列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x67
+        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.ResetType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.SubmitCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.SubmitCount):
+            temSubmitInfoList = tagMCActBossTrialSubmitInfo()
+            _pos = temSubmitInfoList.ReadData(_lpData, _pos)
+            self.SubmitInfoList.append(temSubmitInfoList)
+        self.BillardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.BillardCount):
+            temBillboardInfoList = tagMCActBossTrialBillard()
+            _pos = temBillboardInfoList.ReadData(_lpData, _pos)
+            self.BillboardInfoList.append(temBillboardInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x67
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.IsDayReset = 0
+        self.ResetType = 0
+        self.LimitLV = 0
+        self.SubmitCount = 0
+        self.SubmitInfoList = list()
+        self.BillardCount = 0
+        self.BillboardInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 10
+        length += 10
+        length += 1
+        length += 1
+        length += 2
+        length += 1
+        for i in range(self.SubmitCount):
+            length += self.SubmitInfoList[i].GetLength()
+        length += 1
+        for i in range(self.BillardCount):
+            length += self.BillboardInfoList[i].GetLength()
+
+        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.WriteBYTE(data, self.ResetType)
+        data = CommFunc.WriteWORD(data, self.LimitLV)
+        data = CommFunc.WriteBYTE(data, self.SubmitCount)
+        for i in range(self.SubmitCount):
+            data = CommFunc.WriteString(data, self.SubmitInfoList[i].GetLength(), self.SubmitInfoList[i].GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.BillardCount)
+        for i in range(self.BillardCount):
+            data = CommFunc.WriteString(data, self.BillboardInfoList[i].GetLength(), self.BillboardInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                IsDayReset:%d,
+                                ResetType:%d,
+                                LimitLV:%d,
+                                SubmitCount:%d,
+                                SubmitInfoList:%s,
+                                BillardCount:%d,
+                                BillboardInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.IsDayReset,
+                                self.ResetType,
+                                self.LimitLV,
+                                self.SubmitCount,
+                                "...",
+                                self.BillardCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCActBossTrialInfo=tagMCActBossTrialInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActBossTrialInfo.Head.Cmd,m_NAtagMCActBossTrialInfo.Head.SubCmd))] = m_NAtagMCActBossTrialInfo
+
+
+#------------------------------------------------------
+# AA 68 Boss历练活动玩家信息 #tagMCActBossTrialPlayerInfo
+
+class  tagMCActBossTrialPlayerInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    # 活动编号
+                  ("SubmitCount", c_ushort),    # 已提交凭证个数
+                  ("SubmitCountAward", c_int),    # 提交凭证奖励领奖状态
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x68
+        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 = 0x68
+        self.ActNum = 0
+        self.SubmitCount = 0
+        self.SubmitCountAward = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActBossTrialPlayerInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 68 Boss历练活动玩家信息 //tagMCActBossTrialPlayerInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                SubmitCount:%d,
+                                SubmitCountAward:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.SubmitCount,
+                                self.SubmitCountAward
+                                )
+        return DumpString
+
+
+m_NAtagMCActBossTrialPlayerInfo=tagMCActBossTrialPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActBossTrialPlayerInfo.Cmd,m_NAtagMCActBossTrialPlayerInfo.SubCmd))] = m_NAtagMCActBossTrialPlayerInfo
+
+
+#------------------------------------------------------
 # AA 65 买一送多活动信息 #tagMCActBuyOneInfo
 
 class  tagMCActBuyOneInfoFreeItem(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index b721f29..1f32797 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1400,6 +1400,23 @@
                         ("list", "ProduceGarbageRateList", 0),
                         ),
 
+                "ActBossTrial":(
+                        ("DWORD", "CfgID", 1),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("WORD", "LVLimit", 0),
+                        ("BYTE", "IsDayReset", 0),
+                        ("BYTE", "ResetType", 0),
+                        ("dict", "SubmitItemAwardInfo", 0),
+                        ("list", "TemplateIDList", 0),
+                        ),
+
+                "ActBossTrialTemplate":(
+                        ("DWORD", "TemplateID", 1),
+                        ("BYTE", "Rank", 0),
+                        ("list", "AwardItemList", 0),
+                        ),
+
                 "ActXianXiaMJ":(
                         ("DWORD", "CfgID", 1),
                         ("char", "StartDate", 0),
@@ -5050,6 +5067,42 @@
     def GetAutoProduce(self): return self.AutoProduce # 自动产生垃圾
     def GetProduceGarbageRateList(self): return self.ProduceGarbageRateList # 随机产生垃圾概率饼图
 
+# Boss历练活动表
+class IPY_ActBossTrial():
+    
+    def __init__(self):
+        self.CfgID = 0
+        self.StartDate = ""
+        self.EndDate = ""
+        self.LVLimit = 0
+        self.IsDayReset = 0
+        self.ResetType = 0
+        self.SubmitItemAwardInfo = {}
+        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 GetResetType(self): return self.ResetType # 重置类型,0-0点重置;1-5点重置
+    def GetSubmitItemAwardInfo(self): return self.SubmitItemAwardInfo # 提交凭证个数对应奖励
+    def GetTemplateIDList(self): return self.TemplateIDList # 榜单模板编号列表
+
+# Boss历练榜单模版表
+class IPY_ActBossTrialTemplate():
+    
+    def __init__(self):
+        self.TemplateID = 0
+        self.Rank = 0
+        self.AwardItemList = []
+        return
+        
+    def GetTemplateID(self): return self.TemplateID # 模板编号
+    def GetRank(self): return self.Rank # 名次
+    def GetAwardItemList(self): return self.AwardItemList # 奖励物品信息列表 [[物品ID,个数,是否拍品], ...]
+
 # 仙匣秘境活动时间表
 class IPY_ActXianXiaMJ():
     
@@ -6992,6 +7045,10 @@
         self.ipyActGarbageSortingLen = len(self.ipyActGarbageSortingCache)
         self.ipyActGarbageTaskCache = self.__LoadFileData("ActGarbageTask", IPY_ActGarbageTask)
         self.ipyActGarbageTaskLen = len(self.ipyActGarbageTaskCache)
+        self.ipyActBossTrialCache = self.__LoadFileData("ActBossTrial", IPY_ActBossTrial)
+        self.ipyActBossTrialLen = len(self.ipyActBossTrialCache)
+        self.ipyActBossTrialTemplateCache = self.__LoadFileData("ActBossTrialTemplate", IPY_ActBossTrialTemplate)
+        self.ipyActBossTrialTemplateLen = len(self.ipyActBossTrialTemplateCache)
         self.ipyActXianXiaMJCache = self.__LoadFileData("ActXianXiaMJ", IPY_ActXianXiaMJ)
         self.ipyActXianXiaMJLen = len(self.ipyActXianXiaMJCache)
         self.ipyActXianXiaMJAwardCache = self.__LoadFileData("ActXianXiaMJAward", IPY_ActXianXiaMJAward)
@@ -7604,6 +7661,10 @@
     def GetActGarbageSortingByIndex(self, index): return self.ipyActGarbageSortingCache[index]
     def GetActGarbageTaskCount(self): return self.ipyActGarbageTaskLen
     def GetActGarbageTaskByIndex(self, index): return self.ipyActGarbageTaskCache[index]
+    def GetActBossTrialCount(self): return self.ipyActBossTrialLen
+    def GetActBossTrialByIndex(self, index): return self.ipyActBossTrialCache[index]
+    def GetActBossTrialTemplateCount(self): return self.ipyActBossTrialTemplateLen
+    def GetActBossTrialTemplateByIndex(self, index): return self.ipyActBossTrialTemplateCache[index]
     def GetActXianXiaMJCount(self): return self.ipyActXianXiaMJLen
     def GetActXianXiaMJByIndex(self, index): return self.ipyActXianXiaMJCache[index]
     def GetActXianXiaMJAwardCount(self): return self.ipyActXianXiaMJAwardLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index 9d24aa1..9b31933 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -117,6 +117,7 @@
 import PlayerActManyDayRecharge
 import PlayerActSingleRecharge
 import PlayerActHorsePetFeast
+import PlayerActBossTrial
 import PlayerSpringSale
 import PlayerFairyCeremony
 import PlayerNewFairyCeremony
@@ -851,6 +852,8 @@
     PlayerFreeGoods.OnLogin(curPlayer)
     # BOSS复活活动
     PlayerBossReborn.OnLogin(curPlayer)
+    # boss历练
+    PlayerActBossTrial.OnPlayerLogin(curPlayer)
     # 骑宠盛宴活动
     PlayerActHorsePetFeast.OnLogin(curPlayer)
     # 周狂欢活动
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActBossTrial.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActBossTrial.py
new file mode 100644
index 0000000..9ed125d
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActBossTrial.py
@@ -0,0 +1,267 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerActBossTrial
+#
+# @todo:boss历练
+# @author hxp
+# @date 2023-10-20
+# @version 1.0
+#
+# 详细描述: boss历练
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2023-10-20 16:00"""
+#-------------------------------------------------------------------------------
+
+import PyGameData
+import ItemCommon
+import ShareDefine
+import PlayerControl
+import IpyGameDataPY
+import ChPyNetSendPack
+import PlayerBillboard
+import ItemControler
+import NetPackCommon
+import IPY_GameWorld
+import GameWorld
+import ChConfig
+
+def OnPlayerLogin(curPlayer):
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_BossTrial, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        isReset = __CheckPlayerBossTrialAction(curPlayer, actNum)
+        # 活动中同步活动信息
+        if not isReset and actInfo.get(ShareDefine.ActKey_State):
+            Sync_BossTrialActionInfo(curPlayer, actNum)
+            Sync_BossTrialPlayerInfo(curPlayer, actNum)
+            
+    return
+
+def RefreshBossTrialActionInfo(actNum):
+    ## 收到GameServer同步的活动信息,刷新活动信息
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(index)
+        if curPlayer.GetID() == 0:
+            continue
+        __CheckPlayerBossTrialAction(curPlayer, actNum)
+    return
+
+def __CheckPlayerBossTrialAction(curPlayer, actNum):
+    ## 检查玩活动数据信息
+    
+    playerID = curPlayer.GetPlayerID()
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_BossTrial, actNum)
+    actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+    state = actInfo.get(ShareDefine.ActKey_State, 0)
+    
+    playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BossTrialID % actNum) # 玩家身上的活动ID
+    
+    # 活动ID 相同的话不处理
+    if actID == playerActID:
+        GameWorld.DebugLog("Boss历练活动ID不变,不处理! actID=%s" % actID, curPlayer.GetPlayerID())
+        return
+    GameWorld.DebugLog("Boss历练活动重置! actID=%s,playerActID=%s,state=%s" % (actID, playerActID, state), playerID)
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BossTrialID % actNum, actID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BossTrialSubmitCount % actNum, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BossTrialSubmitAward % actNum, 0)
+    
+    if state:
+        Sync_BossTrialActionInfo(curPlayer, actNum)
+        Sync_BossTrialPlayerInfo(curPlayer, actNum)
+        
+    return True
+
+#// AA 23 Boss历练提交凭证 #tagCMActBossTrialSubmit
+#
+#struct    tagCMActBossTrialSubmit
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#    WORD        SubmitCount;    //提交凭证个数
+#};
+def OnActBossTrialSubmit(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    submitCount = clientData.SubmitCount
+    
+    playerID = curPlayer.GetPlayerID()
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_BossTrial, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        GameWorld.DebugLog("Boss历练非活动中: actNum=%s" % actNum, playerID)
+        return
+    
+    itemID = IpyGameDataPY.GetFuncCfg("BossTrial", 1)
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList({itemID:submitCount}, itemPack)
+    if lackItemDict:
+        GameWorld.DebugLog("Boss历练提交凭证物品不足! actNum=%s,itemID=%s,submitCount=%s,lackItemDict=%s" % (actNum, itemID, submitCount, lackItemDict), playerID)
+        return
+    ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "BossTrialSubmit")
+    
+    nowSubmitCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BossTrialSubmitCount % actNum)
+    updSubmitCount = nowSubmitCount + submitCount    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BossTrialSubmitCount % actNum, updSubmitCount)
+    GameWorld.DebugLog("Boss历练提交凭证: actNum=%s,itemID=%s,submitCount=%s,updSubmitCount=%s" % (actNum, itemID, submitCount, updSubmitCount), playerID)
+    
+    PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_BossTrialSubmit, updSubmitCount)
+    
+    Sync_BossTrialPlayerInfo(curPlayer, actNum)
+    return
+
+#// AA 24 Boss历练领奖 #tagCMActBossTrialGetAward
+#
+#struct    tagCMActBossTrialGetAward
+#{
+#    tagHead        Head;
+#    BYTE        ActNum;        //活动编号
+#    WORD        SubmitCount;    //领取凭证个数对应奖励
+#};
+def OnActBossTrialGetAward(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    actNum = clientData.ActNum
+    submitCount = clientData.SubmitCount
+    
+    playerID = curPlayer.GetPlayerID()
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_BossTrial, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        GameWorld.DebugLog("Boss历练非活动中: actNum=%s" % actNum, playerID)
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActBossTrial", cfgID)
+    if not ipyData:
+        return
+    submitItemAwardInfo = ipyData.GetSubmitItemAwardInfo()
+    if submitCount not in submitItemAwardInfo:
+        GameWorld.DebugLog("Boss历练没有该奖励: actNum=%s,submitCount=%s not in %s" % (actNum, submitCount, submitItemAwardInfo.keys()), playerID)
+        return
+    recordIndex, awardItemList = submitItemAwardInfo[submitCount]
+    
+    nowSubmitCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BossTrialSubmitCount % actNum)
+    if nowSubmitCount < submitCount:
+        GameWorld.DebugLog("Boss历练提交凭证个数不足,无法领奖: actNum=%s,nowSubmitCount=%s < %s" % (actNum, nowSubmitCount, submitCount), playerID)
+        return
+    
+    awardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BossTrialSubmitAward % actNum)
+    if awardState & pow(2, recordIndex):
+        GameWorld.DebugLog("Boss历练领奖已领取过: actNum=%s,submitCount=%s,recordIndex=%s,awardState=%s" % (actNum, submitCount, recordIndex, awardState), playerID)
+        return
+    updAwardState = awardState | pow(2, recordIndex)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BossTrialSubmitAward % actNum, updAwardState)
+    GameWorld.DebugLog("Boss历练领奖: actNum=%s,submitCount=%s,recordIndex=%s,awardState=%s,updAwardState=%s" 
+                       % (actNum, submitCount, recordIndex, awardState, updAwardState), playerID)
+    
+    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["BossTrial", False, {}])
+    Sync_BossTrialPlayerInfo(curPlayer, actNum)
+    return
+
+def GetBossTrialDropItemIDList(curPlayer, limitIndex):
+    bossIndexList = IpyGameDataPY.GetFuncEvalCfg("BossTrial", 2)
+    if limitIndex not in bossIndexList:
+        return
+    
+    dropCountTotal = 0
+    itemID = IpyGameDataPY.GetFuncCfg("BossTrial", 1)
+    dropCountRateList = IpyGameDataPY.GetFuncEvalCfg("BossTrial", 3)
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_BossTrial, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        if not actInfo.get(ShareDefine.ActKey_State):
+            GameWorld.DebugLog("Boss历练非活动中,不掉落! actNum=%s" % actNum)
+            continue
+        dropCount = GameWorld.GetResultByRandomList(dropCountRateList)
+        if not dropCount:
+            continue
+        dropCountTotal += dropCount
+        
+    return itemID, dropCountTotal
+
+def Sync_BossTrialPlayerInfo(curPlayer, actNum):
+    ## 通知玩家数据信息
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_BossTrial, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    clientPack = ChPyNetSendPack.tagMCActBossTrialPlayerInfo()
+    clientPack.ActNum = actNum
+    clientPack.SubmitCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BossTrialSubmitCount % actNum)
+    clientPack.SubmitCountAward = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BossTrialSubmitAward % actNum)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def Sync_BossTrialActionInfo(curPlayer, actNum):
+    ## 通知活动信息
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_BossTrial, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActBossTrial", cfgID)
+    if not ipyData:
+        return
+    templateID = GameWorld.GetTemplateID(ipyData, cfgID, dayIndex)
+    if not templateID:
+        return
+    tempIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActBossTrialTemplate", templateID)
+    if not tempIpyDataList:
+        return
+    
+    startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)
+    startDateSync = actInfo.get(ShareDefine.ActKey_StartDateSync, startDateStr)
+    actInfo = ChPyNetSendPack.tagMCActBossTrialInfo()
+    actInfo.ActNum = actNum
+    actInfo.StartDate = startDateSync
+    actInfo.EndtDate = endDateStr
+    actInfo.IsDayReset = ipyData.GetIsDayReset()
+    actInfo.ResetType = ipyData.GetResetType()
+    actInfo.LimitLV = ipyData.GetLVLimit()
+    
+    actInfo.SubmitInfoList = []
+    submitItemAwardInfo = ipyData.GetSubmitItemAwardInfo()
+    submitCountList = submitItemAwardInfo.keys()
+    submitCountList.sort()
+    for submitCount in submitCountList:
+        recordIndex, awardItemList = submitItemAwardInfo[submitCount]
+        subInfo = ChPyNetSendPack.tagMCActBossTrialSubmitInfo()
+        subInfo.Clear()
+        subInfo.RecordIndex = recordIndex
+        subInfo.NeedCount = submitCount
+        subInfo.AwardItemList = []
+        for itemID, itemCount, isAuctionItem in awardItemList:
+            item = ChPyNetSendPack.tagMCActBossTrialItem()
+            item.Clear()
+            item.ItemID = itemID
+            item.ItemCount = itemCount
+            item.IsBind = isAuctionItem
+            subInfo.AwardItemList.append(item)
+        subInfo.Count = len(subInfo.AwardItemList)
+        actInfo.SubmitInfoList.append(subInfo)
+    actInfo.SubmitCount = len(actInfo.SubmitInfoList)
+    
+    actInfo.BillboardInfoList = []
+    for tempIpyData in tempIpyDataList:
+        rankInfo = ChPyNetSendPack.tagMCActBossTrialBillard()
+        rankInfo.Rank = tempIpyData.GetRank()
+        rankInfo.AwardItemList = []
+                
+        awardItemList = tempIpyData.GetAwardItemList()
+        for itemID, itemCount, isAuctionItem in awardItemList:
+            item = ChPyNetSendPack.tagMCActBossTrialItem()
+            item.Clear()
+            item.ItemID = itemID
+            item.ItemCount = itemCount
+            item.IsBind = isAuctionItem
+            rankInfo.AwardItemList.append(item)
+        rankInfo.Count = len(rankInfo.AwardItemList)
+        actInfo.BillboardInfoList.append(rankInfo)
+    actInfo.BillardCount = len(actInfo.BillboardInfoList)
+    
+    NetPackCommon.SendFakePack(curPlayer, actInfo)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index fea6218..c074111 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -89,6 +89,7 @@
 import PlayerActRechargePrize
 import PlayerActGrowupBuy
 import PlayerActTurntable
+import PlayerActBossTrial
 import PlayerActBuyOne
 import PlayerSpringSale
 import PlayerBossReborn
@@ -1421,6 +1422,9 @@
             elif actionName == ShareDefine.OperationActionName_BossReborn:
                 PlayerBossReborn.RefreshOperationAction_BossReborn()
                 
+            elif actionName == ShareDefine.OperationActionName_BossTrial:
+                PlayerActBossTrial.RefreshBossTrialActionInfo(actNum)
+                
             elif actionName == ShareDefine.OperationActionName_HorsePetFeast:
                 PlayerActHorsePetFeast.RefreshOperationAction_HorsePetFeast(actNum)
                 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 90b0787..1e462d0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -286,6 +286,7 @@
 OperationActionName_XianXiaMJ = "ActXianXiaMJ" # 仙匣秘境活动
 OperationActionName_GodGift = "ActGodGift" # 天帝礼包活动
 OperationActionName_BuyOne = "ActBuyOne" # 买一送多活动
+OperationActionName_BossTrial = "ActBossTrial" # Boss历练
 #节日活动类型列表 - 该类型无视开服天,日期到了就开启
 FeastOperationActionNameList = [OperationActionName_FeastWeekParty, OperationActionName_FeastRedPacket,
                                 OperationActionName_RechargeRebateGold, OperationActionName_GrowupBuy,
@@ -305,7 +306,7 @@
                            OperationActionName_CollectWords, OperationActionName_ManyDayRecharge,
                            OperationActionName_Turntable, OperationActionName_HorsePetFeast, OperationActionName_GarbageSorting,
                            OperationActionName_XianXiaMJ, OperationActionName_GodGift,
-                           OperationActionName_BuyOne,
+                           OperationActionName_BuyOne, OperationActionName_BossTrial,
                            ] + FeastOperationActionNameList
 #需要记录开启活动时的世界等级的运营活动
 NeedWorldLVOperationActNameList = [OperationActionName_FairyCeremony, OperationActionName_WishingWell, 
@@ -329,7 +330,7 @@
                                    OperationActionName_ManyDayRecharge, OperationActionName_SingleRecharge,
                                    OperationActionName_Turntable, OperationActionName_HorsePetFeast, OperationActionName_GarbageSorting,
                                    OperationActionName_XianXiaMJ, OperationActionName_GodGift,
-                                   OperationActionName_BuyOne,
+                                   OperationActionName_BuyOne, OperationActionName_BossTrial,
                                    ]
 
 #跨服运营活动表名定义
@@ -794,9 +795,10 @@
     Def_BT_CharmTotal, #魅力总榜 30
     Def_BT_CharmWeek, #魅力周榜
     Def_BT_CharmDay, #魅力日榜
+    Def_BT_BossTrialSubmit,                   #提交boss凭证榜 (boss历练活动)
     
     Def_BT_Max, #排行榜最大类型
-) = range(0, 32 + 2) 
+) = range(0, 33 + 2) 
 
 ''' 跨服排行榜类型, 从 150 开始
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始

--
Gitblit v1.8.0