From 735b28f37122bc5bb87c52806df1f5299085c89b Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 14 八月 2024 15:58:16 +0800
Subject: [PATCH] 10238 【越南】【砍树】【主干】【港台】骑宠养成(增加骑宠养成活动;任务活动增加骑宠活动相关任务类型;商城增加可配置不重置限购次数;增加境界培养卡道具效果;增加法器生命、攻击、防御百分比属性;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py                 |   12 
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                         |  101 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/FunctionNPCCommon.py |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py                     |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TrainRealmLV.py         |   36 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                  |  607 +++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py                      |    1 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                       |  607 +++++++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py                                |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                    |   84 +
 ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py                                              |    1 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py                     |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                  |    6 
 PySysDB/PySysDBPY.h                                                                                     |   24 
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                           |   31 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py             |   42 +
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py                 |    7 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                      |   31 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py                         |  296 +++++++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py                                    |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py               |   13 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTask.py             |   23 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py                          |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/EffGetSet.py                  |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActHorsePetTrain.py    |  301 +++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py        |    7 
 PySysDB/PySysDBG.h                                                                                      |   40 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                         |   30 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TrainRealmLV.py   |   40 +
 29 files changed, 2,342 insertions(+), 31 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index 3ca9d93..4a1396f 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -622,6 +622,46 @@
 	WORD		FamilyTemplateID;	//仙盟排行模板编号
 };
 
+//骑宠养成活动时间表
+
+struct tagActHorsePetTrain
+{
+	DWORD		_CfgID;	//配置ID
+	list		PlatformList;	//活动平台列表["平台A", "平台A", ...],配[]代表所有
+	list		ServerGroupIDList;	//服务器ID列表
+	BYTE		ActNum;	//活动分组编号, 活动类型 * 10 + 不同界面编号
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	char		JoinStartTime;	//参与开始时间点
+	char		JoinEndTime;	//参与结束时间点
+	WORD		PersonalTemplateID;	//个人排行模板编号
+};
+
+//骑宠养成活动跨服表
+
+struct tagCrossActHorsePetTrain
+{
+	DWORD		_CfgID;	//配置ID
+	char		ActGroupName;	//活动组名(同组活动的名字需相同)
+	BYTE		ZoneID;		//组内分组编号
+	list		ServerIDRangeList;	//活动的账号服务器ID范围列表 [[serverIDA, serverIDB], ...]
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	char		JoinStartTime;	//参与开始时间点
+	char		JoinEndTime;	//参与结束时间点
+	WORD		RankLimitPersonal;	//个人上榜积分限制
+	WORD		PersonalTemplateID;	//个人排行模板编号
+};
+
+//骑宠养成榜单模版表
+
+struct tagActHorsePetTrainBillTemp
+{
+	DWORD		_TemplateID;	//模板编号
+	BYTE		Rank;	//名次
+	list		AwardItemList;	//奖励物品列表[[物品ID,个数,是否拍品], ...]
+};
+
 //古宝养成活动时间表
 
 struct tagActGubao
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index cf52365..c4c43c6 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1169,6 +1169,7 @@
 	list		ItemListEx;	//扩展物品列表[[物品ID,个数,是否绑定],...]
 	DWORD		MainItemID;	//标的物品ID
 	list		JobItem;	//职业替换物品
+	BYTE		RefreshLimit;	//是否限制刷新限购次数,即是否永久限购,包含活动也不重置
 	BYTE		RefreshType;	//刷新类型 0-不重置,1-onWeek0点,2-onWeek5点,3-OnDay0点,4-OnDay5点
 	list		LimitVIPLV;	//VIP限制
 	DWORD		LimitLV;	//等级限制
@@ -1901,6 +1902,29 @@
 	list		MemAwardItemList;	//仙盟榜成员奖励物品信息列表[[物品ID,个数,是否拍品], ...]
 };
 
+//骑宠养成活动时间表
+
+struct tagActHorsePetTrain
+{
+	DWORD		_CfgID;	//配置ID
+	char		StartDate;	//开启日期
+	char		EndDate;	//结束日期
+	char		JoinStartTime;	//参与开始时间点
+	char		JoinEndTime;	//参与结束时间点
+	WORD		LVLimit;	//限制等级
+	WORD		ActShopType;	//开放商店类型,为0时不开放
+	WORD		PersonalTemplateID;	//个人排行模板编号
+};
+
+//骑宠养成榜单模版表
+
+struct tagActHorsePetTrainBillTemp
+{
+	DWORD		_TemplateID;	//模板编号
+	BYTE		Rank;	//名次
+	list		AwardItemList;	//奖励物品列表[[物品ID,个数,是否拍品], ...]
+};
+
 //古宝养成活动时间表
 
 struct tagActGubao
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
index 7b80f63..cc8a352 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -615,6 +615,7 @@
             ShareDefine.Def_BT_BossTrialSubmitFamily    : 100,           #boss凭证仙盟 (boss历练活动)
             ShareDefine.Def_BT_BossTrialSubmitFamilyBak : 100,           #boss凭证仙盟 (boss历练活动 - 上一期)
             ShareDefine.Def_BT_XianXiaMJScore           : 200,           #仙匣秘境积分榜 (仙匣秘境活动)
+            ShareDefine.Def_BT_HorsePetTrainScore       : 200,           #骑宠养成积分榜 (骑宠养成活动)
             ShareDefine.Def_BT_GubaoScore               : 200,           #古宝养成积分榜 (古宝养成活动)
             }
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index c35a90c..0274bc3 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -35952,6 +35952,280 @@
 
 
 #------------------------------------------------------
+# AA 84 骑宠养成活动信息 #tagMCActHorsePetTrainInfo
+
+class  tagMCActHorsePetTrainItem(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(tagMCActHorsePetTrainItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 84 骑宠养成活动信息 //tagMCActHorsePetTrainInfo:
+                                ItemID:%d,
+                                ItemCount:%d,
+                                IsBind:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount,
+                                self.IsBind
+                                )
+        return DumpString
+
+
+class  tagMCActHorsePetTrainBillard(Structure):
+    Rank = 0    #(DWORD Rank)// 名次,1-代表第一名;支持夸段,如1,3 代表第1名,第2~3名
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCActHorsePetTrainItem> 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 = tagMCActHorsePetTrainItem()
+            _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  tagMCActHorsePetTrainInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)// 活动编号
+    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
+    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
+    JoinStartTime = ""    #(char JoinStartTime[5])// 参与开始时间点 mm:ss
+    JoinEndTime = ""    #(char JoinEndTime[5])// 参与结束时间点 mm:ss
+    LimitLV = 0    #(WORD LimitLV)// 限制等级
+    ShopType = 0    #(WORD ShopType)// 开放商店类型,可能为0不开放
+    PersonalBillCount = 0    #(BYTE PersonalBillCount)
+    PersonalBillboardInfoList = list()    #(vector<tagMCActHorsePetTrainBillard> PersonalBillboardInfoList)// 个人榜单奖励信息列表,如果没有代表本次活动没有该榜奖励
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x84
+        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.JoinStartTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.JoinEndTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.ShopType,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.PersonalBillCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.PersonalBillCount):
+            temPersonalBillboardInfoList = tagMCActHorsePetTrainBillard()
+            _pos = temPersonalBillboardInfoList.ReadData(_lpData, _pos)
+            self.PersonalBillboardInfoList.append(temPersonalBillboardInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x84
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.JoinStartTime = ""
+        self.JoinEndTime = ""
+        self.LimitLV = 0
+        self.ShopType = 0
+        self.PersonalBillCount = 0
+        self.PersonalBillboardInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 10
+        length += 10
+        length += 5
+        length += 5
+        length += 2
+        length += 2
+        length += 1
+        for i in range(self.PersonalBillCount):
+            length += self.PersonalBillboardInfoList[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.WriteString(data, 5, self.JoinStartTime)
+        data = CommFunc.WriteString(data, 5, self.JoinEndTime)
+        data = CommFunc.WriteWORD(data, self.LimitLV)
+        data = CommFunc.WriteWORD(data, self.ShopType)
+        data = CommFunc.WriteBYTE(data, self.PersonalBillCount)
+        for i in range(self.PersonalBillCount):
+            data = CommFunc.WriteString(data, self.PersonalBillboardInfoList[i].GetLength(), self.PersonalBillboardInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                JoinStartTime:%s,
+                                JoinEndTime:%s,
+                                LimitLV:%d,
+                                ShopType:%d,
+                                PersonalBillCount:%d,
+                                PersonalBillboardInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.JoinStartTime,
+                                self.JoinEndTime,
+                                self.LimitLV,
+                                self.ShopType,
+                                self.PersonalBillCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCActHorsePetTrainInfo=tagMCActHorsePetTrainInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActHorsePetTrainInfo.Head.Cmd,m_NAtagMCActHorsePetTrainInfo.Head.SubCmd))] = m_NAtagMCActHorsePetTrainInfo
+
+
+#------------------------------------------------------
+# AA 85 骑宠养成活动玩家信息 #tagMCActHorsePetTrainPlayerInfo
+
+class  tagMCActHorsePetTrainPlayerInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    # 活动编号
+                  ("Score", c_int),    # 当前活动积分
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x85
+        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 = 0x85
+        self.ActNum = 0
+        self.Score = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActHorsePetTrainPlayerInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 85 骑宠养成活动玩家信息 //tagMCActHorsePetTrainPlayerInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                Score:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.Score
+                                )
+        return DumpString
+
+
+m_NAtagMCActHorsePetTrainPlayerInfo=tagMCActHorsePetTrainPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActHorsePetTrainPlayerInfo.Cmd,m_NAtagMCActHorsePetTrainPlayerInfo.SubCmd))] = m_NAtagMCActHorsePetTrainPlayerInfo
+
+
+#------------------------------------------------------
 # AA 0C 登录奖励活动信息 #tagMCActLoginAwardInfo
 
 class  tagMCActLoginAwardAction(Structure):
@@ -41353,6 +41627,231 @@
 
 m_NAtagMCCrossActGubaoInfo=tagMCCrossActGubaoInfo()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCrossActGubaoInfo.Head.Cmd,m_NAtagMCCrossActGubaoInfo.Head.SubCmd))] = m_NAtagMCCrossActGubaoInfo
+
+
+#------------------------------------------------------
+# AA 86 骑宠养成跨服活动信息 #tagMCCrossActHorsePetTrainInfo
+
+class  tagMCCrossActHorsePetTrainItem(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(tagMCCrossActHorsePetTrainItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 86 骑宠养成跨服活动信息 //tagMCCrossActHorsePetTrainInfo:
+                                ItemID:%d,
+                                ItemCount:%d,
+                                IsBind:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount,
+                                self.IsBind
+                                )
+        return DumpString
+
+
+class  tagMCCrossActHorsePetTrainBillard(Structure):
+    Rank = 0    #(DWORD Rank)// 名次,1-代表第一名;支持夸段,如1,3 代表第1名,第2~3名
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCCrossActHorsePetTrainItem> 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 = tagMCCrossActHorsePetTrainItem()
+            _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  tagMCCrossActHorsePetTrainInfo(Structure):
+    Head = tagHead()
+    ServerInfoLen = 0    #(BYTE ServerInfoLen)
+    ServerIDRangeInfo = ""    #(String ServerIDRangeInfo)//开放该活动的服务器ID范围列表,json格式 [[IDA, IDB], ...], [] 为全服
+    GroupValue1 = 0    #(BYTE GroupValue1)// 活动榜单分组值1,用于查询对应榜单
+    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
+    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
+    JoinStartTime = ""    #(char JoinStartTime[5])// 参与开始时间点 mm:ss
+    JoinEndTime = ""    #(char JoinEndTime[5])// 参与结束时间点 mm:ss
+    RankLimitPersonal = 0    #(WORD RankLimitPersonal)// 个人榜上榜积分保底限制;
+    PersonalBillCount = 0    #(BYTE PersonalBillCount)
+    PersonalBillboardInfoList = list()    #(vector<tagMCCrossActHorsePetTrainBillard> PersonalBillboardInfoList)// 个人榜单奖励信息列表,如果没有代表本次活动没有该榜奖励
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x86
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ServerInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ServerIDRangeInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ServerInfoLen)
+        self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.JoinStartTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.JoinEndTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.RankLimitPersonal,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.PersonalBillCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.PersonalBillCount):
+            temPersonalBillboardInfoList = tagMCCrossActHorsePetTrainBillard()
+            _pos = temPersonalBillboardInfoList.ReadData(_lpData, _pos)
+            self.PersonalBillboardInfoList.append(temPersonalBillboardInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x86
+        self.ServerInfoLen = 0
+        self.ServerIDRangeInfo = ""
+        self.GroupValue1 = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.JoinStartTime = ""
+        self.JoinEndTime = ""
+        self.RankLimitPersonal = 0
+        self.PersonalBillCount = 0
+        self.PersonalBillboardInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += len(self.ServerIDRangeInfo)
+        length += 1
+        length += 10
+        length += 10
+        length += 5
+        length += 5
+        length += 2
+        length += 1
+        for i in range(self.PersonalBillCount):
+            length += self.PersonalBillboardInfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ServerInfoLen)
+        data = CommFunc.WriteString(data, self.ServerInfoLen, self.ServerIDRangeInfo)
+        data = CommFunc.WriteBYTE(data, self.GroupValue1)
+        data = CommFunc.WriteString(data, 10, self.StartDate)
+        data = CommFunc.WriteString(data, 10, self.EndtDate)
+        data = CommFunc.WriteString(data, 5, self.JoinStartTime)
+        data = CommFunc.WriteString(data, 5, self.JoinEndTime)
+        data = CommFunc.WriteWORD(data, self.RankLimitPersonal)
+        data = CommFunc.WriteBYTE(data, self.PersonalBillCount)
+        for i in range(self.PersonalBillCount):
+            data = CommFunc.WriteString(data, self.PersonalBillboardInfoList[i].GetLength(), self.PersonalBillboardInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ServerInfoLen:%d,
+                                ServerIDRangeInfo:%s,
+                                GroupValue1:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                JoinStartTime:%s,
+                                JoinEndTime:%s,
+                                RankLimitPersonal:%d,
+                                PersonalBillCount:%d,
+                                PersonalBillboardInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ServerInfoLen,
+                                self.ServerIDRangeInfo,
+                                self.GroupValue1,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.JoinStartTime,
+                                self.JoinEndTime,
+                                self.RankLimitPersonal,
+                                self.PersonalBillCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCCrossActHorsePetTrainInfo=tagMCCrossActHorsePetTrainInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCrossActHorsePetTrainInfo.Head.Cmd,m_NAtagMCCrossActHorsePetTrainInfo.Head.SubCmd))] = m_NAtagMCCrossActHorsePetTrainInfo
 
 
 #------------------------------------------------------
@@ -48982,6 +49481,114 @@
 
 
 #------------------------------------------------------
+# B1 12 培养功能境界信息 #tagMCTrainRealmLVInfo
+
+class  tagMCTrainRealmLV(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("FuncType", c_ubyte),    # 功能类型:1-坐骑;2-灵宠;3-灵器
+                  ("TrainRealmLV", 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.FuncType = 0
+        self.TrainRealmLV = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCTrainRealmLV)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 12 培养功能境界信息 //tagMCTrainRealmLVInfo:
+                                FuncType:%d,
+                                TrainRealmLV:%d
+                                '''\
+                                %(
+                                self.FuncType,
+                                self.TrainRealmLV
+                                )
+        return DumpString
+
+
+class  tagMCTrainRealmLVInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    InfoList = list()    #(vector<tagMCTrainRealmLV> InfoList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x12
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temInfoList = tagMCTrainRealmLV()
+            _pos = temInfoList.ReadData(_lpData, _pos)
+            self.InfoList.append(temInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x12
+        self.Count = 0
+        self.InfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.InfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.InfoList[i].GetLength(), self.InfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                InfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCTrainRealmLVInfo=tagMCTrainRealmLVInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCTrainRealmLVInfo.Head.Cmd,m_NAtagMCTrainRealmLVInfo.Head.SubCmd))] = m_NAtagMCTrainRealmLVInfo
+
+
+#------------------------------------------------------
 # B1 20 战令信息 #tagMCZhanlingInfo
 
 class  tagMCZhanling(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
index fab79d4..99d6dc2 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
@@ -25,6 +25,7 @@
 import PlayerActBossTrial
 import PlayerActXianXiaMJ
 import PlayerActGubao
+import PlayerActHorsePetTrain
 import CrossRealmMsg
 import PyGameData
 import PlayerFB
@@ -633,6 +634,9 @@
                 elif actName == ShareDefine.CrossActName_Gubao:
                     PlayerActGubao.OnCrossActIDChange(cfgID, zoneID, ipyData, state)
                     
+                elif actName == ShareDefine.CrossActName_HorsePetTrain:
+                    PlayerActHorsePetTrain.OnCrossActIDChange(cfgID, zoneID, ipyData, state)
+                    
                 else:
                     actChangeList.append([actName, ipyData, state, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID])
                     
@@ -663,6 +667,9 @@
                     elif actName == ShareDefine.CrossActName_Gubao:
                         PlayerActGubao.OnCrossActJoinEnd(cfgID, zoneID, ipyData)
                         
+                    elif actName == ShareDefine.CrossActName_HorsePetTrain:
+                        PlayerActHorsePetTrain.OnCrossActJoinEnd(cfgID, zoneID, ipyData)
+                        
             GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossActInfo % actName, crossActInfoDict[actName])
             # 非活动中的处理完关闭后,最后删除
             if not state and isEnd:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
index 15c12ab..89c9336 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -27,6 +27,7 @@
 import PlayerActBossTrial
 import PlayerActXianXiaMJ
 import PlayerActGubao
+import PlayerActHorsePetTrain
 import CrossActionControl
 import CrossActAllRecharge
 import CrossFamilyFlagwar
@@ -182,6 +183,9 @@
         elif msgType == ShareDefine.ClientServerMsg_GubaoScore:
             PlayerActGubao.ClientServerMsg_GubaoScore(serverGroupID, msgData)
             
+        elif msgType == ShareDefine.ClientServerMsg_HorsePetTrainScore:
+            PlayerActHorsePetTrain.ClientServerMsg_HorsePetTrainScore(serverGroupID, msgData)
+            
         elif msgType == ShareDefine.ClientServerMsg_CreateFuncTeam:
             PlayerFuncTeam.ClientServerMsg_CreateFuncTeam(serverGroupID, msgData)
             
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
index a0d9378..6ffbdec 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldActionControl.py
@@ -38,6 +38,7 @@
 import PlayerActBossTrial
 import PlayerActXianXiaMJ
 import PlayerActGubao
+import PlayerActHorsePetTrain
 import PlayerUniversalGameRec
 import GameWorldAverageLv
 import PlayerFamilyBoss
@@ -826,6 +827,8 @@
                         PlayerActXianXiaMJ.OnActEnd(actNum, ipyData, dayIndex)
                     elif actName == ShareDefine.OperationActionName_Gubao:
                         PlayerActGubao.OnActEnd(actNum, ipyData, dayIndex)
+                    elif actName == ShareDefine.OperationActionName_HorsePetTrain:
+                        PlayerActHorsePetTrain.OnActEnd(actNum, ipyData, dayIndex)
                         
                 if curActID:
                     if actName in ShareDefine.NeedWorldLVOperationActNameList:
@@ -860,6 +863,8 @@
                         PlayerActXianXiaMJ.OnActStart(actNum)
                     elif actName == ShareDefine.OperationActionName_Gubao:
                         PlayerActGubao.OnActStart(actNum)
+                    elif actName == ShareDefine.OperationActionName_HorsePetTrain:
+                        PlayerActHorsePetTrain.OnActStart(actNum)
                     elif actName == ShareDefine.OperationActionName_FamilyCTGAssist:
                         PlayerActFamilyCTGAssist.OnActStart(actNum)
                 else:
@@ -883,6 +888,8 @@
                         PlayerActXianXiaMJ.OnActJoinEnd(actNum, ipyData, dayIndex)
                     elif actName == ShareDefine.OperationActionName_Gubao:
                         PlayerActGubao.OnActJoinEnd(actNum, ipyData, dayIndex)
+                    elif actName == ShareDefine.OperationActionName_HorsePetTrain:
+                        PlayerActHorsePetTrain.OnActJoinEnd(actNum, ipyData, dayIndex)
                         
             if ipyData and actName in ShareDefine.NeedWorldLVOperationActNameList:
                 actWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(dbOperationActWorldLVKey)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index 92430cd..984506e 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -518,6 +518,37 @@
                         ("WORD", "FamilyTemplateID", 0),
                         ),
 
+                "ActHorsePetTrain":(
+                        ("DWORD", "CfgID", 1),
+                        ("list", "PlatformList", 0),
+                        ("list", "ServerGroupIDList", 0),
+                        ("BYTE", "ActNum", 0),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("char", "JoinStartTime", 0),
+                        ("char", "JoinEndTime", 0),
+                        ("WORD", "PersonalTemplateID", 0),
+                        ),
+
+                "CrossActHorsePetTrain":(
+                        ("DWORD", "CfgID", 1),
+                        ("char", "ActGroupName", 0),
+                        ("BYTE", "ZoneID", 0),
+                        ("list", "ServerIDRangeList", 0),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("char", "JoinStartTime", 0),
+                        ("char", "JoinEndTime", 0),
+                        ("WORD", "RankLimitPersonal", 0),
+                        ("WORD", "PersonalTemplateID", 0),
+                        ),
+
+                "ActHorsePetTrainBillTemp":(
+                        ("DWORD", "TemplateID", 1),
+                        ("BYTE", "Rank", 0),
+                        ("list", "AwardItemList", 0),
+                        ),
+
                 "ActGubao":(
                         ("DWORD", "CfgID", 1),
                         ("list", "PlatformList", 0),
@@ -1829,6 +1860,52 @@
     def GetPersonalTemplateID(self): return self.attrTuple[14] # 个人排行模板编号 WORD
     def GetFamilyTemplateID(self): return self.attrTuple[15] # 仙盟排行模板编号 WORD
 
+# 骑宠养成活动时间表
+class IPY_ActHorsePetTrain():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetCfgID(self): return self.attrTuple[0] # 配置ID DWORD
+    def GetPlatformList(self): return self.attrTuple[1] # 活动平台列表["平台A", "平台A", ...],配[]代表所有 list
+    def GetServerGroupIDList(self): return self.attrTuple[2] # 服务器ID列表 list
+    def GetActNum(self): return self.attrTuple[3] # 活动分组编号, 活动类型 * 10 + 不同界面编号 BYTE
+    def GetStartDate(self): return self.attrTuple[4] # 开启日期 char
+    def GetEndDate(self): return self.attrTuple[5] # 结束日期 char
+    def GetJoinStartTime(self): return self.attrTuple[6] # 参与开始时间点 char
+    def GetJoinEndTime(self): return self.attrTuple[7] # 参与结束时间点 char
+    def GetPersonalTemplateID(self): return self.attrTuple[8] # 个人排行模板编号 WORD
+
+# 骑宠养成活动跨服表
+class IPY_CrossActHorsePetTrain():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetCfgID(self): return self.attrTuple[0] # 配置ID DWORD
+    def GetActGroupName(self): return self.attrTuple[1] # 活动组名(同组活动的名字需相同) char
+    def GetZoneID(self): return self.attrTuple[2] # 组内分组编号 BYTE
+    def GetServerIDRangeList(self): return self.attrTuple[3] # 活动的账号服务器ID范围列表 [[serverIDA, serverIDB], ...] list
+    def GetStartDate(self): return self.attrTuple[4] # 开启日期 char
+    def GetEndDate(self): return self.attrTuple[5] # 结束日期 char
+    def GetJoinStartTime(self): return self.attrTuple[6] # 参与开始时间点 char
+    def GetJoinEndTime(self): return self.attrTuple[7] # 参与结束时间点 char
+    def GetRankLimitPersonal(self): return self.attrTuple[8] # 个人上榜积分限制 WORD
+    def GetPersonalTemplateID(self): return self.attrTuple[9] # 个人排行模板编号 WORD
+
+# 骑宠养成榜单模版表
+class IPY_ActHorsePetTrainBillTemp():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetTemplateID(self): return self.attrTuple[0] # 模板编号 DWORD
+    def GetRank(self): return self.attrTuple[1] # 名次 BYTE
+    def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
+
 # 古宝养成活动时间表
 class IPY_ActGubao():
     
@@ -2804,6 +2881,9 @@
         self.__LoadFileData("ActBossTrial", onlyCheck)
         self.__LoadFileData("ActBossTrialTemplate", onlyCheck)
         self.__LoadFileData("CrossActBossTrial", onlyCheck)
+        self.__LoadFileData("ActHorsePetTrain", onlyCheck)
+        self.__LoadFileData("CrossActHorsePetTrain", onlyCheck)
+        self.__LoadFileData("ActHorsePetTrainBillTemp", onlyCheck)
         self.__LoadFileData("ActGubao", onlyCheck)
         self.__LoadFileData("CrossActGubao", onlyCheck)
         self.__LoadFileData("ActGubaoBillTemp", onlyCheck)
@@ -3387,6 +3467,27 @@
         self.CheckLoadData("CrossActBossTrial")
         return self.ipyCrossActBossTrialCache[index]
 
+    def GetActHorsePetTrainCount(self):
+        self.CheckLoadData("ActHorsePetTrain")
+        return self.ipyActHorsePetTrainLen
+    def GetActHorsePetTrainByIndex(self, index):
+        self.CheckLoadData("ActHorsePetTrain")
+        return self.ipyActHorsePetTrainCache[index]
+
+    def GetCrossActHorsePetTrainCount(self):
+        self.CheckLoadData("CrossActHorsePetTrain")
+        return self.ipyCrossActHorsePetTrainLen
+    def GetCrossActHorsePetTrainByIndex(self, index):
+        self.CheckLoadData("CrossActHorsePetTrain")
+        return self.ipyCrossActHorsePetTrainCache[index]
+
+    def GetActHorsePetTrainBillTempCount(self):
+        self.CheckLoadData("ActHorsePetTrainBillTemp")
+        return self.ipyActHorsePetTrainBillTempLen
+    def GetActHorsePetTrainBillTempByIndex(self, index):
+        self.CheckLoadData("ActHorsePetTrainBillTemp")
+        return self.ipyActHorsePetTrainBillTempCache[index]
+
     def GetActGubaoCount(self):
         self.CheckLoadData("ActGubao")
         return self.ipyActGubaoLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py
new file mode 100644
index 0000000..b9f65a6
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py
@@ -0,0 +1,296 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PlayerActHorsePetTrain
+#
+# @todo:骑宠养成活动
+# @author hxp
+# @date 2024-08-14
+# @version 1.0
+#
+# 详细描述: 骑宠养成活动
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-08-14 16:30"""
+#-------------------------------------------------------------------------------
+
+import ShareDefine
+import IpyGameDataPY
+import DataRecordPack
+import PlayerDBGSEvent
+import PlayerBillboard
+import PlayerCompensation
+import CrossActionControl
+import CrossBillboard
+import PyDataManager
+import CrossRealmMsg
+import GameWorld
+
+def OnActStart(actNum):
+    ## 活动开启
+    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActHorsePetTrainAward % actNum, 0)
+    PlayerBillboard.ClearBillboardByIndex(ShareDefine.Def_BT_HorsePetTrainScore)
+    return
+
+def OnActEnd(actNum, ipyData, dayIndex):
+    ## 活动结束
+    cfgID = ipyData.GetCfgID() if ipyData else 0
+    GameWorld.Log("=== 骑宠养成活动结束! === actNum=%s,cfgID=%s,dayIndex=%s" % (actNum, cfgID, dayIndex))
+    
+    __OnEndAward(actNum, ipyData, dayIndex) # 兼容活动没有配置参与时间段的在活动结束补触发结算奖励
+    
+    GameWorld.Log("=================================================================================")
+    return
+
+def OnActJoinEnd(actNum, ipyData, dayIndex):
+    ## 活动参与结束
+    __OnEndAward(actNum, ipyData, dayIndex)
+    return
+
+def __OnEndAward(actNum, ipyData, dayIndex):
+    ## 结算奖励
+    if not ipyData:
+        return
+    cfgID = ipyData.GetCfgID()
+    awardState = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActHorsePetTrainAward % actNum)
+    if awardState:
+        #已经结算过该活动
+        GameWorld.Log("骑宠养成活动已经结算过奖励了! actNum=%s,cfgID=%s,dayIndex=%s" % (actNum, cfgID, dayIndex))
+        return
+    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActHorsePetTrainAward % actNum, 1)
+    
+    GameWorld.Log("=== 本服骑宠养成活动发放榜单奖励! === actNum=%s,cfgID=%s,dayIndex=%s" % (actNum, cfgID, dayIndex))
+    
+    __OnEndAward_Personal(ipyData.GetPersonalTemplateID(), ShareDefine.Def_BT_HorsePetTrainScore)
+    
+    DataRecordPack.DR_BillboardData(ShareDefine.Def_BT_HorsePetTrainScore, "ActHorsePetTrain", {"actNum":actNum, "cfgID":cfgID, "dayIndex":dayIndex})
+    GameWorld.Log("=================================================================================")
+    return
+
+def __OnEndAward_Personal(templateID, billboardType):
+    billBoard = GameWorld.GetBillboard().FindBillboard(billboardType)
+    if not billBoard:
+        return
+    if not templateID:
+        GameWorld.Log("本次活动没有个人榜奖励!")
+        return
+    tempIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActHorsePetTrainBillTemp", 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("    发放骑宠养成个人榜单奖励: rank=%s,playerID=%s,cmpValue=%s,awardItemList=%s, %s" 
+                      % (rank, playerID, cmpValue, awardItemList, name2))
+        
+        PlayerCompensation.SendMailByKey("ActHorsePetTrainPlayer", [playerID], awardItemList, [rank])
+        
+    return
+
+def MapServer_HorsePetTrain(curPlayer, msgList):
+    mapID = curPlayer.GetRealMapID()
+    playerID = curPlayer.GetPlayerID()
+    GameWorld.DebugLog("MapServer_HorsePetTrain mapID=%s,msgList=%s" % (mapID, msgList), playerID)
+    if not msgList:
+        return
+    
+    msgType, dataMsg = msgList
+    ret = None
+    
+    if msgType == "AddHorsePetTrainScore":
+        ret = __OnAddHorsePetTrainScore(curPlayer, dataMsg)
+        
+    if ret == None:
+        return
+    return msgList + (ret if isinstance(ret, list) else [ret])
+
+def __OnAddHorsePetTrainScore(curPlayer, dataMsg):
+    ## 地图增加积分
+    playerID = curPlayer.GetPlayerID()
+    accID = curPlayer.GetAccID()
+    playerName = curPlayer.GetName()
+    job = curPlayer.GetJob()
+    realmLV = curPlayer.GetOfficialRank()
+    _, updScore = dataMsg
+    
+    #同步跨服
+    playerInfo = {"playerID":playerID, "playerName":playerName, "accID":accID, "job":job, "realmLV":realmLV,
+                  "playerScore":updScore}
+    SyncHorsePetTrainToCrossServer(curPlayer, playerInfo)
+    return
+
+def SyncHorsePetTrainToCrossServer(curPlayer, playerInfo):
+    ## 同步到跨服服务器
+    actInfo = CrossActionControl.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_HorsePetTrain)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+    if not ipyDataDict:
+        return
+    zoneID = ipyDataDict.get("ZoneID")
+    if not cfgID or not zoneID:
+        return
+    
+    dataMsg = {"cfgID":cfgID, "zoneID":zoneID, "playerInfo":playerInfo}
+    CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_HorsePetTrainScore, dataMsg)
+    return
+
+##------------------------------------------ 跨服骑宠养成活动 ---------------------------------------
+def ClientServerMsg_HorsePetTrainScore(serverGroupID, msgData):
+    ## 收到子服 - 同步积分
+    
+    cfgID = msgData["cfgID"]
+    zoneID = msgData["zoneID"]
+    playerInfo = msgData["playerInfo"]
+    
+    actInfo = CrossActionControl.GetCrossActInfoByCfgID(ShareDefine.CrossActName_HorsePetTrain, cfgID, zoneID)
+    if not actInfo or not actInfo[ShareDefine.ActKey_State]:
+        GameWorld.ErrLog("跨服骑宠养成非活动中,无法更新! cfgID=%s, zoneID=%s" % (cfgID, zoneID))
+        return
+    if actInfo[ShareDefine.ActKey_StateJoin] != ShareDefine.ActStateJoin_Start:
+        GameWorld.ErrLog("跨服骑宠养成非可参与状态,无法更新! cfgID=%s, zoneID=%s" % (cfgID, zoneID))
+        return
+    ipyData = IpyGameDataPY.GetIpyGameData("CrossActHorsePetTrain", cfgID)
+    if not ipyData:
+        return
+    personlLimit = ipyData.GetRankLimitPersonal()
+    
+    playerID = playerInfo["playerID"]
+    playerName = playerInfo["playerName"]
+    job = playerInfo["job"]
+    accID = playerInfo["accID"]
+    realmLV = playerInfo["realmLV"]
+    playerScore = playerInfo["playerScore"]
+    
+    groupValue1 = zoneID
+    
+    if playerScore >= personlLimit:
+        name2, type2, value1, value2 = accID, job, realmLV, 0
+        CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_HorsePetTrainScore, groupValue1, playerID, playerName, 
+                                         name2, type2, value1, value2, playerScore)
+    return
+
+def OnCrossActIDChange(cfgID, zoneID, ipyData, state):
+    ## 跨服活动ID变更
+    if state:
+        OnCrossActStart(cfgID, zoneID, ipyData)
+    else:
+        OnCrossActEnd(cfgID, zoneID, ipyData)
+    return
+
+def OnCrossActStart(cfgID, zoneID, ipyData):
+    ## 跨服活动开启
+    
+    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActHorsePetTrainAwardC % zoneID, 0)
+    
+    groupValue1 = zoneID
+    billboardMgr = PyDataManager.GetCrossBillboardManager()
+    billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_HorsePetTrainScore, groupValue1)
+    billboardObj.ClearData() # 新活动重置榜单数据
+    return
+
+def OnCrossActEnd(cfgID, zoneID, ipyData):
+    ## 跨服活动结束
+    
+    groupValue1 = zoneID
+    GameWorld.Log("=== 跨服骑宠养成活动结束! === cfgID=%s,zoneID=%s" % (cfgID, zoneID))
+    __OnCrossEndAward(cfgID, zoneID, ipyData)
+    
+    # 备份、清除榜单数据
+    billboardMgr = PyDataManager.GetCrossBillboardManager()
+    billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_HorsePetTrainScore, groupValue1)
+    billboardObj.ClearData()
+    
+    GameWorld.Log("=================================================================================")
+    return
+
+def OnCrossActJoinEnd(cfgID, zoneID, ipyData):
+    ## 跨服活动参与结束
+    __OnCrossEndAward(cfgID, zoneID, ipyData)
+    return
+
+def __OnCrossEndAward(cfgID, zoneID, ipyData):
+    ## 结算跨服奖励
+    awardState = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActHorsePetTrainAwardC % zoneID)
+    if awardState:
+        #已经结算过该活动
+        GameWorld.Log("跨服骑宠养成活动已经结算过奖励了! cfgID=%s,zoneID=%s" % (cfgID, zoneID))
+        return
+    PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActHorsePetTrainAwardC % zoneID, 1)
+    
+    GameWorld.Log("=== 跨服骑宠养成活动发放榜单奖励! === cfgID=%s,zoneID=%s" % (cfgID, zoneID))
+    
+    PersonalTemplateID = ipyData.GetPersonalTemplateID()
+    
+    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_HorsePetTrainScore)
+    GameWorld.Log("=================================================================================")
+    return
+    
+def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType):
+    
+    groupValue1 = zoneID
+    billboardMgr = PyDataManager.GetCrossBillboardManager()
+    billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1)
+    billboardDataCount = billboardObj.GetCount()
+    if not billboardDataCount:
+        GameWorld.Log("跨服骑宠养成个人排行数据为空! billboardType=%s,zoneID=%s,cfgID=%s,templateID=%s" % (billboardType, zoneID, cfgID, templateID))
+        return
+    
+    # 结算时排序并保存榜单数据流向
+    billboardObj.SortData()
+    billboardObj.SaveDRData("Award", {"cfgID":cfgID, "zoneID":zoneID})
+    
+    GameWorld.Log("结算跨服骑宠养成个人排行奖励: billboardType=%s,zoneID=%s,cfgID=%s,templateID=%s,billboardDataCount=%s" 
+                  % (billboardType, zoneID, cfgID, templateID, billboardDataCount))
+    
+    orderIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActHorsePetTrainBillTemp", templateID)
+    if orderIpyDataList:
+        rankPre = 0
+        billboardIndex = 0
+        for ipyData in orderIpyDataList:
+            rank = ipyData.GetRank()
+            awardItemList = ipyData.GetAwardItemList()
+            orderCountTotal = rank - rankPre # 奖励名次数量
+            rankPre = rank
+            orderCount = 0
+            
+            for index in xrange(billboardIndex, billboardDataCount):
+                if orderCount >= orderCountTotal:
+                    break
+                
+                billboardData = billboardObj.At(index)
+                playerID = billboardData.ID
+                name2 = billboardData.Name2
+                cmpValue = billboardData.CmpValue
+                
+                playerRank = index + 1
+                GameWorld.Log("    发放骑宠养成个人榜单奖励: rank=%s,playerID=%s,cmpValue=%s,awardItemList=%s, %s" 
+                              % (rank, playerID, cmpValue, awardItemList, name2))
+                PlayerCompensation.SendMailByKey("ActHorsePetTrainCrossPlayer", [playerID], awardItemList, [playerRank], crossMail=True)
+                
+                orderCount += 1
+                billboardIndex += 1
+                
+    return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
index b740c6c..980c8fa 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
@@ -186,6 +186,10 @@
 Def_ActGubaoAward = "ActGubaoAward_%s"
 #跨服古宝养成结算状态,参数(zoneID)
 Def_ActGubaoAwardC = "ActGubaoAwardC_%s"
+#骑宠养成结算状态,参数(actNum),跨服活动参数(zoneID)
+Def_ActHorsePetTrainAward = "ActHorsePetTrainAward_%s"
+#跨服骑宠养成结算状态,参数(zoneID)
+Def_ActHorsePetTrainAwardC = "ActHorsePetTrainAwardC_%s"
 
 def SetInitOpenServerTime(initTime):
     openDatetime = GameWorld.ChangeTimeNumToDatetime(initTime)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index c066819..bf3468f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -77,6 +77,7 @@
 import CrossFamilyFlagwar
 import CrossActAllRecharge
 import PlayerActGubao
+import PlayerActHorsePetTrain
 import PlayerActXianXiaMJ
 import PlayerActBossTrial
 import PlayerActFamilyCTGAssist
@@ -721,6 +722,14 @@
         PlayerActGubao.MapServer_Gubao(curPlayer, eval(resultName))
         return
     
+    # 骑宠养成
+    if callName == "ActHorsePetTrain":
+        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
+        if not curPlayer:
+            return
+        PlayerActHorsePetTrain.MapServer_HorsePetTrain(curPlayer, eval(resultName))
+        return
+    
     #py喇叭聊天
     if callName == 'PYSpeaker':
         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 5b7caff..48d54ec 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -295,6 +295,7 @@
 OperationActionName_BuyCountGift = "ActBuyCountGift" # 购买次数礼包活动
 OperationActionName_FamilyCTGAssist = "ActFamilyCTGAssist" # 仙盟充值协助
 OperationActionName_Gubao = "ActGubao" # 古宝养成活动
+OperationActionName_HorsePetTrain = "ActHorsePetTrain" # 骑宠养成活动
 #节日活动类型列表 - 该类型无视开服天,日期到了就开启
 FeastOperationActionNameList = [OperationActionName_FeastWeekParty, OperationActionName_FeastRedPacket,
                                 OperationActionName_RechargeRebateGold, OperationActionName_GrowupBuy,
@@ -317,7 +318,7 @@
                            OperationActionName_BuyOne, OperationActionName_BossTrial,
                            OperationActionName_ActLoginNew, OperationActionName_ActTask,
                            OperationActionName_BuyCountGift, OperationActionName_FamilyCTGAssist,
-                           OperationActionName_Gubao,
+                           OperationActionName_Gubao, OperationActionName_HorsePetTrain,
                            ] + FeastOperationActionNameList
 #需要记录开启活动时的世界等级的运营活动
 NeedWorldLVOperationActNameList = [OperationActionName_FairyCeremony, OperationActionName_WishingWell, 
@@ -344,7 +345,7 @@
                                    OperationActionName_BuyOne, OperationActionName_BossTrial,
                                    OperationActionName_ActLoginNew, OperationActionName_ActTask,
                                    OperationActionName_BuyCountGift, OperationActionName_FamilyCTGAssist,
-                                   OperationActionName_Gubao,
+                                   OperationActionName_Gubao, OperationActionName_HorsePetTrain,
                                    ]
 
 #跨服运营活动表名定义
@@ -354,9 +355,11 @@
 CrossActName_BossTrial = "CrossActBossTrial" # Boss历练 - 跨服
 CrossActName_XianXiaMJ = "CrossActXianXiaMJ" # 仙匣秘境 - 跨服
 CrossActName_Gubao = "CrossActGubao" # 古宝养成 - 跨服
+CrossActName_HorsePetTrain = "CrossActHorsePetTrain" # 骑宠养成 - 跨服
 
 #跨服运营活动列表
-CrossActNameList = [CrossActName_CTGBillboard, CrossActName_AllRecharge, CrossActName_LuckyCloudBuy, CrossActName_BossTrial, CrossActName_XianXiaMJ, CrossActName_Gubao]
+CrossActNameList = [CrossActName_CTGBillboard, CrossActName_AllRecharge, CrossActName_LuckyCloudBuy, CrossActName_BossTrial, 
+                    CrossActName_XianXiaMJ, CrossActName_Gubao, CrossActName_HorsePetTrain]
 #需要锁定活动分区分配直到活动结束的跨服运营活动,即使热更分区配置,也不会改变正在活动中的分区设定,直到活动结束
 CrossActLockServerGroupIDList = [CrossActName_CTGBillboard, CrossActName_AllRecharge]
 
@@ -722,6 +725,13 @@
 
 Def_Effect_BossFinalHurtPer = 166   # Boss最终伤害万分率
 
+#法器生命百分比
+Def_Effect_FaQiMaxHPPer = 167
+#法器攻击百分比
+Def_Effect_FaQiAtkPer = 168
+#法器防御百分比
+Def_Effect_FaQiDefPer = 169
+
 #增加%d物理伤害值,其中a值为伤害值
 Def_Effect_AddAtk = 1005
 #增加%d魔法伤害值,其中a值为伤害值
@@ -830,9 +840,10 @@
     Def_BT_BossTrialSubmitFamilyBak,          #提交boss凭证仙盟榜 (boss历练活动 - 上一期)
     Def_BT_XianXiaMJScore,                    #仙匣秘境积分榜 (仙匣秘境活动)
     Def_BT_GubaoScore,                        #古宝养成积分榜 (古宝养成活动)
+    Def_BT_HorsePetTrainScore,                #骑宠养成积分榜 (骑宠养成活动) 40
     
     Def_BT_Max, #排行榜最大类型
-) = range(0, 39 + 2) 
+) = range(0, 40 + 2) 
 
 ''' 跨服排行榜类型, 从 150 开始
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
@@ -854,7 +865,8 @@
 Def_CBT_BossTrialSubmitFamilyBak, # boss凭证 - 仙盟榜 上一期  161
 Def_CBT_XianXiaMJScore, # 仙匣秘境积分 - 个人榜  162
 Def_CBT_GubaoScore, # 古宝养成积分 - 个人榜  163
-) = range(150, 163 + 1)
+Def_CBT_HorsePetTrainScore, # 骑宠养成积分 - 个人榜  164
+) = range(150, 164 + 1)
 
 # 跨服榜单最大数据名次,没有设置的默认100
 CrossBillboard_MaxDataCount = {
@@ -866,6 +878,7 @@
                                Def_CBT_BossTrialSubmitBak:1000,
                                Def_CBT_XianXiaMJScore:1000,
                                Def_CBT_GubaoScore:1000,
+                               Def_CBT_HorsePetTrainScore:1000,
                                }
 
 #职业对应战力排行榜类型
@@ -1131,7 +1144,8 @@
 CDBPlayerRefresh_BossTrial, # 凭证积分 262
 CDBPlayerRefresh_GatherSoul, # 聚魂精华 263
 CDBPlayerRefresh_BossFinalHurtPer,  # Boss最终输出伤害百分比 264
-) = range(146, 265)
+CDBPlayerRefresh_HorsePetTrainScore, # 骑宠养成积分 265
+) = range(146, 266)
 
 TYPE_Price_Gold_Paper_Money = 5    # 金钱类型,(先用礼券,再用金子)
 TYPE_Price_Family_Contribution = 6 # 战盟贡献度(活跃度转换得来)
@@ -1164,6 +1178,7 @@
 TYPE_Price_Lingyu = 42    # 灵玉
 TYPE_Price_BossTrial = 43    # boss历练凭证积分
 TYPE_Price_GatherSoul = 44    # 聚魂精华
+TYPE_Price_HorsePetTrainScore = 45    # 骑宠养成积分
 TYPE_Price_PayCoin = 99    # 代币
 
 #key可用于遍历所有货币,value仅GM相关会用到
@@ -1171,7 +1186,7 @@
                  1:"仙玉", 2:"绑玉", 3:"铜钱", 6:"战盟贡献度", 10:"战盟仓库积分", 13:"境界修行点", 14:"符印融合石", 15:"仙盟活跃令", 
                  16:"助战积分", 18:"荣誉", 19:"Boss积分", 23:"符印精华", 24:"符印碎片", 25:"寻宝积分", 26:"集市额度", 27:"丹精", 28:"魂尘", 
                  29:"聚魂碎片", 30:"核心环", 31:"功能特权令", 32:"环保值", 33:"GM令", 34:"古神币", 35:"功德点", 
-                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 99:"代币"
+                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 99:"代币"
                  }
 
 #以下是旧的金钱类型
@@ -1205,6 +1220,7 @@
                            TYPE_Price_FamilyFlagWarPoint:CDBPlayerRefresh_FamilyFlagWarPoint,
                            TYPE_Price_BossTrial:CDBPlayerRefresh_BossTrial,
                            TYPE_Price_GatherSoul:CDBPlayerRefresh_GatherSoul,
+                           TYPE_Price_HorsePetTrainScore:CDBPlayerRefresh_HorsePetTrainScore,
                            }
 
 # 支持负值的货币及对应0418刷新类型
@@ -1635,6 +1651,7 @@
 ClientServerMsg_FuncTeamMemOP = "FuncTeamMemOP"   # 功能队伍成员操作
 ClientServerMsg_QueryFuncTeam = "QueryFuncTeam"   # 查询功能队伍
 ClientServerMsg_GubaoScore = "GubaoScore" # 古宝养成积分
+ClientServerMsg_HorsePetTrainScore = "HorsePetTrainScore" # 骑宠养成积分
 
 #跨服广播类型定义
 CrossNotify_CrossAct = "CrossAct"
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 975a73b..b7d8b2c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -79,7 +79,7 @@
 Def_BuffValue_Count = 3     # buff记录的value个数
 
 #游戏对象属性--------------------------------------------
-Def_Calc_AllAttrType_MAX = 177
+Def_Calc_AllAttrType_MAX = 180
 #基本属性BUFF计算,顺序与 ObjProperty_AttrByIndex 对应,同时也为buff效果ID同步通知策划
 TYPE_Calc_AttrList = (
 TYPE_Calc_Metal,                        # 金 1
@@ -270,6 +270,9 @@
 TYPE_Calc_SuperHitHurtPer,               # 强化暴伤
 TYPE_Calc_SuperHitHurtDefPer,            # 弱化暴伤 175
 TYPE_Calc_BossFinalHurtPer,              # boss最终伤害百分比
+TYPE_Calc_FaQiMaxHPPer,                  # 法器生命百分比 
+TYPE_Calc_FaQiAtkPer,                    # 法器攻击百分比 
+TYPE_Calc_FaQiDefPer,                    # 法器防御百分比 
 ) = range(1, Def_Calc_AllAttrType_MAX)
 
 ## 支持大数值属性,超过20E
@@ -520,6 +523,7 @@
 Def_Effect_GuajiAward = 266    #直接给挂机收益,A值分钟
 Def_Effect_ItemCount = 267     #自动转化为对应物品ID的个数,不存背包
 Def_Effect_GubaoPiece = 270     #古宝碎片效果ID, A值-古宝ID
+Def_Effect_TrainRealmLV = 272     #境界培养卡,值A-功能(1-坐骑;2-灵宠;3-灵器), 值B-境界
 #----以下未使用或代码依然存在的---
 Def_Effect_ItemGiveGongXun = 1920        #使用道具给予功勋
 Def_Effect_ItemGiveRuneJH = 1925       #使用道具给予符印精华
@@ -3385,6 +3389,9 @@
 Def_PlayerKey_BaseDefAddPer = "BaseDefAddPer" # 基础防御百分比
 Def_PlayerKey_BaseHitAddPer = "BaseHitAddPer" # 基础命中百分比
 Def_PlayerKey_BaseMissAddPer = "BaseMissAddPer" # 基础闪避百分比
+Def_PlayerKey_FaQiMaxHPPer = "FaQiMaxHPPer" # 法器生命百分比
+Def_PlayerKey_FaQiAtkPer = "FaQiAtkPer" # 法器攻击百分比
+Def_PlayerKey_FaQiDefPer = "FaQiDefPer" # 法器防御百分比
 Def_PlayerKey_GodWeaponMaxHPPer = "GodWeaponMaxHPPer" # 神兵生命百分比
 Def_PlayerKey_GodWeaponAtkPer = "GodWeaponAtkPer" # 神兵攻击百分比
 Def_PlayerKey_StoneMaxHPPer = "StoneMaxHPPer" # 宝石生命百分比
@@ -3713,6 +3720,7 @@
 Def_PDict_TJGDeadPayTime = "TJGDeadPayTime"  # 脱机被杀后可补偿的时间
 Def_PDict_TJGDeadExp = "TJGDeadExp"  # 脱机被杀经验
 Def_PDict_TJGDeadExp1 = "TJGDeadExp1"  # 脱机被杀经验 亿
+Def_PDict_TrainRealmLV = "TrainRealmLV_%s"  # 培养境界等级,参数(培养功能 1-坐骑;2-灵宠;3-灵器)
 
 Def_PDict_LoginClientType = "LoginClientType"  # 客户端登录类型
 
@@ -4110,6 +4118,11 @@
 Def_PDict_CA_GubaoID = "CA_GubaoID"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值
 Def_PDict_ActGubaoID = "ActGubaoID_%s"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值,参数:(活动编号)
 Def_PDict_ActGubaoScore = "ActGubaoScore_%s"  # 养成积分,参数:(活动编号)
+
+#骑宠养成活动
+Def_PDict_CA_HorsePetTrainID = "CA_HorsePetTrainID"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值
+Def_PDict_ActHorsePetTrainID = "ActHorsePetTrainID_%s"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值,参数:(活动编号)
+Def_PDict_ActHorsePetTrainScore = "ActHorsePetTrainScore_%s"  # 累计获得活动养成积分,参数:(活动编号)
 
 #天帝礼包活动
 Def_PDict_GodGiftID = "ActGodGiftID_%s"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值,参数:(活动编号)
@@ -4818,6 +4831,9 @@
     ShareDefine.Def_Effect_BaseDefAddPer:[[TYPE_Calc_BaseDefAddPer], False, TYPE_NoLinear],
     ShareDefine.Def_Effect_BaseHitAddPer:[[TYPE_Calc_BaseHitAddPer], False, TYPE_NoLinear],
     ShareDefine.Def_Effect_BaseMissAddPer:[[TYPE_Calc_BaseMissAddPer], False, TYPE_NoLinear],
+    ShareDefine.Def_Effect_FaQiMaxHPPer:[[TYPE_Calc_FaQiMaxHPPer], False, TYPE_NoLinear],
+    ShareDefine.Def_Effect_FaQiAtkPer:[[TYPE_Calc_FaQiAtkPer], False, TYPE_NoLinear],
+    ShareDefine.Def_Effect_FaQiDefPer:[[TYPE_Calc_FaQiDefPer], False, TYPE_NoLinear],
     ShareDefine.Def_Effect_GodWeaponMaxHPPer:[[TYPE_Calc_GodWeaponMaxHPPer], False, TYPE_NoLinear],
     ShareDefine.Def_Effect_GodWeaponAtkPer:[[TYPE_Calc_GodWeaponAtkPer], False, TYPE_NoLinear],
     ShareDefine.Def_Effect_StoneMaxHPPer:[[TYPE_Calc_StoneMaxHPPer], False, TYPE_NoLinear],
@@ -4846,6 +4862,9 @@
                         TYPE_Calc_BaseDefAddPer:[TYPE_Calc_AttrDEF],
                         TYPE_Calc_BaseHitAddPer:[TYPE_Calc_AttrHit],
                         TYPE_Calc_BaseMissAddPer:[TYPE_Calc_AttrMiss],
+                        TYPE_Calc_FaQiMaxHPPer:[TYPE_Calc_AttrMaxHP],
+                        TYPE_Calc_FaQiAtkPer:[TYPE_Calc_AttrATKMin, TYPE_Calc_AttrATKMax],
+                        TYPE_Calc_FaQiDefPer:[TYPE_Calc_AttrDEF],
                         TYPE_Calc_GodWeaponMaxHPPer:[TYPE_Calc_AttrMaxHP],
                         TYPE_Calc_GodWeaponAtkPer:[TYPE_Calc_AttrATKMin, TYPE_Calc_AttrATKMax],
                         TYPE_Calc_StoneMaxHPPer:[TYPE_Calc_AttrMaxHP],
@@ -6114,7 +6133,14 @@
 ActTaskType_XianXiaMJLottery, # 仙匣秘境寻宝x次 6
 ActTaskType_XianXiaMJLayer, # 仙匣秘境达到x层 7
 ActTaskType_TreasureGubao, # 古宝寻宝x次 8
-) = range(1, 1 + 8)
+ActTaskType_HorseUpItem, # 消耗X个坐骑经验丹 9
+ActTaskType_PetUpItem, # 消耗X个灵宠经验丹 10
+ActTaskType_HorseTrainItem2, # 消耗X个坐骑培养2道具 11
+ActTaskType_PetTrainItem2, # 消耗X个灵宠培养2道具 12
+ActTaskType_HorseTrainItem3, # 消耗X个坐骑培养3道具 13
+ActTaskType_PetTrainItem3, # 消耗X个灵宠培养3道具 14
+ActTaskType_HorsePetActScore, # 获得X点骑宠养成积分 15
+) = range(1, 1 + 15)
 
 # 套装枚举,普通套装,强化套装
 (EquipSuitType_Normal,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index c35a90c..0274bc3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -35952,6 +35952,280 @@
 
 
 #------------------------------------------------------
+# AA 84 骑宠养成活动信息 #tagMCActHorsePetTrainInfo
+
+class  tagMCActHorsePetTrainItem(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(tagMCActHorsePetTrainItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 84 骑宠养成活动信息 //tagMCActHorsePetTrainInfo:
+                                ItemID:%d,
+                                ItemCount:%d,
+                                IsBind:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount,
+                                self.IsBind
+                                )
+        return DumpString
+
+
+class  tagMCActHorsePetTrainBillard(Structure):
+    Rank = 0    #(DWORD Rank)// 名次,1-代表第一名;支持夸段,如1,3 代表第1名,第2~3名
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCActHorsePetTrainItem> 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 = tagMCActHorsePetTrainItem()
+            _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  tagMCActHorsePetTrainInfo(Structure):
+    Head = tagHead()
+    ActNum = 0    #(BYTE ActNum)// 活动编号
+    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
+    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
+    JoinStartTime = ""    #(char JoinStartTime[5])// 参与开始时间点 mm:ss
+    JoinEndTime = ""    #(char JoinEndTime[5])// 参与结束时间点 mm:ss
+    LimitLV = 0    #(WORD LimitLV)// 限制等级
+    ShopType = 0    #(WORD ShopType)// 开放商店类型,可能为0不开放
+    PersonalBillCount = 0    #(BYTE PersonalBillCount)
+    PersonalBillboardInfoList = list()    #(vector<tagMCActHorsePetTrainBillard> PersonalBillboardInfoList)// 个人榜单奖励信息列表,如果没有代表本次活动没有该榜奖励
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x84
+        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.JoinStartTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.JoinEndTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.LimitLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.ShopType,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.PersonalBillCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.PersonalBillCount):
+            temPersonalBillboardInfoList = tagMCActHorsePetTrainBillard()
+            _pos = temPersonalBillboardInfoList.ReadData(_lpData, _pos)
+            self.PersonalBillboardInfoList.append(temPersonalBillboardInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x84
+        self.ActNum = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.JoinStartTime = ""
+        self.JoinEndTime = ""
+        self.LimitLV = 0
+        self.ShopType = 0
+        self.PersonalBillCount = 0
+        self.PersonalBillboardInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 10
+        length += 10
+        length += 5
+        length += 5
+        length += 2
+        length += 2
+        length += 1
+        for i in range(self.PersonalBillCount):
+            length += self.PersonalBillboardInfoList[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.WriteString(data, 5, self.JoinStartTime)
+        data = CommFunc.WriteString(data, 5, self.JoinEndTime)
+        data = CommFunc.WriteWORD(data, self.LimitLV)
+        data = CommFunc.WriteWORD(data, self.ShopType)
+        data = CommFunc.WriteBYTE(data, self.PersonalBillCount)
+        for i in range(self.PersonalBillCount):
+            data = CommFunc.WriteString(data, self.PersonalBillboardInfoList[i].GetLength(), self.PersonalBillboardInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ActNum:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                JoinStartTime:%s,
+                                JoinEndTime:%s,
+                                LimitLV:%d,
+                                ShopType:%d,
+                                PersonalBillCount:%d,
+                                PersonalBillboardInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ActNum,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.JoinStartTime,
+                                self.JoinEndTime,
+                                self.LimitLV,
+                                self.ShopType,
+                                self.PersonalBillCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCActHorsePetTrainInfo=tagMCActHorsePetTrainInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActHorsePetTrainInfo.Head.Cmd,m_NAtagMCActHorsePetTrainInfo.Head.SubCmd))] = m_NAtagMCActHorsePetTrainInfo
+
+
+#------------------------------------------------------
+# AA 85 骑宠养成活动玩家信息 #tagMCActHorsePetTrainPlayerInfo
+
+class  tagMCActHorsePetTrainPlayerInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ActNum", c_ubyte),    # 活动编号
+                  ("Score", c_int),    # 当前活动积分
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xAA
+        self.SubCmd = 0x85
+        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 = 0x85
+        self.ActNum = 0
+        self.Score = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCActHorsePetTrainPlayerInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 85 骑宠养成活动玩家信息 //tagMCActHorsePetTrainPlayerInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ActNum:%d,
+                                Score:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ActNum,
+                                self.Score
+                                )
+        return DumpString
+
+
+m_NAtagMCActHorsePetTrainPlayerInfo=tagMCActHorsePetTrainPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCActHorsePetTrainPlayerInfo.Cmd,m_NAtagMCActHorsePetTrainPlayerInfo.SubCmd))] = m_NAtagMCActHorsePetTrainPlayerInfo
+
+
+#------------------------------------------------------
 # AA 0C 登录奖励活动信息 #tagMCActLoginAwardInfo
 
 class  tagMCActLoginAwardAction(Structure):
@@ -41353,6 +41627,231 @@
 
 m_NAtagMCCrossActGubaoInfo=tagMCCrossActGubaoInfo()
 ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCrossActGubaoInfo.Head.Cmd,m_NAtagMCCrossActGubaoInfo.Head.SubCmd))] = m_NAtagMCCrossActGubaoInfo
+
+
+#------------------------------------------------------
+# AA 86 骑宠养成跨服活动信息 #tagMCCrossActHorsePetTrainInfo
+
+class  tagMCCrossActHorsePetTrainItem(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(tagMCCrossActHorsePetTrainItem)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// AA 86 骑宠养成跨服活动信息 //tagMCCrossActHorsePetTrainInfo:
+                                ItemID:%d,
+                                ItemCount:%d,
+                                IsBind:%d
+                                '''\
+                                %(
+                                self.ItemID,
+                                self.ItemCount,
+                                self.IsBind
+                                )
+        return DumpString
+
+
+class  tagMCCrossActHorsePetTrainBillard(Structure):
+    Rank = 0    #(DWORD Rank)// 名次,1-代表第一名;支持夸段,如1,3 代表第1名,第2~3名
+    Count = 0    #(BYTE Count)// 奖励物品数
+    AwardItemList = list()    #(vector<tagMCCrossActHorsePetTrainItem> 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 = tagMCCrossActHorsePetTrainItem()
+            _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  tagMCCrossActHorsePetTrainInfo(Structure):
+    Head = tagHead()
+    ServerInfoLen = 0    #(BYTE ServerInfoLen)
+    ServerIDRangeInfo = ""    #(String ServerIDRangeInfo)//开放该活动的服务器ID范围列表,json格式 [[IDA, IDB], ...], [] 为全服
+    GroupValue1 = 0    #(BYTE GroupValue1)// 活动榜单分组值1,用于查询对应榜单
+    StartDate = ""    #(char StartDate[10])// 开始日期 y-m-d
+    EndtDate = ""    #(char EndtDate[10])// 结束日期 y-m-d
+    JoinStartTime = ""    #(char JoinStartTime[5])// 参与开始时间点 mm:ss
+    JoinEndTime = ""    #(char JoinEndTime[5])// 参与结束时间点 mm:ss
+    RankLimitPersonal = 0    #(WORD RankLimitPersonal)// 个人榜上榜积分保底限制;
+    PersonalBillCount = 0    #(BYTE PersonalBillCount)
+    PersonalBillboardInfoList = list()    #(vector<tagMCCrossActHorsePetTrainBillard> PersonalBillboardInfoList)// 个人榜单奖励信息列表,如果没有代表本次活动没有该榜奖励
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x86
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ServerInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ServerIDRangeInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ServerInfoLen)
+        self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+        self.JoinStartTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.JoinEndTime,_pos = CommFunc.ReadString(_lpData, _pos,5)
+        self.RankLimitPersonal,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.PersonalBillCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.PersonalBillCount):
+            temPersonalBillboardInfoList = tagMCCrossActHorsePetTrainBillard()
+            _pos = temPersonalBillboardInfoList.ReadData(_lpData, _pos)
+            self.PersonalBillboardInfoList.append(temPersonalBillboardInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xAA
+        self.Head.SubCmd = 0x86
+        self.ServerInfoLen = 0
+        self.ServerIDRangeInfo = ""
+        self.GroupValue1 = 0
+        self.StartDate = ""
+        self.EndtDate = ""
+        self.JoinStartTime = ""
+        self.JoinEndTime = ""
+        self.RankLimitPersonal = 0
+        self.PersonalBillCount = 0
+        self.PersonalBillboardInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += len(self.ServerIDRangeInfo)
+        length += 1
+        length += 10
+        length += 10
+        length += 5
+        length += 5
+        length += 2
+        length += 1
+        for i in range(self.PersonalBillCount):
+            length += self.PersonalBillboardInfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ServerInfoLen)
+        data = CommFunc.WriteString(data, self.ServerInfoLen, self.ServerIDRangeInfo)
+        data = CommFunc.WriteBYTE(data, self.GroupValue1)
+        data = CommFunc.WriteString(data, 10, self.StartDate)
+        data = CommFunc.WriteString(data, 10, self.EndtDate)
+        data = CommFunc.WriteString(data, 5, self.JoinStartTime)
+        data = CommFunc.WriteString(data, 5, self.JoinEndTime)
+        data = CommFunc.WriteWORD(data, self.RankLimitPersonal)
+        data = CommFunc.WriteBYTE(data, self.PersonalBillCount)
+        for i in range(self.PersonalBillCount):
+            data = CommFunc.WriteString(data, self.PersonalBillboardInfoList[i].GetLength(), self.PersonalBillboardInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ServerInfoLen:%d,
+                                ServerIDRangeInfo:%s,
+                                GroupValue1:%d,
+                                StartDate:%s,
+                                EndtDate:%s,
+                                JoinStartTime:%s,
+                                JoinEndTime:%s,
+                                RankLimitPersonal:%d,
+                                PersonalBillCount:%d,
+                                PersonalBillboardInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ServerInfoLen,
+                                self.ServerIDRangeInfo,
+                                self.GroupValue1,
+                                self.StartDate,
+                                self.EndtDate,
+                                self.JoinStartTime,
+                                self.JoinEndTime,
+                                self.RankLimitPersonal,
+                                self.PersonalBillCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCCrossActHorsePetTrainInfo=tagMCCrossActHorsePetTrainInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCCrossActHorsePetTrainInfo.Head.Cmd,m_NAtagMCCrossActHorsePetTrainInfo.Head.SubCmd))] = m_NAtagMCCrossActHorsePetTrainInfo
 
 
 #------------------------------------------------------
@@ -48982,6 +49481,114 @@
 
 
 #------------------------------------------------------
+# B1 12 培养功能境界信息 #tagMCTrainRealmLVInfo
+
+class  tagMCTrainRealmLV(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("FuncType", c_ubyte),    # 功能类型:1-坐骑;2-灵宠;3-灵器
+                  ("TrainRealmLV", 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.FuncType = 0
+        self.TrainRealmLV = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCTrainRealmLV)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 12 培养功能境界信息 //tagMCTrainRealmLVInfo:
+                                FuncType:%d,
+                                TrainRealmLV:%d
+                                '''\
+                                %(
+                                self.FuncType,
+                                self.TrainRealmLV
+                                )
+        return DumpString
+
+
+class  tagMCTrainRealmLVInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    InfoList = list()    #(vector<tagMCTrainRealmLV> InfoList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x12
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temInfoList = tagMCTrainRealmLV()
+            _pos = temInfoList.ReadData(_lpData, _pos)
+            self.InfoList.append(temInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x12
+        self.Count = 0
+        self.InfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.InfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.InfoList[i].GetLength(), self.InfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                InfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCTrainRealmLVInfo=tagMCTrainRealmLVInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCTrainRealmLVInfo.Head.Cmd,m_NAtagMCTrainRealmLVInfo.Head.SubCmd))] = m_NAtagMCTrainRealmLVInfo
+
+
+#------------------------------------------------------
 # B1 20 战令信息 #tagMCZhanlingInfo
 
 class  tagMCZhanling(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/FunctionNPCCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/FunctionNPCCommon.py
index b6efd84..6887d9f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/FunctionNPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/FunctionNPCCommon.py
@@ -275,6 +275,8 @@
         shopItem = ipyDataMgr.GetStoreByIndex(i)
         if not shopItem.GetLimitCnt():
             continue
+        if shopItem.GetRefreshLimit():
+            continue
         if shopItem.GetRefreshType() not in resetTypeList:
             continue
         dayBuyCntKey = ChConfig.Def_PDict_ShopItemDayBuyCnt % shopItem.GetID()
@@ -295,6 +297,8 @@
         shopItem = ipyDataMgr.GetStoreByIndex(i)
         if not shopItem.GetLimitCnt():
             continue
+        if shopItem.GetRefreshLimit():
+            continue
         if shopItem.GetShopType() not in shopTypeList:
             continue
         dayBuyCntKey = ChConfig.Def_PDict_ShopItemDayBuyCnt % shopItem.GetID()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TrainRealmLV.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TrainRealmLV.py
new file mode 100644
index 0000000..7ae0050
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TrainRealmLV.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.TrainRealmLV
+#
+# @todo:培养境界
+# @author hxp
+# @date 2024-08-14
+# @version 1.0
+#
+# 详细描述: 培养境界
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-08-14 16:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerControl
+
+## GM命令执行入口
+#  @param curPlayer 当前玩家
+#  @param msgList 参数列表
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+    
+    if not msgList:
+        GameWorld.DebugAnswer(curPlayer, "设置培养卡境界: TrainRealmLV 培养功能 境界")
+        GameWorld.DebugAnswer(curPlayer, "培养功能: 1-坐骑,2-灵宠,3-灵器")
+        return
+    funcType = msgList[0]
+    trainRealmLV = msgList[1] if len(msgList) > 1 else 0
+    PlayerControl.SetTrainRealmLV(curPlayer, funcType, trainRealmLV)
+    GameWorld.DebugAnswer(curPlayer, "设置培养卡境界: funcType:%s,境界:%s" % (funcType, trainRealmLV))
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index d038f4b..72eab92 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -952,6 +952,7 @@
                         ("list", "ItemListEx", 0),
                         ("DWORD", "MainItemID", 0),
                         ("list", "JobItem", 0),
+                        ("BYTE", "RefreshLimit", 0),
                         ("BYTE", "RefreshType", 0),
                         ("list", "LimitVIPLV", 0),
                         ("DWORD", "LimitLV", 0),
@@ -1504,6 +1505,23 @@
                         ("BYTE", "Rank", 0),
                         ("list", "AwardItemList", 0),
                         ("list", "MemAwardItemList", 0),
+                        ),
+
+                "ActHorsePetTrain":(
+                        ("DWORD", "CfgID", 1),
+                        ("char", "StartDate", 0),
+                        ("char", "EndDate", 0),
+                        ("char", "JoinStartTime", 0),
+                        ("char", "JoinEndTime", 0),
+                        ("WORD", "LVLimit", 0),
+                        ("WORD", "ActShopType", 0),
+                        ("WORD", "PersonalTemplateID", 0),
+                        ),
+
+                "ActHorsePetTrainBillTemp":(
+                        ("DWORD", "TemplateID", 1),
+                        ("BYTE", "Rank", 0),
+                        ("list", "AwardItemList", 0),
                         ),
 
                 "ActGubao":(
@@ -3734,17 +3752,18 @@
     def GetItemListEx(self): return self.attrTuple[6] # 扩展物品列表[[物品ID,个数,是否绑定],...] list
     def GetMainItemID(self): return self.attrTuple[7] # 标的物品ID DWORD
     def GetJobItem(self): return self.attrTuple[8] # 职业替换物品 list
-    def GetRefreshType(self): return self.attrTuple[9] # 刷新类型 0-不重置,1-onWeek0点,2-onWeek5点,3-OnDay0点,4-OnDay5点 BYTE
-    def GetLimitVIPLV(self): return self.attrTuple[10] # VIP限制 list
-    def GetLimitLV(self): return self.attrTuple[11] # 等级限制 DWORD
-    def GetLimitCnt(self): return self.attrTuple[12] # 个人限制数量 list
-    def GetServerLimitCnt(self): return self.attrTuple[13] # 全服限制数量 DWORD
-    def GetMoneyType(self): return self.attrTuple[14] # 金钱类型 BYTE
-    def GetMoneyNum(self): return self.attrTuple[15] # 金钱数量 DWORD
-    def GetMoneyOriginal(self): return self.attrTuple[16] # 原价 DWORD
-    def GetLimitValue(self): return self.attrTuple[17] # 限制条件 DWORD
-    def GetNotifyMark(self): return self.attrTuple[18] # 广播提示 char
-    def GetMailKey(self): return self.attrTuple[19] # 背包不足时邮件KEY char
+    def GetRefreshLimit(self): return self.attrTuple[9] # 是否限制刷新限购次数,即是否永久限购,包含活动也不重置 BYTE
+    def GetRefreshType(self): return self.attrTuple[10] # 刷新类型 0-不重置,1-onWeek0点,2-onWeek5点,3-OnDay0点,4-OnDay5点 BYTE
+    def GetLimitVIPLV(self): return self.attrTuple[11] # VIP限制 list
+    def GetLimitLV(self): return self.attrTuple[12] # 等级限制 DWORD
+    def GetLimitCnt(self): return self.attrTuple[13] # 个人限制数量 list
+    def GetServerLimitCnt(self): return self.attrTuple[14] # 全服限制数量 DWORD
+    def GetMoneyType(self): return self.attrTuple[15] # 金钱类型 BYTE
+    def GetMoneyNum(self): return self.attrTuple[16] # 金钱数量 DWORD
+    def GetMoneyOriginal(self): return self.attrTuple[17] # 原价 DWORD
+    def GetLimitValue(self): return self.attrTuple[18] # 限制条件 DWORD
+    def GetNotifyMark(self): return self.attrTuple[19] # 广播提示 char
+    def GetMailKey(self): return self.attrTuple[20] # 背包不足时邮件KEY char
 
 # 限时特惠表
 class IPY_ActSpringSale():
@@ -4576,6 +4595,33 @@
     def GetRank(self): return self.attrTuple[1] # 名次 BYTE
     def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] 仙盟榜时为盟主奖励,如果没有配置,则统一取成员奖励 list
     def GetMemAwardItemList(self): return self.attrTuple[3] # 仙盟榜成员奖励物品信息列表[[物品ID,个数,是否拍品], ...] list
+
+# 骑宠养成活动时间表
+class IPY_ActHorsePetTrain():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetCfgID(self): return self.attrTuple[0] # 配置ID DWORD
+    def GetStartDate(self): return self.attrTuple[1] # 开启日期 char
+    def GetEndDate(self): return self.attrTuple[2] # 结束日期 char
+    def GetJoinStartTime(self): return self.attrTuple[3] # 参与开始时间点 char
+    def GetJoinEndTime(self): return self.attrTuple[4] # 参与结束时间点 char
+    def GetLVLimit(self): return self.attrTuple[5] # 限制等级 WORD
+    def GetActShopType(self): return self.attrTuple[6] # 开放商店类型,为0时不开放 WORD
+    def GetPersonalTemplateID(self): return self.attrTuple[7] # 个人排行模板编号 WORD
+
+# 骑宠养成榜单模版表
+class IPY_ActHorsePetTrainBillTemp():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetTemplateID(self): return self.attrTuple[0] # 模板编号 DWORD
+    def GetRank(self): return self.attrTuple[1] # 名次 BYTE
+    def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
 
 # 古宝养成活动时间表
 class IPY_ActGubao():
@@ -6207,6 +6253,8 @@
         self.__LoadFileData("ActGarbageTask", onlyCheck)
         self.__LoadFileData("ActBossTrial", onlyCheck)
         self.__LoadFileData("ActBossTrialTemplate", onlyCheck)
+        self.__LoadFileData("ActHorsePetTrain", onlyCheck)
+        self.__LoadFileData("ActHorsePetTrainBillTemp", onlyCheck)
         self.__LoadFileData("ActGubao", onlyCheck)
         self.__LoadFileData("ActGubaoBillTemp", onlyCheck)
         self.__LoadFileData("ActXianXiaMJ", onlyCheck)
@@ -7492,6 +7540,20 @@
         self.CheckLoadData("ActBossTrialTemplate")
         return self.ipyActBossTrialTemplateCache[index]
 
+    def GetActHorsePetTrainCount(self):
+        self.CheckLoadData("ActHorsePetTrain")
+        return self.ipyActHorsePetTrainLen
+    def GetActHorsePetTrainByIndex(self, index):
+        self.CheckLoadData("ActHorsePetTrain")
+        return self.ipyActHorsePetTrainCache[index]
+
+    def GetActHorsePetTrainBillTempCount(self):
+        self.CheckLoadData("ActHorsePetTrainBillTemp")
+        return self.ipyActHorsePetTrainBillTempLen
+    def GetActHorsePetTrainBillTempByIndex(self, index):
+        self.CheckLoadData("ActHorsePetTrainBillTemp")
+        return self.ipyActHorsePetTrainBillTempCache[index]
+
     def GetActGubaoCount(self):
         self.CheckLoadData("ActGubao")
         return self.ipyActGubaoLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py
index 0841b1f..23f9e50 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChEquip.py
@@ -645,7 +645,7 @@
         return
     
     needRealmLV = trainIpyData.GetNeedRealmLV()
-    curRealmLV = curPlayer.GetOfficialRank()
+    curRealmLV = PlayerControl.GetTrainRealmLVReal(curPlayer, 3)
     if curRealmLV < needRealmLV:
         GameWorld.DebugLog("    境界不足,无法培养!  curRealmLV(%s) < needRealmLV(%s)" % (curRealmLV, needRealmLV))
         return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
index be25cc7..a076940 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -727,6 +727,7 @@
                             ChConfig.Def_Effect_AddVIPExp:"Item_AddVIPExp", # 增加VIP经验
                             ChConfig.Def_Effect_VIPLVCard:"Item_VIPLVCard", # VIP等级直升卡
                             ChConfig.Def_Effect_GubaoPiece:"Item_GubaoPiece", # 古宝碎片效果ID
+                            ChConfig.Def_Effect_TrainRealmLV:"Item_TrainRealmLV", # 境界培养卡
                             ChConfig.Def_Effect_ResetBossKillCnt:"Item_ResetBossKillCnt", # 重置boss击杀疲劳
                             ChConfig.Def_Effect_AddFBCnt:"Item_AddFBCnt", # 增加副本可进入次数
                             ChConfig.Def_Effect_AddArenaBattleCount:"Item_AddArenaBattleCount", # 增加竞技场挑战次数
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TrainRealmLV.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TrainRealmLV.py
new file mode 100644
index 0000000..24a45d4
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TrainRealmLV.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package UseItem.Item_TrainRealmLV
+#
+# @todo:境界培养卡
+# @author hxp
+# @date 2024-08-14
+# @version 1.0
+#
+# 详细描述: 境界培养卡 值A-功能(1-坐骑;2-灵宠;3-灵器), 值B-境界
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-08-14 16:30"""
+#-------------------------------------------------------------------------------
+
+import ItemCommon
+import PlayerControl
+import GameWorld
+import ChConfig
+
+def BatchUseItem(curPlayer, curRoleItem, tick, useCnt, exData):
+    ##批量使用物品
+    curEff = curRoleItem.GetEffectByIndex(0)
+    funcType = curEff.GetEffectValue(0)
+    effTrainRealmLV = curEff.GetEffectValue(1)
+    
+    trainRealmLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TrainRealmLV % funcType)
+    if effTrainRealmLV > trainRealmLV:
+        PlayerControl.SetTrainRealmLV(curPlayer, funcType, effTrainRealmLV)
+        
+    GameWorld.DebugLog("境界培养卡使用: itemID=%s,funcType=%s,effTrainRealmLV=%s,trainRealmLV=%s" 
+                       % (curRoleItem.GetItemTypeID(), funcType, effTrainRealmLV, trainRealmLV))
+    succCnt = useCnt
+    saveDataDict = {}
+    ItemCommon.DelItem(curPlayer, curRoleItem, succCnt, True, ChConfig.ItemDel_Unknown, saveDataDict, True)
+    return True, succCnt
+
+
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 793c371..ffa8e74 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -114,6 +114,7 @@
 import PlayerActGarbageSorting
 import PlayerActXianXiaMJ
 import PlayerActGubao
+import PlayerActHorsePetTrain
 import PlayerActGodGift
 import PlayerActFamilyCTGAssist
 import PlayerActRechargeRebateGold
@@ -622,6 +623,7 @@
     
     PlayerControl.SyncOnLineTimeTotal(curPlayer)
     #PlayerControl.SyncOnLineTimeLastOpenPack(curPlayer, IPY_GameWorld.rptItem)
+    PlayerControl.SyncTrainRealmLV(curPlayer)
     PlayerGodWeapon.OnLogin(curPlayer)
     PlayerPrestigeSys.OnLogin(curPlayer)
     #DataRecordPack.DR_PlayerLogin(curPlayer)
@@ -891,6 +893,8 @@
     PlayerActXianXiaMJ.OnPlayerLogin(curPlayer)
     # 古宝养成活动
     PlayerActGubao.OnPlayerLogin(curPlayer)
+    # 骑宠养成活动
+    PlayerActHorsePetTrain.OnPlayerLogin(curPlayer)
     # 天帝礼包活动
     PlayerActGodGift.OnPlayerLogin(curPlayer)
     # 多日连充活动
@@ -1083,6 +1087,8 @@
     PlayerActXianXiaMJ.OnMixFirstLogin(curPlayer)
     # 古宝养成
     PlayerActGubao.OnMixFirstLogin(curPlayer)
+    # 骑宠养成
+    PlayerActHorsePetTrain.OnMixFirstLogin(curPlayer)
     # 重置玩家改名次数
     #UpdatePlayerName.ResetChangeNameCnt(curPlayer)
     return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActHorsePetTrain.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActHorsePetTrain.py
new file mode 100644
index 0000000..4e4fe4e
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActHorsePetTrain.py
@@ -0,0 +1,301 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerActHorsePetTrain
+#
+# @todo:骑宠养成活动
+# @author hxp
+# @date 2024-08-14
+# @version 1.0
+#
+# 详细描述: 骑宠养成活动
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-08-14 16:30"""
+#-------------------------------------------------------------------------------
+
+import PyGameData
+import ShareDefine
+import PlayerControl
+import IpyGameDataPY
+import CrossRealmPlayer
+import FunctionNPCCommon
+import PlayerBillboard
+import ChPyNetSendPack
+import NetPackCommon
+import PlayerActTask
+import GameWorld
+import ChConfig
+
+def OnMixFirstLogin(curPlayer):
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_HorsePetTrain, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        if not actInfo.get(ShareDefine.ActKey_State):
+            continue
+        score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ActHorsePetTrainScore % actNum)
+        if not score:
+            continue
+        GameWorld.Log("骑宠养成合服首登同步积分榜单: actNum=%s,score=%s" % (actNum, score), curPlayer.GetPlayerID())
+        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_HorsePetTrainScore, score, autoSort=True)
+        break
+    
+    return
+
+def OnPlayerLogin(curPlayer):
+    
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_HorsePetTrain, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        isReset = __CheckPlayerHorsePetTrainAction(curPlayer, actNum)
+        if not isReset:
+            # 活动中同步活动信息
+            if actInfo.get(ShareDefine.ActKey_State):
+                Sync_HorsePetTrainActionInfo(curPlayer, actNum)
+                Sync_HorsePetTrainPlayerInfo(curPlayer, actNum)
+                
+    if not __CheckPlayerCrossActHorsePetTrain(curPlayer):
+        Sync_CrossActHorsePetTrainActionInfo(curPlayer)
+        
+    return
+
+def RefreshHorsePetTrainActionInfo(actNum):
+    ## 收到GameServer同步的活动信息,刷新活动信息
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(index)
+        if curPlayer.GetID() == 0:
+            continue
+        __CheckPlayerHorsePetTrainAction(curPlayer, actNum)
+    return
+
+def __CheckPlayerHorsePetTrainAction(curPlayer, actNum):
+    ## 检查玩家活动数据信息
+    
+    playerID = curPlayer.GetPlayerID()
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_HorsePetTrain, actNum)
+    actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+    state = actInfo.get(ShareDefine.ActKey_State, 0)
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+    
+    playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ActHorsePetTrainID % actNum) # 玩家身上的活动ID
+    
+    # 活动ID 相同的话不处理
+    if actID == playerActID:
+        GameWorld.DebugLog("骑宠养成活动ID不变,不处理!actNum=%s,actID=%s" % (actNum, actID), playerID)
+        return
+    
+    GameWorld.DebugLog("骑宠养成活动重置! actNum=%s,actID=%s,playerActID=%s,state=%s,cfgID=%s" 
+                       % (actNum, actID, playerActID, state, cfgID), playerID)
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ActHorsePetTrainID % actNum, actID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ActHorsePetTrainScore % actNum, 0)
+    
+    if state:
+        cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+        ipyData = IpyGameDataPY.GetIpyGameData("ActHorsePetTrain", cfgID)
+        if ipyData and ipyData.GetActShopType():
+            FunctionNPCCommon.ResetShopItemBuyCountByShopType(curPlayer, [ipyData.GetActShopType()])
+        Sync_HorsePetTrainActionInfo(curPlayer, actNum)
+        Sync_HorsePetTrainPlayerInfo(curPlayer, actNum)
+    return True
+
+def RefreshCrossActHorsePetTrainInfo():
+    ## 收到GameServer同步的活动信息,刷新活动信息
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(index)
+        if curPlayer.GetID() == 0:
+            continue
+        __CheckPlayerCrossActHorsePetTrain(curPlayer)
+        
+    return
+
+def __CheckPlayerCrossActHorsePetTrain(curPlayer):
+    
+    playerID = curPlayer.GetPlayerID()
+    
+    actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_HorsePetTrain)
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
+    actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+    state = actInfo.get(ShareDefine.ActKey_State, 0)
+    dayIndex = actInfo.get(ShareDefine.ActKey_DayIndex, 0)
+    
+    playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CA_HorsePetTrainID) # 玩家身上的活动ID
+    
+    # 活动ID 相同的话不处理
+    if actID == playerActID:
+        GameWorld.DebugLog("跨服骑宠养成活动ID不变,不处理!cfgID=%s,dayIndex=%s,actID=%s" % (cfgID, dayIndex, actID), playerID)   
+        return
+    GameWorld.DebugLog("跨服骑宠养成活动重置! cfgID=%s,actID=%s,playerActID=%s,state=%s" % (cfgID, actID, playerActID, state), playerID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CA_HorsePetTrainID, actID)
+    
+    if not state:
+        CrossRealmPlayer.NotifyCrossActEnd(curPlayer, ShareDefine.CrossActName_HorsePetTrain)
+        
+    Sync_CrossActHorsePetTrainActionInfo(curPlayer)
+    return True
+
+def OnHorsePetTrainCost(curPlayer, costItemDict):
+    
+    playerID = curPlayer.GetPlayerID()
+    for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_HorsePetTrain, {}).values():
+        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
+        if not actInfo.get(ShareDefine.ActKey_State):
+            continue
+        
+        crossActInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_HorsePetTrain)
+        if crossActInfo.get(ShareDefine.ActKey_State, 0):
+            if crossActInfo.get(ShareDefine.ActKey_StateJoin) != ShareDefine.ActStateJoin_Start:
+                GameWorld.Log("跨服骑宠养成非参与活动中: actNum=%s" % actNum, playerID)
+                continue
+        else:
+            if actInfo.get(ShareDefine.ActKey_StateJoin) != ShareDefine.ActStateJoin_Start:
+                GameWorld.Log("骑宠养成非参与活动中: actNum=%s" % actNum, playerID)
+                continue
+            
+        addActScore = 0
+        itemScoreDict = IpyGameDataPY.GetFuncEvalCfg("HorsePetTrainAct", 1, {})
+        for itemID, costCount in costItemDict.items():
+            if str(itemID) not in itemScoreDict:
+                continue
+            itemScore = costCount * itemScoreDict[str(itemID)]
+            addActScore += itemScore
+            GameWorld.DebugLog("骑宠养成活动消耗物品积分统计: actNum=%s,itemID=%s,costCount=%s,itemScore=%s, %s" 
+                               % (actNum, itemID, costCount, itemScore, addActScore))
+            
+        if addActScore <= 0:
+            continue
+        
+        AddPlayerScore(curPlayer, actNum, addActScore)
+        
+    return
+
+def AddPlayerScore(curPlayer, actNum, addScore):
+    if addScore <= 0:
+        return 0
+    score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ActHorsePetTrainScore % actNum)
+    updScore = score + addScore
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ActHorsePetTrainScore % actNum, updScore)
+    GameWorld.DebugLog("骑宠养成活动增加积分: actNum=%s,addScore=%s,updScore=%s" % (actNum, addScore, updScore))
+    Sync_HorsePetTrainPlayerInfo(curPlayer, actNum)
+    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_HorsePetTrainScore, addScore, "ActHorsePetTrain")
+    PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorsePetActScore, addScore)
+    PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_HorsePetTrainScore, updScore, autoSort=True)
+    SendToGameServer_HorsePetTrain(curPlayer, "AddHorsePetTrainScore", [addScore, updScore])
+    return updScore
+
+def SendToGameServer_HorsePetTrain(curPlayer, msgType, dataMsg=""):
+    playerID = curPlayer.GetPlayerID()
+    msgList = str([msgType, dataMsg])
+    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "ActHorsePetTrain", msgList, len(msgList))
+    GameWorld.Log("骑宠养成活动发送GameServer: %s, %s" % (msgType, dataMsg), playerID)
+    return
+
+def Sync_HorsePetTrainActionInfo(curPlayer, actNum):
+    ## 通知活动信息
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_HorsePetTrain, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActHorsePetTrain", cfgID)
+    if not ipyData:
+        return
+    
+    personalTempID = ipyData.GetPersonalTemplateID()
+    personalTempIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActHorsePetTrainBillTemp", personalTempID) if personalTempID else []
+    
+    startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)
+    
+    clientPack = ChPyNetSendPack.tagMCActHorsePetTrainInfo()
+    clientPack.ActNum = actNum
+    clientPack.StartDate = startDateStr
+    clientPack.EndtDate = endDateStr
+    clientPack.JoinStartTime = ipyData.GetJoinStartTime()
+    clientPack.JoinEndTime = ipyData.GetJoinEndTime()
+    clientPack.LimitLV = ipyData.GetLVLimit()
+    clientPack.ShopType = ipyData.GetActShopType()
+    
+    clientPack.PersonalBillboardInfoList = __GetTempRankBillPackList(personalTempIpyDataList)
+    clientPack.PersonalBillCount = len(clientPack.PersonalBillboardInfoList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def Sync_HorsePetTrainPlayerInfo(curPlayer, actNum):
+    
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_HorsePetTrain, actNum)
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    clientPack = ChPyNetSendPack.tagMCActHorsePetTrainPlayerInfo()
+    clientPack.ActNum = actNum
+    clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ActHorsePetTrainScore % actNum)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def Sync_CrossActHorsePetTrainActionInfo(curPlayer):
+    ## 通知活动信息
+    actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, ShareDefine.CrossActName_HorsePetTrain)
+    if not actInfo:
+        return
+    
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return
+    
+    ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+    if not ipyDataDict:
+        return
+    
+    personalTempID = ipyDataDict.get("PersonalTemplateID", 0)
+    personalTempIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActHorsePetTrainBillTemp", personalTempID) if personalTempID else []
+    
+    clientPack = ChPyNetSendPack.tagMCCrossActHorsePetTrainInfo()
+    clientPack.ServerIDRangeInfo = str(actInfo.get(ShareDefine.ActKey_ServerIDRangeList, []))
+    clientPack.ServerInfoLen = len(clientPack.ServerIDRangeInfo)
+    clientPack.GroupValue1 = ipyDataDict.get("ZoneID", 0)
+    clientPack.StartDate = ipyDataDict.get("StartDate", "")
+    clientPack.EndtDate = ipyDataDict.get("EndDate", "")
+    clientPack.JoinStartTime = ipyDataDict.get("JoinStartTime", "")
+    clientPack.JoinEndTime = ipyDataDict.get("JoinEndTime", "")
+    clientPack.RankLimitPersonal = ipyDataDict.get("RankLimitPersonal", 0)
+    
+    clientPack.PersonalBillboardInfoList = __GetTempRankBillPackList(personalTempIpyDataList)
+    clientPack.PersonalBillCount = len(clientPack.PersonalBillboardInfoList)
+    
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def __GetTempRankBillPackList(ipyDataList):
+    packBillList = []
+    if not ipyDataList:
+        return packBillList
+    for tempIpyData in ipyDataList:
+        rankInfo = ChPyNetSendPack.tagMCActHorsePetTrainBillard()
+        rankInfo.Rank = tempIpyData.GetRank()
+        
+        rankInfo.AwardItemList = []
+        awardItemList = tempIpyData.GetAwardItemList()
+        for itemID, itemCount, isAuctionItem in awardItemList:
+            item = ChPyNetSendPack.tagMCActHorsePetTrainItem()
+            item.Clear()
+            item.ItemID = itemID
+            item.ItemCount = itemCount
+            item.IsBind = isAuctionItem
+            rankInfo.AwardItemList.append(item)
+        rankInfo.Count = len(rankInfo.AwardItemList)
+        
+#        rankInfo.MemAwardItemList = []
+#        memAwardItemList = tempIpyData.GetMemAwardItemList()
+#        for itemID, itemCount, isAuctionItem in memAwardItemList:
+#            item = ChPyNetSendPack.tagMCActHorsePetTrainItem()
+#            item.Clear()
+#            item.ItemID = itemID
+#            item.ItemCount = itemCount
+#            item.IsBind = isAuctionItem
+#            rankInfo.MemAwardItemList.append(item)
+#        rankInfo.MemCount = len(rankInfo.MemAwardItemList)
+        
+        packBillList.append(rankInfo)
+    return packBillList
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTask.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTask.py
index 62a8904..4db63b4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTask.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActTask.py
@@ -290,6 +290,27 @@
     Sync_ActTaskPlayerInfo(curPlayer, actNum)
     return
 
+def GetActTaskTypeList(actNum):
+    taskTypeList = []
+    actInfo = GameWorld.GetActInfo(ShareDefine.OperationActionName_ActTask, actNum)
+    if not actInfo:
+        return taskTypeList
+    if not actInfo.get(ShareDefine.ActKey_State):
+        return taskTypeList
+    cfgID = actInfo.get(ShareDefine.ActKey_CfgID)
+    ipyData = IpyGameDataPY.GetIpyGameData("ActTask", cfgID)
+    if not ipyData:
+        return taskTypeList
+    templateID = ipyData.GetTemplateID()
+    taskIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActTaskTemp", templateID)
+    if not taskIpyDataList:
+        return taskTypeList
+    for taskIpyData in taskIpyDataList:
+        taskType = taskIpyData.GetTaskType()
+        if taskType not in taskTypeList:
+            taskTypeList.append(taskType)
+    return taskTypeList
+
 def Sync_ActTaskPlayerInfo(curPlayer, actNum):
     ## 通知活动玩家信息
     templateID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ActTaskTempID % actNum)
@@ -308,7 +329,7 @@
 def Sync_ActTaskPlayerValueInfo(curPlayer, actNum, taskTypeList=None):
     ## 通知活动玩家信息
     if taskTypeList == None:
-        taskTypeList = ChConfig.ActTaskTypeList
+        taskTypeList = GetActTaskTypeList(actNum)
         
     clientPack = ChPyNetSendPack.tagMCActTaskPlayerValueInfo()
     clientPack.ActNum = actNum
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index bc68945..9f9dc3f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -4820,6 +4820,9 @@
                            ChConfig.TYPE_Calc_BaseDefAddPer:baseAttrList,
                            ChConfig.TYPE_Calc_BaseHitAddPer:baseAttrList,
                            ChConfig.TYPE_Calc_BaseMissAddPer:baseAttrList,
+                           ChConfig.TYPE_Calc_FaQiMaxHPPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FaQi],
+                           ChConfig.TYPE_Calc_FaQiAtkPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FaQi],
+                           ChConfig.TYPE_Calc_FaQiDefPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FaQi],
                            ChConfig.TYPE_Calc_GodWeaponMaxHPPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_GodWeapon],
                            ChConfig.TYPE_Calc_GodWeaponAtkPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_GodWeapon],
                            ChConfig.TYPE_Calc_StoneMaxHPPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Stone],
@@ -6868,6 +6871,36 @@
 #    addAttrList[ChConfig.CalcAttr_BattleNoline] = {}
 #    return addAttrList
 #===============================================================================
+## 培养境界等级
+def GetTrainRealmLVReal(curPlayer, funcType):
+    trainRealmLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TrainRealmLV % funcType)
+    return max(trainRealmLV, curPlayer.GetOfficialRank())
+def SetTrainRealmLV(curPlayer, funcType, trainRealmLV):
+    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TrainRealmLV % funcType, trainRealmLV)
+    SyncTrainRealmLV(curPlayer, funcType)
+    return
+def SyncTrainRealmLV(curPlayer, funcType=None):
+    if funcType == None:
+        syncFuncTypeList = range(1, 1 + 10)
+    else:
+        syncFuncTypeList = [funcType]
+    infoList = []
+    for fType in syncFuncTypeList:
+        trainRealmLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TrainRealmLV % fType)
+        if not trainRealmLV and funcType == None:
+            continue
+        lvInfo = ChPyNetSendPack.tagMCTrainRealmLV()
+        lvInfo.FuncType = fType
+        lvInfo.TrainRealmLV = trainRealmLV
+        infoList.append(lvInfo)
+    if not infoList:
+        return
+    clientPack = ChPyNetSendPack.tagMCTrainRealmLVInfo()
+    clientPack.InfoList = infoList
+    clientPack.Count = len(clientPack.InfoList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
 ## 魅力等级
 def GetCharmLV(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CharmLV)
 def SetCharmLV(curPlayer, charmLV):
@@ -7093,6 +7126,15 @@
 # 基础闪避百分比
 def GetBaseMissAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BaseMissAddPer)
 def SetBaseMissAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BaseMissAddPer, value)
+# 法器生命百分比
+def GetFaQiMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaQiMaxHPPer)
+def SetFaQiMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaQiMaxHPPer, value)
+# 法器攻击百分比
+def GetFaQiAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaQiAtkPer)
+def SetFaQiAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaQiAtkPer, value)
+# 法器防御百分比
+def GetFaQiDefPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaQiDefPer)
+def SetFaQiDefPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaQiDefPer, value)
 # 神兵生命百分比
 def GetGodWeaponMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GodWeaponMaxHPPer)
 def SetGodWeaponMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GodWeaponMaxHPPer, value)
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 7555dab..d315b2f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -83,6 +83,7 @@
 import PlayerActGarbageSorting
 import PlayerActXianXiaMJ
 import PlayerActGubao
+import PlayerActHorsePetTrain
 import PlayerActGodGift
 import PlayerActFamilyCTGAssist
 import PlayerActRechargeRebateGold
@@ -1424,6 +1425,9 @@
             elif actionName == ShareDefine.OperationActionName_Gubao:
                 PlayerActGubao.RefreshGubaoActionInfo(actNum)
                 
+            elif actionName == ShareDefine.OperationActionName_HorsePetTrain:
+                PlayerActHorsePetTrain.RefreshHorsePetTrainActionInfo(actNum)
+                
             elif actionName == ShareDefine.OperationActionName_GodGift:
                 PlayerActGodGift.RefreshGodGiftActionInfo(actNum)
                 
@@ -1546,6 +1550,9 @@
             elif actionName == ShareDefine.CrossActName_Gubao:
                 PlayerActGubao.RefreshCrossActGubaoInfo()
                 
+            elif actionName == ShareDefine.CrossActName_HorsePetTrain:
+                PlayerActHorsePetTrain.RefreshCrossActHorsePetTrainInfo()
+                
             return
         
         if key == ShareDefine.Def_Notify_WorldKey_CrossZoneName:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
index a7a4d97..b0a472f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
@@ -36,6 +36,8 @@
 import IpyGameDataPY
 import CrossPlayerData
 import PlayerSuccess
+import PlayerActHorsePetTrain
+import PlayerActTask
 import PlayerPet
 
 import time
@@ -645,6 +647,9 @@
     Sync_HorseClassData(curPlayer)
     # 刷属性,更新排行榜
     RefreshHorseAttr(curPlayer)
+    
+    PlayerActHorsePetTrain.OnHorsePetTrainCost(curPlayer, {costItemID:costItemCount})
+    PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseUpItem, costItemCount)
     return
 
 #// A5 31 坐骑培养 #tagCMHorseTrain
@@ -677,7 +682,7 @@
         return
     
     needRealmLV = trainIpyData.GetNeedRealmLV()
-    curRealmLV = curPlayer.GetOfficialRank()
+    curRealmLV = PlayerControl.GetTrainRealmLVReal(curPlayer, 1)
     if curRealmLV < needRealmLV:
         GameWorld.DebugLog("    境界不足,无法培养!  curRealmLV(%s) < needRealmLV(%s)" % (curRealmLV, needRealmLV))
         return
@@ -724,6 +729,12 @@
     Sync_HorseClassData(curPlayer)
     # 刷属性,更新排行榜
     RefreshHorseAttr(curPlayer)
+    
+    PlayerActHorsePetTrain.OnHorsePetTrainCost(curPlayer, {costItemID:costItemCount})
+    if trainType == 2:
+        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseTrainItem2, costItemCount)
+    elif trainType == 3:
+        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_HorseTrainItem3, costItemCount)
     return
 
 #// A5 35 坐骑升星 #tagCMHorseStarUp
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py
index 8021f3a..cc3bd5d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPet.py
@@ -45,6 +45,8 @@
 import PlayerActivity
 import ChPyNetSendPack
 import NetPackCommon
+import PlayerActHorsePetTrain
+import PlayerActTask
 import PlayerHorse
 import GameObj
 
@@ -768,6 +770,8 @@
         
     #EventReport.WriteEvent_pet_class(curPlayer, petNpcData.GetName(), classLV, petClassExp, updClassLV, newClassExp)
     
+    PlayerActHorsePetTrain.OnHorsePetTrainCost(curPlayer, {autoBuyItemID:costItemCount})
+    PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_PetUpItem, costItemCount)
     return
 
 def GetTotalPetLV(curPlayer):
@@ -1067,7 +1071,7 @@
         return
     
     needRealmLV = trainIpyData.GetNeedRealmLV()
-    curRealmLV = curPlayer.GetOfficialRank()
+    curRealmLV = PlayerControl.GetTrainRealmLVReal(curPlayer, 2)
     if curRealmLV < needRealmLV:
         GameWorld.DebugLog("    境界不足,无法培养!  curRealmLV(%s) < needRealmLV(%s)" % (curRealmLV, needRealmLV))
         return
@@ -1114,6 +1118,12 @@
     Sync_PetTrainData(curPlayer)
     # 刷属性,更新排行榜
     RefreshPetItemAddAttr(curPlayer, True)
+    
+    PlayerActHorsePetTrain.OnHorsePetTrainCost(curPlayer, {costItemID:costItemCount})
+    if trainType == 2:
+        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_PetTrainItem2, costItemCount)
+    elif trainType == 3:
+        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_PetTrainItem3, costItemCount)
     return
 
 #// A7 06 宠物升星 #tagCMPetStarUp
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 5b7caff..48d54ec 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -295,6 +295,7 @@
 OperationActionName_BuyCountGift = "ActBuyCountGift" # 购买次数礼包活动
 OperationActionName_FamilyCTGAssist = "ActFamilyCTGAssist" # 仙盟充值协助
 OperationActionName_Gubao = "ActGubao" # 古宝养成活动
+OperationActionName_HorsePetTrain = "ActHorsePetTrain" # 骑宠养成活动
 #节日活动类型列表 - 该类型无视开服天,日期到了就开启
 FeastOperationActionNameList = [OperationActionName_FeastWeekParty, OperationActionName_FeastRedPacket,
                                 OperationActionName_RechargeRebateGold, OperationActionName_GrowupBuy,
@@ -317,7 +318,7 @@
                            OperationActionName_BuyOne, OperationActionName_BossTrial,
                            OperationActionName_ActLoginNew, OperationActionName_ActTask,
                            OperationActionName_BuyCountGift, OperationActionName_FamilyCTGAssist,
-                           OperationActionName_Gubao,
+                           OperationActionName_Gubao, OperationActionName_HorsePetTrain,
                            ] + FeastOperationActionNameList
 #需要记录开启活动时的世界等级的运营活动
 NeedWorldLVOperationActNameList = [OperationActionName_FairyCeremony, OperationActionName_WishingWell, 
@@ -344,7 +345,7 @@
                                    OperationActionName_BuyOne, OperationActionName_BossTrial,
                                    OperationActionName_ActLoginNew, OperationActionName_ActTask,
                                    OperationActionName_BuyCountGift, OperationActionName_FamilyCTGAssist,
-                                   OperationActionName_Gubao,
+                                   OperationActionName_Gubao, OperationActionName_HorsePetTrain,
                                    ]
 
 #跨服运营活动表名定义
@@ -354,9 +355,11 @@
 CrossActName_BossTrial = "CrossActBossTrial" # Boss历练 - 跨服
 CrossActName_XianXiaMJ = "CrossActXianXiaMJ" # 仙匣秘境 - 跨服
 CrossActName_Gubao = "CrossActGubao" # 古宝养成 - 跨服
+CrossActName_HorsePetTrain = "CrossActHorsePetTrain" # 骑宠养成 - 跨服
 
 #跨服运营活动列表
-CrossActNameList = [CrossActName_CTGBillboard, CrossActName_AllRecharge, CrossActName_LuckyCloudBuy, CrossActName_BossTrial, CrossActName_XianXiaMJ, CrossActName_Gubao]
+CrossActNameList = [CrossActName_CTGBillboard, CrossActName_AllRecharge, CrossActName_LuckyCloudBuy, CrossActName_BossTrial, 
+                    CrossActName_XianXiaMJ, CrossActName_Gubao, CrossActName_HorsePetTrain]
 #需要锁定活动分区分配直到活动结束的跨服运营活动,即使热更分区配置,也不会改变正在活动中的分区设定,直到活动结束
 CrossActLockServerGroupIDList = [CrossActName_CTGBillboard, CrossActName_AllRecharge]
 
@@ -722,6 +725,13 @@
 
 Def_Effect_BossFinalHurtPer = 166   # Boss最终伤害万分率
 
+#法器生命百分比
+Def_Effect_FaQiMaxHPPer = 167
+#法器攻击百分比
+Def_Effect_FaQiAtkPer = 168
+#法器防御百分比
+Def_Effect_FaQiDefPer = 169
+
 #增加%d物理伤害值,其中a值为伤害值
 Def_Effect_AddAtk = 1005
 #增加%d魔法伤害值,其中a值为伤害值
@@ -830,9 +840,10 @@
     Def_BT_BossTrialSubmitFamilyBak,          #提交boss凭证仙盟榜 (boss历练活动 - 上一期)
     Def_BT_XianXiaMJScore,                    #仙匣秘境积分榜 (仙匣秘境活动)
     Def_BT_GubaoScore,                        #古宝养成积分榜 (古宝养成活动)
+    Def_BT_HorsePetTrainScore,                #骑宠养成积分榜 (骑宠养成活动) 40
     
     Def_BT_Max, #排行榜最大类型
-) = range(0, 39 + 2) 
+) = range(0, 40 + 2) 
 
 ''' 跨服排行榜类型, 从 150 开始
 与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
@@ -854,7 +865,8 @@
 Def_CBT_BossTrialSubmitFamilyBak, # boss凭证 - 仙盟榜 上一期  161
 Def_CBT_XianXiaMJScore, # 仙匣秘境积分 - 个人榜  162
 Def_CBT_GubaoScore, # 古宝养成积分 - 个人榜  163
-) = range(150, 163 + 1)
+Def_CBT_HorsePetTrainScore, # 骑宠养成积分 - 个人榜  164
+) = range(150, 164 + 1)
 
 # 跨服榜单最大数据名次,没有设置的默认100
 CrossBillboard_MaxDataCount = {
@@ -866,6 +878,7 @@
                                Def_CBT_BossTrialSubmitBak:1000,
                                Def_CBT_XianXiaMJScore:1000,
                                Def_CBT_GubaoScore:1000,
+                               Def_CBT_HorsePetTrainScore:1000,
                                }
 
 #职业对应战力排行榜类型
@@ -1131,7 +1144,8 @@
 CDBPlayerRefresh_BossTrial, # 凭证积分 262
 CDBPlayerRefresh_GatherSoul, # 聚魂精华 263
 CDBPlayerRefresh_BossFinalHurtPer,  # Boss最终输出伤害百分比 264
-) = range(146, 265)
+CDBPlayerRefresh_HorsePetTrainScore, # 骑宠养成积分 265
+) = range(146, 266)
 
 TYPE_Price_Gold_Paper_Money = 5    # 金钱类型,(先用礼券,再用金子)
 TYPE_Price_Family_Contribution = 6 # 战盟贡献度(活跃度转换得来)
@@ -1164,6 +1178,7 @@
 TYPE_Price_Lingyu = 42    # 灵玉
 TYPE_Price_BossTrial = 43    # boss历练凭证积分
 TYPE_Price_GatherSoul = 44    # 聚魂精华
+TYPE_Price_HorsePetTrainScore = 45    # 骑宠养成积分
 TYPE_Price_PayCoin = 99    # 代币
 
 #key可用于遍历所有货币,value仅GM相关会用到
@@ -1171,7 +1186,7 @@
                  1:"仙玉", 2:"绑玉", 3:"铜钱", 6:"战盟贡献度", 10:"战盟仓库积分", 13:"境界修行点", 14:"符印融合石", 15:"仙盟活跃令", 
                  16:"助战积分", 18:"荣誉", 19:"Boss积分", 23:"符印精华", 24:"符印碎片", 25:"寻宝积分", 26:"集市额度", 27:"丹精", 28:"魂尘", 
                  29:"聚魂碎片", 30:"核心环", 31:"功能特权令", 32:"环保值", 33:"GM令", 34:"古神币", 35:"功德点", 
-                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 99:"代币"
+                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 99:"代币"
                  }
 
 #以下是旧的金钱类型
@@ -1205,6 +1220,7 @@
                            TYPE_Price_FamilyFlagWarPoint:CDBPlayerRefresh_FamilyFlagWarPoint,
                            TYPE_Price_BossTrial:CDBPlayerRefresh_BossTrial,
                            TYPE_Price_GatherSoul:CDBPlayerRefresh_GatherSoul,
+                           TYPE_Price_HorsePetTrainScore:CDBPlayerRefresh_HorsePetTrainScore,
                            }
 
 # 支持负值的货币及对应0418刷新类型
@@ -1635,6 +1651,7 @@
 ClientServerMsg_FuncTeamMemOP = "FuncTeamMemOP"   # 功能队伍成员操作
 ClientServerMsg_QueryFuncTeam = "QueryFuncTeam"   # 查询功能队伍
 ClientServerMsg_GubaoScore = "GubaoScore" # 古宝养成积分
+ClientServerMsg_HorsePetTrainScore = "HorsePetTrainScore" # 骑宠养成积分
 
 #跨服广播类型定义
 CrossNotify_CrossAct = "CrossAct"
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/EffGetSet.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/EffGetSet.py
index f3dd35a..681a06a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/EffGetSet.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/EffGetSet.py
@@ -216,6 +216,9 @@
    [lambda curObj:GameObj.GetSuperHitHurtPer(curObj), lambda curObj, value:GameObj.SetSuperHitHurtPer(curObj, value), ShareDefine.CDBPlayerRefresh_SuperHitHurtPer, 1, 0],          # 强化暴伤
    [lambda curObj:GameObj.GetSuperHitHurtDefPer(curObj), lambda curObj, value:GameObj.SetSuperHitHurtDefPer(curObj, value), ShareDefine.CDBPlayerRefresh_SuperHitHurtDefPer, 1, 0],          # 弱化暴伤
    [lambda curObj:PlayerControl.GetBossFinalHurtPer(curObj), lambda curObj, value:PlayerControl.SetBossFinalHurtPer(curObj, value), ShareDefine.CDBPlayerRefresh_BossFinalHurtPer, 1, 0],        # Boss最终伤害百分比
+   [lambda curObj:PlayerControl.GetFaQiMaxHPPer(curObj), lambda curObj, value:PlayerControl.SetFaQiMaxHPPer(curObj, value), 0, 0, 0],  # 法器生命百分比
+   [lambda curObj:PlayerControl.GetFaQiAtkPer(curObj), lambda curObj, value:PlayerControl.SetFaQiAtkPer(curObj, value), 0, 0, 0],  # 法器攻击百分比
+   [lambda curObj:PlayerControl.GetFaQiDefPer(curObj), lambda curObj, value:PlayerControl.SetFaQiDefPer(curObj, value), 0, 0, 0],  # 法器防御百分比
 ]
 
 ## 通过索引获得属性值

--
Gitblit v1.8.0