From a166d721a3d7ff6cd2339983214e718c7a6a0ffe Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 11 六月 2025 11:00:36 +0800
Subject: [PATCH] 121 【武将】武将系统-服务端(武将招募;武将背包;武将养成系统;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py         |   71 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                |   21 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                |  520 +++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py            |  112 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py      |   15 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py                |    1 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py |   28 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItemCount.py  |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py           |  135 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini                  |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py          |  923 ++++++++++++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                        |   39 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py    |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py              |  242 ++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py            |    5 
 PySysDB/PySysDBPY.h                                                                               |   85 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py       |   14 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                   |   18 
 18 files changed, 2,226 insertions(+), 22 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 23cd4f0..772f55b 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -26,6 +26,91 @@
 	BYTE		OPLimitInAct;	//活动期间限制队伍操作
 };
 
+//武将表
+struct	Hero
+{
+	DWORD		_HeroID;	//英雄ID
+	WORD		HeroIndex;	// 记录索引
+	BYTE		Country;	// 国家
+	BYTE		Quality;	// 品质
+	list		SkinNPCIDList;	// 皮肤NPCID列表
+	DWORD		AtkSkillID;	//普攻技能ID
+	DWORD		AngerSkillID;	//怒气技能ID
+};
+
+//武将星级天赋表
+struct	HeroTalent
+{
+	DWORD		_TalentID;	//天赋ID
+	BYTE		AttrID;	// 属性ID
+	DWORD		AttrValue;	// 属性值
+	DWORD		InitWeight;	// 初始权重
+	DWORD		WashWeight;	// 洗炼权重
+	DWORD		AweakWeight;	// 觉醒权重
+};
+
+//武将突破潜能表
+struct	HeroBreak
+{
+	DWORD		_HeroID;	//英雄ID
+	BYTE		BreakLV;	// 突破等级
+	list		AttrIDList;	// 属性ID列表
+	list		AttrValueList;	// 属性值列表
+	DWORD		SkillID;	// 激活技能ID
+};
+
+//武将觉醒天赋表
+struct	HeroAwake
+{
+	DWORD		_HeroID;	//英雄ID
+	BYTE		AwakeLV;	// 觉醒等级
+	list		AttrIDList;	// 属性ID列表
+	list		AttrValueList;	// 属性值列表
+	DWORD		SkillID;	// 激活技能ID
+	BYTE		UnlockTalentSlot;	// 解锁第x槽位
+	BYTE		AddStarUpper;	// 增加星级上限
+};
+
+//武将皮肤表
+struct	HeroSkin
+{
+	DWORD		_SkinNPCID;	//皮肤NPCID
+	list		WearAttrIDList;	// 穿戴属性ID列表
+	list		WearAttrValueList;	// 穿戴属性值列表
+	list		AllBatAttrIDList;	// 全体上阵属性ID列表
+	list		AllBatAttrValueList;	// 全体上阵属性值列表
+};
+
+//武将品质表
+struct	HeroQuality
+{
+	DWORD		_Quality;	//品质
+	list		UPCostItem;	// 升级消耗道具
+	list		InitTalentWeight;	// 初始天赋数权重
+	BYTE		InitStarUpper;	// 初始星级上限
+	DWORD		InitAddPer;	// 初始加成万分率
+	DWORD		LVAddPer;	// 每等级加成
+	DWORD		BreakLVAddPer;	// 每突破等级加成
+	DWORD		StarAddPer;	// 每星级加成
+};
+
+//武将品质突破表
+struct	HeroQualityBreak
+{
+	DWORD		_Quality;	//品质
+	DWORD		_BreakLV;	//突破等级
+	WORD		LVMax;	// 等级上限
+	list		UPCostItem;	// 突破到下级消耗道具
+};
+
+//武将品质觉醒表
+struct	HeroQualityAwake
+{
+	DWORD		_Quality;	//品质
+	DWORD		_AwakeLV;	//觉醒等级
+	list		UPCostItem;	// 觉醒到下级消耗道具
+};
+
 //称号表 #tagDienstgrad
 
 struct	tagDienstgrad
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini
index 1fe370c..117a69d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini
@@ -1,7 +1,7 @@
 [RolePackConfig]
 ;2000///<所有背包总量限制
 ;玩家背包配置
-PackTypeCnt=35
+PackTypeCnt=36
 
 ;已删除物品rptDeleted//已无用
 PackCnt00=0
@@ -72,4 +72,6 @@
 ;神兽装备背包
 PackCnt33=150
 ;垃圾分类背包
-PackCnt34=30
\ No newline at end of file
+PackCnt34=30
+;武将英雄背包
+PackCnt35=500
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index 3baff6f..c847a2f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1904,3 +1904,42 @@
 PacketSubCMD_4=0x27
 PacketCallFunc_4=OnFamilyGCZSQ
 
+;武将
+[PlayerHero]
+ScriptName = Player\PlayerHero.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 8
+
+PacketCMD_1=0xB2
+PacketSubCMD_1=0x30
+PacketCallFunc_1=OnHeroLVUP
+
+PacketCMD_2=0xB2
+PacketSubCMD_2=0x31
+PacketCallFunc_2=OnHeroStarUP
+
+PacketCMD_3=0xB2
+PacketSubCMD_3=0x32
+PacketCallFunc_3=OnHeroBreak
+
+PacketCMD_4=0xB2
+PacketSubCMD_4=0x33
+PacketCallFunc_4=OnHeroAwake
+
+PacketCMD_5=0xB2
+PacketSubCMD_5=0x34
+PacketCallFunc_5=OnHeroAwakeSelectTalent
+
+PacketCMD_6=0xB2
+PacketSubCMD_6=0x35
+PacketCallFunc_6=OnHeroWash
+
+PacketCMD_7=0xB2
+PacketSubCMD_7=0x36
+PacketCallFunc_7=OnHeroWearSkin
+
+PacketCMD_8=0xB4
+PacketSubCMD_8=0x12
+PacketCallFunc_8=OnHeroBattlePosSave
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 38ae491..5f25ed4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -463,6 +463,8 @@
 
 Def_ItemType_CanUseByCDTime = 145 # 创建后根据CDTime到后可开启
 
+Def_ItemType_Hero = 150 # 武将英雄
+
 #以下定义物品类型下次删除
 Def_Item_Type_Horse = 1000036          #坐骑
 
@@ -555,6 +557,7 @@
 Def_Effect_EmojiPack = 276   #表情包物品;A值-表情包ID
 Def_Effect_RecycleItemMoney = 277   #回收物品转化为货币; A值-直接给货币物品ID;B值-货币数量
 Def_Effect_FamilyEmblem = 278   #激活仙盟徽章; A值-徽章ID;
+Def_Effect_HeroSkin = 279   #激活武将皮肤; A值-武将ID;B值-皮肤索引
 #----以下未使用或代码依然存在的---
 Def_Effect_ItemGiveGongXun = 1920        #使用道具给予功勋
 Def_Effect_ItemGiveRuneJH = 1925       #使用道具给予符印精华
@@ -1153,6 +1156,7 @@
                                     ShareDefine.rptDogzItem,
                                     ShareDefine.rptDogzEquip,
                                     ShareDefine.rptGarbage,
+                                    ShareDefine.rptHero,
                                     ]
 
 #装备可强化背包列表
@@ -1510,7 +1514,7 @@
 #自动恢复计算间隔
 Def_HPRestoreInterval = 5000
 #允许重置的背包索引
-Def_CanItemResetPack = [IPY_GameWorld.rptItem, IPY_GameWorld.rptWarehouse, ShareDefine.rptTreasure, ShareDefine.rptGarbage]
+Def_CanItemResetPack = [IPY_GameWorld.rptItem, IPY_GameWorld.rptWarehouse, ShareDefine.rptTreasure, ShareDefine.rptGarbage, ShareDefine.rptHero]
 #仓库分页个数
 Def_ItemReset_WarehousePageCnt = 56
 #玩家捡起物品的距离 8
@@ -3444,6 +3448,7 @@
 Def_Player_Dict_CabinetCount_Horse = "CabinetCount_Horse_42"    #马匹收纳柜
 Def_Player_Dict_PackCount_Item = "PackCount_Item_72"    #玩家物品背包格子数
 Def_Player_Dict_PackCount_Warehouse = "PackCount_Warehouse_73"    #仓库背包格子数
+Def_Player_Dict_PackCount_Hero = "PackCount_Hero"    #武将背包格子数
 Def_Player_Dict_PlayerMapSignCnt = "PlayerMapSignCnt_75"    # 大地图标记数量
 Def_Player_Dict_PlayerBuyZhenQiCnt = "PlayerBuyZhenQiCnt_76"  # 购买真气次数
 Def_Player_Dict_PlayChangeLineID = "PlayChangeLineID"     # 玩家主动切换线路记录
@@ -4414,6 +4419,10 @@
 Def_PDict_TiandaoQiyun = "TiandaoQiyun" # 天道树当前气运
 Def_PDict_TiandaoAward = "TiandaoAward_%s" # 天道树领奖记录,按奖励索引记录是否已领取,参数(key编号)
 
+#武将
+Def_PDict_HeroActState = "HeroActState_%s" # 武将解锁状态,按记录索引二进制存储,参数(key编号)
+Def_PDict_HeroSkin = "HeroSkin_%s" # 武将皮肤解锁状态,按皮肤索引二进制存储,参数(武将ID)
+
 #-------------------------------------------------------------------------------
 #可以从07 41封包购买的背包类型,和对应字典{背包类型:[字典key, 默认格子数]}
 
@@ -4445,6 +4454,10 @@
                                       
                                   IPY_GameWorld.rptWarehouse:[
                                        Def_Player_Dict_PackCount_Warehouse, 
+                                       0],
+                                      
+                                  ShareDefine.rptHero:[
+                                       Def_Player_Dict_PackCount_Hero, 
                                        0],
                                       
                                   #IPY_GameWorld.rptFineSoulSlot:[
@@ -5733,8 +5746,9 @@
 ntMonsterTime, #按时间掉血的怪物 22 废弃,以是否有配置在时间掉血怪物表为准
 ntPriWoodPilePVE, #专属私有木桩 - PVE 23
 ntPriWoodPilePVP, #专属私有木桩 - PVP 24
+ntHero, #武将英雄 25
 ntMax
-) = range(26)
+) = range(27)
 
 
 (Def_SkillFuncType_Common, #0为通用技能
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index e95e85e..cae4322 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -17264,6 +17264,411 @@
 
 
 #------------------------------------------------------
+# B2 33 武将觉醒 #tagCSHeroAwake
+
+class  tagCSHeroAwake(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x33
+        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 = 0xB2
+        self.SubCmd = 0x33
+        self.ItemIndex = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroAwake)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 33 武将觉醒 //tagCSHeroAwake:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemIndex:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemIndex
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroAwake=tagCSHeroAwake()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroAwake.Cmd,m_NAtagCSHeroAwake.SubCmd))] = m_NAtagCSHeroAwake
+
+
+#------------------------------------------------------
+# B2 34 武将觉醒选择天赋 #tagCSHeroAwakeSelectTalent
+
+class  tagCSHeroAwakeSelectTalent(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ("SelectIndex", c_ubyte),    #选择新解锁槽位的天赋索引
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x34
+        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 = 0xB2
+        self.SubCmd = 0x34
+        self.ItemIndex = 0
+        self.SelectIndex = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroAwakeSelectTalent)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 34 武将觉醒选择天赋 //tagCSHeroAwakeSelectTalent:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemIndex:%d,
+                                SelectIndex:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemIndex,
+                                self.SelectIndex
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroAwakeSelectTalent=tagCSHeroAwakeSelectTalent()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroAwakeSelectTalent.Cmd,m_NAtagCSHeroAwakeSelectTalent.SubCmd))] = m_NAtagCSHeroAwakeSelectTalent
+
+
+#------------------------------------------------------
+# B2 32 武将突破 #tagCSHeroBreak
+
+class  tagCSHeroBreak(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x32
+        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 = 0xB2
+        self.SubCmd = 0x32
+        self.ItemIndex = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroBreak)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 32 武将突破 //tagCSHeroBreak:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemIndex:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemIndex
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroBreak=tagCSHeroBreak()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroBreak.Cmd,m_NAtagCSHeroBreak.SubCmd))] = m_NAtagCSHeroBreak
+
+
+#------------------------------------------------------
+# B2 30 武将升级 #tagCSHeroLVUP
+
+class  tagCSHeroLVUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x30
+        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 = 0xB2
+        self.SubCmd = 0x30
+        self.ItemIndex = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroLVUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 30 武将升级 //tagCSHeroLVUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemIndex:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemIndex
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroLVUP=tagCSHeroLVUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroLVUP.Cmd,m_NAtagCSHeroLVUP.SubCmd))] = m_NAtagCSHeroLVUP
+
+
+#------------------------------------------------------
+# B2 31 武将升星 #tagCSHeroStarUP
+
+class  tagCSHeroStarUP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ("UseItemIndex", c_ushort),    #使用武将材料物品所在武将背包位置索引
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x31
+        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 = 0xB2
+        self.SubCmd = 0x31
+        self.ItemIndex = 0
+        self.UseItemIndex = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroStarUP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 31 武将升星 //tagCSHeroStarUP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemIndex:%d,
+                                UseItemIndex:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemIndex,
+                                self.UseItemIndex
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroStarUP=tagCSHeroStarUP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroStarUP.Cmd,m_NAtagCSHeroStarUP.SubCmd))] = m_NAtagCSHeroStarUP
+
+
+#------------------------------------------------------
+# B2 35 武将洗炼 #tagCSHeroWash
+
+class  tagCSHeroWash(Structure):
+    Head = tagHead()
+    ItemIndex = 0    #(WORD ItemIndex)//武将物品所在武将背包位置索引
+    LockCnt = 0    #(BYTE LockCnt)
+    LockTalentIndexs = list()    #(vector<BYTE> LockTalentIndexs)//锁定天赋索引列表
+    OPType = 0    #(BYTE OPType)// 操作类型:0-执行洗炼;1-替换原天赋;2-保留原天赋
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB2
+        self.Head.SubCmd = 0x35
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ItemIndex,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.LockCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.LockCnt):
+            value,_pos=CommFunc.ReadBYTE(_lpData,_pos)
+            self.LockTalentIndexs.append(value)
+        self.OPType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB2
+        self.Head.SubCmd = 0x35
+        self.ItemIndex = 0
+        self.LockCnt = 0
+        self.LockTalentIndexs = list()
+        self.OPType = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        length += 1
+        length += 1 * self.LockCnt
+        length += 1
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.ItemIndex)
+        data = CommFunc.WriteBYTE(data, self.LockCnt)
+        for i in range(self.LockCnt):
+            data = CommFunc.WriteBYTE(data, self.LockTalentIndexs[i])
+        data = CommFunc.WriteBYTE(data, self.OPType)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ItemIndex:%d,
+                                LockCnt:%d,
+                                LockTalentIndexs:%s,
+                                OPType:%d
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ItemIndex,
+                                self.LockCnt,
+                                "...",
+                                self.OPType
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroWash=tagCSHeroWash()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroWash.Head.Cmd,m_NAtagCSHeroWash.Head.SubCmd))] = m_NAtagCSHeroWash
+
+
+#------------------------------------------------------
+# B2 36 武将换肤 #tagCSHeroWearSkin
+
+class  tagCSHeroWearSkin(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ("SkinIndex", c_ubyte),    #皮肤索引
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x36
+        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 = 0xB2
+        self.SubCmd = 0x36
+        self.ItemIndex = 0
+        self.SkinIndex = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroWearSkin)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 36 武将换肤 //tagCSHeroWearSkin:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemIndex:%d,
+                                SkinIndex:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemIndex,
+                                self.SkinIndex
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroWearSkin=tagCSHeroWearSkin()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroWearSkin.Cmd,m_NAtagCSHeroWearSkin.SubCmd))] = m_NAtagCSHeroWearSkin
+
+
+#------------------------------------------------------
 # B2 07 重置加点 #tagCMResetAttrPoint
 
 class  tagCMResetAttrPoint(Structure):
@@ -18535,6 +18940,121 @@
 
 
 #------------------------------------------------------
+# B4 12 战斗阵型保存 #tagCSHeroBattlePosSave
+
+class  tagCSHeroBattlePos(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引
+                  ("PosNum", c_ubyte),    #1~n上阵位置编号  
+                  ]
+
+    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.ItemIndex = 0
+        self.PosNum = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCSHeroBattlePos)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B4 12 战斗阵型保存 //tagCSHeroBattlePosSave:
+                                ItemIndex:%d,
+                                PosNum:%d
+                                '''\
+                                %(
+                                self.ItemIndex,
+                                self.PosNum
+                                )
+        return DumpString
+
+
+class  tagCSHeroBattlePosSave(Structure):
+    Head = tagHead()
+    FuncType = 0    #(BYTE FuncType)//布阵功能类型:0-默认主阵型;其他待扩展,如某个活动的防守阵型
+    PosCnt = 0    #(BYTE PosCnt)
+    HeroPosList = list()    #(vector<tagCSHeroBattlePos> HeroPosList)// 保存的阵型,只要发送最终的阵型武将位置即可
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB4
+        self.Head.SubCmd = 0x12
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.FuncType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.PosCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.PosCnt):
+            temHeroPosList = tagCSHeroBattlePos()
+            _pos = temHeroPosList.ReadData(_lpData, _pos)
+            self.HeroPosList.append(temHeroPosList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB4
+        self.Head.SubCmd = 0x12
+        self.FuncType = 0
+        self.PosCnt = 0
+        self.HeroPosList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        for i in range(self.PosCnt):
+            length += self.HeroPosList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.FuncType)
+        data = CommFunc.WriteBYTE(data, self.PosCnt)
+        for i in range(self.PosCnt):
+            data = CommFunc.WriteString(data, self.HeroPosList[i].GetLength(), self.HeroPosList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                FuncType:%d,
+                                PosCnt:%d,
+                                HeroPosList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.FuncType,
+                                self.PosCnt,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagCSHeroBattlePosSave=tagCSHeroBattlePosSave()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroBattlePosSave.Head.Cmd,m_NAtagCSHeroBattlePosSave.Head.SubCmd))] = m_NAtagCSHeroBattlePosSave
+
+
+#------------------------------------------------------
 # B4 11 镜像战斗 #tagCMMirrorFight
 
 class  tagCMMirrorFight(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 0b5955d..50f951f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -44094,6 +44094,118 @@
 
 
 #------------------------------------------------------
+# B1 22 武将信息 #tagSCHeroInfo
+
+class  tagSCHero(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("HeroID", c_int),    # 武将ID
+                  ("IsActive", c_ubyte),    # 是否已激活
+                  ("SkinState", c_int),    # 武将皮肤已解锁状态信息,按皮肤所在索引二进制位运算判断是否解锁,0索引位默认皮肤,不用验证
+                  ]
+
+    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.HeroID = 0
+        self.IsActive = 0
+        self.SkinState = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSCHero)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 22 武将信息 //tagSCHeroInfo:
+                                HeroID:%d,
+                                IsActive:%d,
+                                SkinState:%d
+                                '''\
+                                %(
+                                self.HeroID,
+                                self.IsActive,
+                                self.SkinState
+                                )
+        return DumpString
+
+
+class  tagSCHeroInfo(Structure):
+    Head = tagHead()
+    HeroCnt = 0    #(WORD HeroCnt)
+    HeroInfoList = list()    #(vector<tagSCHero> HeroInfoList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x22
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.HeroCnt,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        for i in range(self.HeroCnt):
+            temHeroInfoList = tagSCHero()
+            _pos = temHeroInfoList.ReadData(_lpData, _pos)
+            self.HeroInfoList.append(temHeroInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x22
+        self.HeroCnt = 0
+        self.HeroInfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        for i in range(self.HeroCnt):
+            length += self.HeroInfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.HeroCnt)
+        for i in range(self.HeroCnt):
+            data = CommFunc.WriteString(data, self.HeroInfoList[i].GetLength(), self.HeroInfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                HeroCnt:%d,
+                                HeroInfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.HeroCnt,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagSCHeroInfo=tagSCHeroInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCHeroInfo.Head.Cmd,m_NAtagSCHeroInfo.Head.SubCmd))] = m_NAtagSCHeroInfo
+
+
+#------------------------------------------------------
 # B1 06 通知玩家向目标点移动 #tagMCNotifyPlayerMove
 
 class  tagMCNotifyPlayerMove(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
new file mode 100644
index 0000000..cb4faeb
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Hero
+#
+# @todo:武将英雄
+# @author hxp
+# @date 2025-06-11
+# @version 1.0
+#
+# 详细描述: 武将英雄
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-06-11 11:00"""
+#-------------------------------------------------------------------------------
+
+import PlayerHero
+import ShareDefine
+import IpyGameDataPY
+import GameWorld
+import ChConfig
+
+## GM命令执行入口
+#  @param curPlayer 当前玩家
+#  @param msgList 参数列表
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+    
+    if not msgList:
+        GameWorld.DebugAnswer(curPlayer, "武将重置: Hero 0 背包位置")
+        GameWorld.DebugAnswer(curPlayer, "武将等级: Hero l 背包位置 设置等级")
+        GameWorld.DebugAnswer(curPlayer, "武将升星: Hero s 背包位置 升x星")
+        GameWorld.DebugAnswer(curPlayer, "武将突破: Hero b 背包位置 设置等级")
+        GameWorld.DebugAnswer(curPlayer, "武将觉醒: Hero a 背包位置 设置等级")
+        GameWorld.DebugAnswer(curPlayer, "武将图鉴: Hero t 武将ID 是否激活")
+        GameWorld.DebugAnswer(curPlayer, "重置图鉴: Hero t 0")
+        GameWorld.DebugAnswer(curPlayer, "武将皮肤: Hero sk 武将ID 皮肤索引 是否解锁")
+        GameWorld.DebugAnswer(curPlayer, "清空武将: ClearPack 35")
+        GameWorld.DebugAnswer(curPlayer, "新增武将: MakeItemCount 英雄ID [个数]")
+        return
+    
+    value = msgList[0]
+    value2 = msgList[1] if len(msgList) > 1 else 0
+    
+    # 图鉴
+    if value == "t":
+        isAct = 0
+        if not value2:
+            heroIDList = []
+            ipyDataMgr = IpyGameDataPY.IPY_Data()
+            for index in range(ipyDataMgr.GetHeroCount()):
+                ipyData = ipyDataMgr.GetHeroByIndex(index)
+                heroIDList.append(ipyData.GetHeroID())
+        else:
+            isAct = msgList[2] if len(msgList) > 2 else 0
+            heroIDList = [value2]
+        
+        syncHeroIDList = []
+        for heroID in heroIDList:
+            heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+            if not heroIpyData:
+                continue
+            heroIndex = heroIpyData.GetHeroIndex()
+            if GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex) == isAct:
+                continue
+            GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex, isAct)
+            syncHeroIDList.append(heroID)
+            
+        PlayerHero.Sync_HeroInfo(curPlayer, syncHeroIDList)
+        if not value2:
+            GameWorld.DebugAnswer(curPlayer, "重置图鉴OK!")
+        else:
+            GameWorld.DebugAnswer(curPlayer, "设置武将(%s),激活(%s)" % (value2, isAct))
+        return
+    
+    # 皮肤
+    if value == "sk":
+        heroID = value2
+        skinIndex = msgList[2] if len(msgList) > 2 else 0
+        isActive = msgList[3] if len(msgList) > 3 else 0
+        PlayerHero.ActiveHeroSkin(curPlayer, heroID, skinIndex, isActive)
+        return
+    
+    itemIndex = value2
+    heroItem = PlayerHero.GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        GameWorld.DebugAnswer(curPlayer, "不存在武将: itemIndex=%s" % itemIndex)
+        return
+    
+    if value == 0:
+        PlayerHero.InitHeroItem(heroItem.GetItem())
+        heroItem.Sync_Item()
+        GameWorld.DebugAnswer(curPlayer, "重置武将: itemIndex=%s" % (itemIndex))
+        return
+    
+    # 等级
+    if value == "l":
+        heroLV = msgList[2] if len(msgList) > 2 else 1
+        LVMax = PlayerHero.GetHeroLVMax(heroItem)
+        heroLV = min(LVMax, heroLV)
+        heroItem.SetUserAttr(ShareDefine.Def_IudetHeroLV, heroLV)
+        GameWorld.DebugAnswer(curPlayer, "设置武将等级: %s,itemIndex=%s" % (heroLV, itemIndex))
+        return
+    
+    # 星级
+    if value == "s":
+        addStar = msgList[2] if len(msgList) > 2 else 1
+        curStar = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+        starMax = PlayerHero.GetHeroStarMax(heroItem)
+        if curStar >= starMax:
+            GameWorld.DebugAnswer(curPlayer, "武将已满星: %s,itemIndex=%s" % (curStar, itemIndex))
+            return
+        updStar = min(curStar + addStar, starMax)
+        PlayerHero.DoHeroUpdStar(curPlayer, heroItem, updStar)
+        GameWorld.DebugAnswer(curPlayer, "更新武将星级: %s,itemIndex=%s" % (updStar, itemIndex))
+        return
+    
+    # 突破
+    if value == "b":
+        breakLV = msgList[2] if len(msgList) > 2 else 0
+        PlayerHero.SetHeroBreakLV(heroItem, breakLV)
+        GameWorld.DebugAnswer(curPlayer, "设置武将突破: %s,itemIndex=%s" % (breakLV, itemIndex))
+        return
+    
+    # 觉醒
+    if value == "a":
+        awakeLV = msgList[2] if len(msgList) > 2 else 0
+        PlayerHero.SetHeroAwakeLV(heroItem, awakeLV)
+        GameWorld.DebugAnswer(curPlayer, "设置武将觉醒: %s,itemIndex=%s" % (awakeLV, itemIndex))
+        return
+    
+    return
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItemCount.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItemCount.py
index 913dd60..3f7467e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItemCount.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItemCount.py
@@ -66,12 +66,12 @@
             if not ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, True, [IPY_GameWorld.rptItem], event=event):
                 GameWorld.DebugAnswer(curPlayer, "###放入物品失败!")
     else:
-        if not ItemCommon.GetIsEquip(itemData):
-            if not ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, False, [IPY_GameWorld.rptItem], event=event):
-                GameWorld.DebugAnswer(curPlayer, "###放入物品失败!")
-        else:
+        if ItemCommon.GetIsEquip(itemData) or itemData.GetPackCount() <= 1:
             for _ in xrange(itemCount):
                 __DoGMGivePlayerItem(curPlayer, playerItemControler, itemID, 1, False, isAllAttr, event)
+        else:
+            if not ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, False, [IPY_GameWorld.rptItem], event=event):
+                GameWorld.DebugAnswer(curPlayer, "###放入物品失败!")
     return
 
 def __DoGMGivePlayerItem(curPlayer, playerItemControler, itemID, count, isAuctionItem, isAllAttr, event):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index c1e5011..8244a79 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -56,6 +56,75 @@
                         ("BYTE", "OPLimitInAct", 0),
                         ),
 
+                "Hero":(
+                        ("DWORD", "HeroID", 1),
+                        ("WORD", "HeroIndex", 0),
+                        ("BYTE", "Country", 0),
+                        ("BYTE", "Quality", 0),
+                        ("list", "SkinNPCIDList", 0),
+                        ("DWORD", "AtkSkillID", 0),
+                        ("DWORD", "AngerSkillID", 0),
+                        ),
+
+                "HeroTalent":(
+                        ("DWORD", "TalentID", 1),
+                        ("BYTE", "AttrID", 0),
+                        ("DWORD", "AttrValue", 0),
+                        ("DWORD", "InitWeight", 0),
+                        ("DWORD", "WashWeight", 0),
+                        ("DWORD", "AweakWeight", 0),
+                        ),
+
+                "HeroBreak":(
+                        ("DWORD", "HeroID", 1),
+                        ("BYTE", "BreakLV", 0),
+                        ("list", "AttrIDList", 0),
+                        ("list", "AttrValueList", 0),
+                        ("DWORD", "SkillID", 0),
+                        ),
+
+                "HeroAwake":(
+                        ("DWORD", "HeroID", 1),
+                        ("BYTE", "AwakeLV", 0),
+                        ("list", "AttrIDList", 0),
+                        ("list", "AttrValueList", 0),
+                        ("DWORD", "SkillID", 0),
+                        ("BYTE", "UnlockTalentSlot", 0),
+                        ("BYTE", "AddStarUpper", 0),
+                        ),
+
+                "HeroSkin":(
+                        ("DWORD", "SkinNPCID", 1),
+                        ("list", "WearAttrIDList", 0),
+                        ("list", "WearAttrValueList", 0),
+                        ("list", "AllBatAttrIDList", 0),
+                        ("list", "AllBatAttrValueList", 0),
+                        ),
+
+                "HeroQuality":(
+                        ("DWORD", "Quality", 1),
+                        ("list", "UPCostItem", 0),
+                        ("list", "InitTalentWeight", 0),
+                        ("BYTE", "InitStarUpper", 0),
+                        ("DWORD", "InitAddPer", 0),
+                        ("DWORD", "LVAddPer", 0),
+                        ("DWORD", "BreakLVAddPer", 0),
+                        ("DWORD", "StarAddPer", 0),
+                        ),
+
+                "HeroQualityBreak":(
+                        ("DWORD", "Quality", 1),
+                        ("DWORD", "BreakLV", 1),
+                        ("WORD", "LVMax", 0),
+                        ("list", "UPCostItem", 0),
+                        ),
+
+                "HeroQualityAwake":(
+                        ("DWORD", "Quality", 1),
+                        ("DWORD", "AwakeLV", 1),
+                        ("list", "UPCostItem", 0),
+                        ),
+
                 "Dienstgrad":(
                         ("DWORD", "ID", 1),
                         ("WORD", "Type", 0),
@@ -2689,6 +2758,115 @@
     def GetSortType(self): return self.attrTuple[5] # 队伍列表排序方案 BYTE
     def GetSortReverse(self): return self.attrTuple[6] # 是否倒序 BYTE
     def GetOPLimitInAct(self): return self.attrTuple[7] # 活动期间限制队伍操作 BYTE
+
+# 武将表
+class IPY_Hero():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetHeroID(self): return self.attrTuple[0] # 英雄ID DWORD
+    def GetHeroIndex(self): return self.attrTuple[1] #  记录索引 WORD
+    def GetCountry(self): return self.attrTuple[2] #  国家 BYTE
+    def GetQuality(self): return self.attrTuple[3] #  品质 BYTE
+    def GetSkinNPCIDList(self): return self.attrTuple[4] #  皮肤NPCID列表 list
+    def GetAtkSkillID(self): return self.attrTuple[5] # 普攻技能ID DWORD
+    def GetAngerSkillID(self): return self.attrTuple[6] # 怒气技能ID DWORD
+
+# 武将星级天赋表
+class IPY_HeroTalent():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetTalentID(self): return self.attrTuple[0] # 天赋ID DWORD
+    def GetAttrID(self): return self.attrTuple[1] #  属性ID BYTE
+    def GetAttrValue(self): return self.attrTuple[2] #  属性值 DWORD
+    def GetInitWeight(self): return self.attrTuple[3] #  初始权重 DWORD
+    def GetWashWeight(self): return self.attrTuple[4] #  洗炼权重 DWORD
+    def GetAweakWeight(self): return self.attrTuple[5] #  觉醒权重 DWORD
+
+# 武将突破潜能表
+class IPY_HeroBreak():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetHeroID(self): return self.attrTuple[0] # 英雄ID DWORD
+    def GetBreakLV(self): return self.attrTuple[1] #  突破等级 BYTE
+    def GetAttrIDList(self): return self.attrTuple[2] #  属性ID列表 list
+    def GetAttrValueList(self): return self.attrTuple[3] #  属性值列表 list
+    def GetSkillID(self): return self.attrTuple[4] #  激活技能ID DWORD
+
+# 武将觉醒天赋表
+class IPY_HeroAwake():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetHeroID(self): return self.attrTuple[0] # 英雄ID DWORD
+    def GetAwakeLV(self): return self.attrTuple[1] #  觉醒等级 BYTE
+    def GetAttrIDList(self): return self.attrTuple[2] #  属性ID列表 list
+    def GetAttrValueList(self): return self.attrTuple[3] #  属性值列表 list
+    def GetSkillID(self): return self.attrTuple[4] #  激活技能ID DWORD
+    def GetUnlockTalentSlot(self): return self.attrTuple[5] #  解锁第x槽位 BYTE
+    def GetAddStarUpper(self): return self.attrTuple[6] #  增加星级上限 BYTE
+
+# 武将皮肤表
+class IPY_HeroSkin():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetSkinNPCID(self): return self.attrTuple[0] # 皮肤NPCID DWORD
+    def GetWearAttrIDList(self): return self.attrTuple[1] #  穿戴属性ID列表 list
+    def GetWearAttrValueList(self): return self.attrTuple[2] #  穿戴属性值列表 list
+    def GetAllBatAttrIDList(self): return self.attrTuple[3] #  全体上阵属性ID列表 list
+    def GetAllBatAttrValueList(self): return self.attrTuple[4] #  全体上阵属性值列表 list
+
+# 武将品质表
+class IPY_HeroQuality():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetQuality(self): return self.attrTuple[0] # 品质 DWORD
+    def GetUPCostItem(self): return self.attrTuple[1] #  升级消耗道具 list
+    def GetInitTalentWeight(self): return self.attrTuple[2] #  初始天赋数权重 list
+    def GetInitStarUpper(self): return self.attrTuple[3] #  初始星级上限 BYTE
+    def GetInitAddPer(self): return self.attrTuple[4] #  初始加成万分率 DWORD
+    def GetLVAddPer(self): return self.attrTuple[5] #  每等级加成 DWORD
+    def GetBreakLVAddPer(self): return self.attrTuple[6] #  每突破等级加成 DWORD
+    def GetStarAddPer(self): return self.attrTuple[7] #  每星级加成 DWORD
+
+# 武将品质突破表
+class IPY_HeroQualityBreak():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetQuality(self): return self.attrTuple[0] # 品质 DWORD
+    def GetBreakLV(self): return self.attrTuple[1] # 突破等级 DWORD
+    def GetLVMax(self): return self.attrTuple[2] #  等级上限 WORD
+    def GetUPCostItem(self): return self.attrTuple[3] #  突破到下级消耗道具 list
+
+# 武将品质觉醒表
+class IPY_HeroQualityAwake():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetQuality(self): return self.attrTuple[0] # 品质 DWORD
+    def GetAwakeLV(self): return self.attrTuple[1] # 觉醒等级 DWORD
+    def GetUPCostItem(self): return self.attrTuple[2] #  觉醒到下级消耗道具 list
 
 # 称号表
 class IPY_Dienstgrad():
@@ -6699,6 +6877,14 @@
         self.__LoadFileData("DirtyList", onlyCheck)
         self.__LoadFileData("DirtyName", onlyCheck)
         self.__LoadFileData("FuncTeamSet", onlyCheck)
+        self.__LoadFileData("Hero", onlyCheck)
+        self.__LoadFileData("HeroTalent", onlyCheck)
+        self.__LoadFileData("HeroBreak", onlyCheck)
+        self.__LoadFileData("HeroAwake", onlyCheck)
+        self.__LoadFileData("HeroSkin", onlyCheck)
+        self.__LoadFileData("HeroQuality", onlyCheck)
+        self.__LoadFileData("HeroQualityBreak", onlyCheck)
+        self.__LoadFileData("HeroQualityAwake", onlyCheck)
         self.__LoadFileData("Dienstgrad", onlyCheck)
         self.__LoadFileData("TitleStarUp", onlyCheck)
         self.__LoadFileData("PlayerFace", onlyCheck)
@@ -7202,6 +7388,62 @@
         self.CheckLoadData("FuncTeamSet")
         return self.ipyFuncTeamSetCache[index]
 
+    def GetHeroCount(self):
+        self.CheckLoadData("Hero")
+        return self.ipyHeroLen
+    def GetHeroByIndex(self, index):
+        self.CheckLoadData("Hero")
+        return self.ipyHeroCache[index]
+
+    def GetHeroTalentCount(self):
+        self.CheckLoadData("HeroTalent")
+        return self.ipyHeroTalentLen
+    def GetHeroTalentByIndex(self, index):
+        self.CheckLoadData("HeroTalent")
+        return self.ipyHeroTalentCache[index]
+
+    def GetHeroBreakCount(self):
+        self.CheckLoadData("HeroBreak")
+        return self.ipyHeroBreakLen
+    def GetHeroBreakByIndex(self, index):
+        self.CheckLoadData("HeroBreak")
+        return self.ipyHeroBreakCache[index]
+
+    def GetHeroAwakeCount(self):
+        self.CheckLoadData("HeroAwake")
+        return self.ipyHeroAwakeLen
+    def GetHeroAwakeByIndex(self, index):
+        self.CheckLoadData("HeroAwake")
+        return self.ipyHeroAwakeCache[index]
+
+    def GetHeroSkinCount(self):
+        self.CheckLoadData("HeroSkin")
+        return self.ipyHeroSkinLen
+    def GetHeroSkinByIndex(self, index):
+        self.CheckLoadData("HeroSkin")
+        return self.ipyHeroSkinCache[index]
+
+    def GetHeroQualityCount(self):
+        self.CheckLoadData("HeroQuality")
+        return self.ipyHeroQualityLen
+    def GetHeroQualityByIndex(self, index):
+        self.CheckLoadData("HeroQuality")
+        return self.ipyHeroQualityCache[index]
+
+    def GetHeroQualityBreakCount(self):
+        self.CheckLoadData("HeroQualityBreak")
+        return self.ipyHeroQualityBreakLen
+    def GetHeroQualityBreakByIndex(self, index):
+        self.CheckLoadData("HeroQualityBreak")
+        return self.ipyHeroQualityBreakCache[index]
+
+    def GetHeroQualityAwakeCount(self):
+        self.CheckLoadData("HeroQualityAwake")
+        return self.ipyHeroQualityAwakeLen
+    def GetHeroQualityAwakeByIndex(self, index):
+        self.CheckLoadData("HeroQualityAwake")
+        return self.ipyHeroQualityAwakeCache[index]
+
     def GetDienstgradCount(self):
         self.CheckLoadData("Dienstgrad")
         return self.ipyDienstgradLen
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 e4e12c9..398dd1f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -734,6 +734,7 @@
                             ChConfig.Def_Effect_ItemGiveWeekPartyPoint1:"Item_WeekPartyPoint", # 增加活动巡礼积分
                             ChConfig.Def_Effect_AddRealmExpRate:"Item_AddRealmExpRate", # 增加聚灵效率
                             ChConfig.Def_Effect_TouchMission:"Item_TouchMission",  # 触发任务接口
+                            ChConfig.Def_Effect_HeroSkin:"Item_HeroSkin",  # 武将皮肤
                             #ChConfig.Def_Effect_FamilyImpeach:"Item_FamilyImpeach",  # 弹劾符
                             #ChConfig.Def_Effect_ClothesCoatSkin:"Item_ClothesCoatSkin", #激活时装皮肤
                             #ChConfig.Def_Effect_AddOfficialExp:"Item_AddOfficialExp", # 增加爵位经验
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
index d75bf5e..4b2cec1 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
@@ -41,6 +41,7 @@
 import PyGameData
 import PlayerVip
 import ChEquip
+import PlayerHero
 
 import math
 import time
@@ -1346,6 +1347,10 @@
                 if isNeedRecord:
                     itemNoteDict = ItemCommon.GetItemNoteDict(item, curItemCount, packItemCount, GetItemCount(item))
                     ItemCommon.DR_GetItem(curPlayer, packIndex, eventName, itemNoteDict, addDict)
+                    
+                if item.GetType() == ChConfig.Def_ItemType_Hero:
+                    PlayerHero.OnGiveHeroItem(curPlayer, item)
+                    
                 break
                                                 
         #放入东西
@@ -1663,7 +1668,14 @@
             return
     
     # 整理方式不同区分
-    if packIndex == IPY_GameWorld.rptWarehouse:
+    if packIndex == ShareDefine.rptHero:
+        if tick - curPlayer.GetResetItemTick() <= ChConfig.Def_ItemPackResetInterval:
+            #GameWorld.DebugLog("重整背包时间间隔太短")
+            return
+        curPlayer.SetResetItemTick(tick)
+        ResetHeroPack(curPlayer, curPack, beingIndex, endIndex)
+        
+    elif packIndex == IPY_GameWorld.rptWarehouse:
         #验证间隔
         if tick - curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_WareHouseSort) < \
                 ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_WareHouseSort]:
@@ -1968,7 +1980,60 @@
  
     return
 
+def ResetHeroPack(curPlayer, curPack, beingIndex, endIndex):
+    itemList = []
+    for i in range(beingIndex, endIndex + 1):
+        curRoleItem = curPack.GetAt(i)
+        if curRoleItem.IsEmpty():
+            continue
+        curItem = curRoleItem.GetItem() 
+        itemList.append(curItem)
+    itemList.sort(__CmpHeroPack)
+    
+    curPack.WipePack(beingIndex, endIndex)
+    putPlace = beingIndex
+    for item in itemList:
+        curPack.GetAt(putPlace).AssignItem(item, False)
+        putPlace += 1
+        
+    return
 
+def __CmpHeroPack(item1, item2):
+    '''排序规则:上阵武将排前,未上阵武将排后,再各自按照以下规则排序
+    武将等级>突破等级>武将星级>武将品质>武将ID
+    '''
+    
+    posNum1 = item1.GetUserAttr(ShareDefine.Def_IudetHeroPosNum)
+    posNum2 = item2.GetUserAttr(ShareDefine.Def_IudetHeroPosNum)
+    if (posNum1 and posNum2) or (not posNum1 and not posNum2):
+        lv1 = item1.GetUserAttr(ShareDefine.Def_IudetHeroLV)
+        lv2 = item2.GetUserAttr(ShareDefine.Def_IudetHeroLV)
+        if lv1 == lv2:
+            bLV1 = item1.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+            bLV2 = item2.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+            if bLV1 == bLV2:
+                star1 = item1.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+                star2 = item2.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+                if star1 == star2:
+                    heroID1 = item1.GetItemTypeID()
+                    heroID2 = item2.GetItemTypeID()
+                    ipyData1 = IpyGameDataPY.GetIpyGameData("Hero", heroID1)
+                    ipyData2 = IpyGameDataPY.GetIpyGameData("Hero", heroID2)
+                    quality1 = ipyData1.GetQuality() if ipyData1 else 0
+                    quality2 = ipyData2.GetQuality() if ipyData2 else 0
+                    if quality1 == quality2:
+                        return cmp(heroID1, heroID2)
+                    return -cmp(quality1, quality2)
+                return -cmp(star1, star2)
+            return -cmp(bLV1, bLV2)
+        return -cmp(lv1, lv2)
+    elif posNum1:
+        return -1
+    elif posNum2:
+        return 1
+    else:
+        return cmp(item1.GetItemTypeID(), item2.GetItemTypeID())
+    
 #===============================================================================
 #Python 版重整物品
 # def ResetItem(curPlayer, curPackIndex, tick):
@@ -2575,6 +2640,10 @@
         GameWorld.ErrLog("产出物品异常,无法创建物品 = %s" % (itemID))
         return
     
+    # 英雄
+    if curItem.GetType() == ChConfig.Def_ItemType_Hero:
+        return curItem
+    
     # 非装备,无需设置属性
     if not ItemCommon.CheckItemIsEquip(curItem):
         return curItem
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
index c1508fb..8e688c2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
@@ -37,6 +37,7 @@
 import PyGameData
 import ChEquip
 import SkillShell
+import PlayerHero
 import random
 import math
 import time
@@ -360,6 +361,10 @@
     if expireTime > 0:
         curSingleItem.SetUserAttr(ShareDefine.Def_IudetExpireTime, expireTime)
         
+    # 英雄
+    if curSingleItem.GetType() == ChConfig.Def_ItemType_Hero:
+        PlayerHero.InitHeroItem(curSingleItem)
+        
     #这里返回的是SingleItem , 如果创建了,未使用,会找出C++内存泄露!!!
     return curSingleItem
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py
new file mode 100644
index 0000000..cce1865
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package UseItem.Item_HeroSkin
+#
+# @todo:激活武将皮肤
+# @author hxp
+# @date 2025-06-11
+# @version 1.0
+#
+# 详细描述: 激活武将皮肤
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-06-11 11:00"""
+#-------------------------------------------------------------------------------
+
+import ItemCommon
+import PlayerHero
+
+
+def UseItem(curPlayer, curRoleItem, tick):
+    useItemEff = curRoleItem.GetEffectByIndex(0)
+    heroID = useItemEff.GetEffectValue(0)
+    skinIndex = useItemEff.GetEffectValue(1)
+    PlayerHero.ActiveHeroSkin(curPlayer, heroID, skinIndex, True)
+    ItemCommon.DelItem(curPlayer, curRoleItem, 1)
+    return True
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 897af83..12eae96 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -174,6 +174,7 @@
 from PyMongoDB import RecvPackToMapDB
 import PyMongoMain
 import PlayerTalk
+import PlayerHero
 
 import datetime
 import time
@@ -874,6 +875,7 @@
     
     else:
         PyMongoMain.GetUserCtrlDB().OnPlayerLogin(curPlayer)
+        PlayerHero.OnPlayerLogin(curPlayer)
         PlayerMail.OnPlayerLogin(curPlayer)
         PlayerChatBox.OnPlayerLogin(curPlayer)
         PlayerFace.OnPlayerLogin(curPlayer)
@@ -1481,6 +1483,9 @@
     #初始化寻宝背包
     PlayerControl.Init_TreasurePack(curPlayer)
     
+    #初始化英雄背包
+    PlayerControl.Init_HeroPack(curPlayer)
+    
     #初始化神兽物品背包
     curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptDogzItem)
     curPack.SetCount(ItemCommon.GetPackInitCount(ShareDefine.rptDogzItem))
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 bcc26a4..647a9d6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -5676,8 +5676,20 @@
     #通知客户端
     curPack.Sync_PackCanUseCount()
     return
-    
 
+def Init_HeroPack(curPlayer):
+    packType = ShareDefine.rptHero    
+    #获取玩家背包
+    curPack = curPlayer.GetItemManager().GetPack(packType)
+    initCount = ItemCommon.GetPackInitCount(packType)
+    if packType in ChConfig.Def_Type_CanBuyPack_PlayerDict.keys():
+        keyName = ChConfig.Def_Type_CanBuyPack_PlayerDict.get(packType)[ChConfig.Def_PlayerPackDict_Index_Key]
+        initCount += curPlayer.NomalDictGetProperty(keyName)
+    curPack.SetCount(initCount)
+    #通知客户端背包格子数目
+#    curPlayer.Sync_ItemCount(curPack.GetCount())
+    curPack.Sync_PackCanUseCount()
+    return
 
 
 ##初始化寻宝背包
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
new file mode 100644
index 0000000..7540395
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
@@ -0,0 +1,923 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerHero
+#
+# @todo:武将英雄
+# @author hxp
+# @date 2025-06-11
+# @version 1.0
+#
+# 详细描述: 武将英雄
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-06-11 11:00"""
+#-------------------------------------------------------------------------------
+
+import ItemCommon
+import ShareDefine
+import IpyGameDataPY
+import IPY_GameWorld
+import ItemControler
+import ChPyNetSendPack
+import NetPackCommon
+import PlayerControl
+import GameWorld
+import ChConfig
+
+import random
+
+def OnPlayerLogin(curPlayer):
+    Sync_HeroInfo(curPlayer)
+    return
+
+def InitHeroItem(singleItem):
+    ## 武将卡牌初始化:初始等级1; 星级、突破等级、觉醒等级均为0
+    singleItem.SetUserAttr(ShareDefine.Def_IudetHeroLV, 1)
+    if singleItem.GetUserAttr(ShareDefine.Def_IudetHeroStar):
+        singleItem.SetUserAttr(ShareDefine.Def_IudetHeroStar, 0)
+    if singleItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV):
+        singleItem.SetUserAttr(ShareDefine.Def_IudetHeroBreakLV, 0)
+    if singleItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV):
+        singleItem.SetUserAttr(ShareDefine.Def_IudetHeroAwakeLV, 0)
+    if singleItem.GetUserAttr(ShareDefine.Def_IudetHeroSkin):
+        singleItem.SetUserAttr(ShareDefine.Def_IudetHeroSkin, 0)
+    if singleItem.GetUserAttr(ShareDefine.Def_IudetHeroPosNum):
+        singleItem.SetUserAttr(ShareDefine.Def_IudetHeroPosNum, 0)
+        
+    if singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentID):
+        singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentID)
+    if singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDLV):
+        singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentIDLV)
+    if singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentWashLock):
+        singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentWashLock)
+    if singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentWashID):
+        singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentWashID)
+    if singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDAwakeRand):
+        singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentIDAwakeRand)
+        
+    InitHeroTalent(singleItem)
+    return
+
+def InitHeroTalent(singleItem):
+    '''初始化槽位天赋,不同槽位天赋ID不能一样
+    '''
+    heroID = singleItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    quality = heroIpyData.GetQuality()
+    qualityIpyData = IpyGameDataPY.GetIpyGameData("HeroQuality", quality)
+    if not qualityIpyData:
+        return
+    
+    initTalentCnt = 1
+    initTalentWeight = qualityIpyData.GetInitTalentWeight() # 初始天赋数权重
+    if initTalentWeight:
+        initTalentCnt = GameWorld.GetResultByWeightList(initTalentWeight, 1)
+        
+    talentIDDict = {}
+    talentWeightList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetHeroTalentCount()):
+        talentIpyData = ipyDataMgr.GetHeroTalentByIndex(index)
+        talentID = talentIpyData.GetTalentID()
+        initWeight = talentIpyData.GetInitWeight()
+        talentWeightList.append([initWeight, talentID])
+        talentIDDict[talentID] = initWeight
+        
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentID)
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentIDLV)
+    for _ in range(initTalentCnt):
+        randTalentID = GameWorld.GetResultByWeightList(talentWeightList)
+        if not randTalentID:
+            continue
+        
+        # 移除确保不重复
+        randWeightID = [talentIDDict.get(randTalentID, 0), randTalentID]
+        if randWeightID in talentWeightList:
+            talentWeightList.remove(randWeightID)
+            
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentID, randTalentID)
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentIDLV, 1)
+        
+    return
+
+def OnGiveHeroItem(curPlayer, heroItem):
+    ## 获得某个武将
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    heroIndex = heroIpyData.GetHeroIndex()
+    heroActState = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex)
+    if not heroActState:
+        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex, 1)
+        GameWorld.DebugLog("首次激活武将: heroID=%s,heroIndex=%s" % (heroID, heroIndex), curPlayer.GetPlayerID())
+        Sync_HeroInfo(curPlayer, [heroID])
+    return
+
+def GetHeroItem(curPlayer, itemIndex):
+    curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero)
+    if itemIndex < 0 or itemIndex >= curPack.GetCount():
+        return
+    heroItem = curPack.GetAt(itemIndex)
+    if not heroItem or heroItem.IsEmpty():
+        return
+    if heroItem.GetType() != ChConfig.Def_ItemType_Hero:
+        return
+    return heroItem
+
+#// B2 30 武将升级 #tagCSHeroLVUP
+#
+#struct    tagCSHeroLVUP
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#};
+def OnHeroLVUP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    itemIndex = clientData.ItemIndex
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    quality = heroIpyData.GetQuality()
+    breakLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+    heroLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroLV)
+    LVMax = GetHeroLVMax(heroItem)
+    GameWorld.DebugLog("请求武将升级: itemIndex=%s,heroID=%s,heroLV=%s,quality=%s,breakLV=%s,LVMax=%s" 
+                       % (itemIndex, heroID, heroLV, quality, breakLV, LVMax), playerID)
+    if heroLV >= LVMax:
+        GameWorld.DebugLog("该武将已满级!LVMax=%s" % (LVMax), playerID)
+        return
+    qualityIpyData = IpyGameDataPY.GetIpyGameData("HeroQuality", quality)
+    if not qualityIpyData:
+        return
+    costItemInfo = qualityIpyData.GetUPCostItem()
+    if not costItemInfo:
+        return
+    costItemID, costItemCount = costItemInfo
+    if not costItemID or not costItemCount:
+        return
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    hasEnough, itemIndexList = ItemCommon.GetItem_FromPack_ByID(costItemID, itemPack, costItemCount)
+    if not hasEnough:
+        GameWorld.DebugLog("材料不足,武将无法升级! costItemID=%s, costItemCount=%s" % (costItemID, costItemCount))
+        return
+    ItemCommon.ReduceItem(curPlayer, itemPack, itemIndexList, costItemCount, True, "HeroLVUP")
+    
+    updHeroLV = heroLV + 1
+    GameWorld.DebugLog("武将升级: itemIndex=%s,heroID=%s,updHeroLV=%s" % (itemIndex, heroID, updHeroLV), playerID)
+    heroItem.SetUserAttr(ShareDefine.Def_IudetHeroLV, updHeroLV)
+    
+    # 刷属性,之后扩展
+    
+    return
+
+def GetHeroLVMax(heroItem):
+    ## 获取武将当前最大等级
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return 0
+    quality = heroIpyData.GetQuality()
+    breakLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+    qualityBreakIpyData = IpyGameDataPY.GetIpyGameData("HeroQualityBreak", quality, breakLV)
+    if not qualityBreakIpyData:
+        return 0
+    LVMax = qualityBreakIpyData.GetLVMax()
+    return LVMax
+
+#// B2 31 武将升星 #tagCSHeroStarUP
+#
+#struct    tagCSHeroStarUP
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#    WORD        UseItemIndex;    //使用武将材料物品所在武将背包位置索引
+#};
+def OnHeroStarUP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    itemIndex = clientData.ItemIndex
+    useItemIndex = clientData.UseItemIndex
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    useItem = GetHeroItem(curPlayer, useItemIndex)
+    if not heroItem or not useItem or itemIndex == useItemIndex:
+        return
+    heroID = heroItem.GetItemTypeID()
+    useHeroID = useItem.GetItemTypeID()
+    GameWorld.DebugLog("请求武将升星: itemIndex=%s,heroID=%s,useItemIndex=%s,useHeroID=%s" 
+                       % (itemIndex, heroID, useItemIndex, useHeroID), playerID)
+    if heroID != useHeroID:
+        GameWorld.DebugLog("武将材料非本体,无法升星!", playerID)
+        return
+    washIDCnt = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentWashID)
+    if washIDCnt:
+        GameWorld.ErrLog("武将洗炼结果未处理,无法升星! itemIndex=%s,heroID=%s" % (itemIndex, heroID), playerID)
+        return
+    awakeRandCnt = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDAwakeRand)
+    if awakeRandCnt:
+        GameWorld.ErrLog("武将觉醒解锁天赋未选择,无法升星! itemIndex=%s,heroID=%s" % (itemIndex, heroID), playerID)
+        return
+    useBreakLV = useItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+    useAwakeLV = useItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV)
+    if useBreakLV or useAwakeLV:
+        GameWorld.DebugLog("材料卡突破或觉醒等级不为0暂时无法升星!useBreakLV=%s,useAwakeLV=%s" % (useBreakLV, useAwakeLV), playerID)
+        return
+    
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    quality = heroIpyData.GetQuality()
+    star = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+    awakeLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV)
+    starMax = GetHeroStarMax(heroItem)
+    GameWorld.DebugLog("heroID=%s,star=%s,quality=%s,awakeLV=%s,starMax=%s" % (heroID, star, quality, awakeLV, starMax), playerID)
+    if star >= starMax:
+        GameWorld.DebugLog("该武将已满星!starMax=%s" % (starMax), playerID)
+        return
+    useStar = useItem.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+    addStar = useStar + 1
+    updStar = star + addStar
+    GameWorld.DebugLog("武将升星: itemIndex=%s,heroID=%s,star=%s,useStar=%s,addStar=%s,updStar=%s" 
+                       % (itemIndex, heroID, star, useStar, addStar, updStar), playerID)
+    ItemCommon.DelItem(curPlayer, useItem, useItem.GetCount(), False, "HeroStarUP")
+    DoHeroUpdStar(curPlayer, heroItem, updStar)
+    return
+
+def GetHeroStarMax(heroItem):
+    ## 获取武将当前最大星级
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return 0
+    quality = heroIpyData.GetQuality()
+    qualityIpyData = IpyGameDataPY.GetIpyGameData("HeroQuality", quality)
+    if not qualityIpyData:
+        return 0
+    InitStarUpper = qualityIpyData.GetInitStarUpper()
+    
+    addStarUpper = 0
+    heroAwakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroAwake", heroID)
+    if heroAwakeIpyDataList:
+        awakeLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV)
+        for ipyData in heroAwakeIpyDataList:
+            if ipyData.GetAwakeLV() > awakeLV:
+                break
+            #ipyData.GetUnlockTalentSlot()
+            addStarUpper += ipyData.GetAddStarUpper()
+            
+    starMax = InitStarUpper + addStarUpper
+    return starMax
+
+def DoHeroUpdStar(curPlayer, heroItem, updStar):
+    ## 执行武将星级更新
+    curStar = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+    addStar = updStar - curStar
+    item = heroItem.GetItem()
+    item.SetUserAttr(ShareDefine.Def_IudetHeroStar, updStar)
+    if addStar > 0:
+        __DoHeroStarTalentUp(item, addStar)
+    heroItem.Sync_Item()
+    
+    # 刷属性,之后扩展
+    
+    return
+
+def __DoHeroStarTalentUp(singleItem, addLV):
+    ## 执行武将星级天赋等级提升
+    
+    commTalentSlot = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 1) # 常规天赋槽个数
+    talentMaxLV = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 2) # 每个天赋最大等级
+    idCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentID)
+    lvCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDLV)
+    idList, lvList = [], [] # 记录在物品上的值,有顺序
+    unfullLVIDList = [] # 未满级的天赋ID
+    haveUp = False
+    for index in range(min(idCount, lvCount)):
+        talentID = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentID, index)
+        talentLV = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentIDLV, index)
+        idList.append(talentID)
+        lvList.append(talentLV)
+        if talentLV < talentMaxLV:
+            unfullLVIDList.append(talentID)
+            
+    if len(idList) < commTalentSlot:
+        idList += [0] * (commTalentSlot - len(idList))
+        lvList += [0] * (commTalentSlot - len(lvList))
+        
+    GameWorld.DebugLog("执行武将星级天赋等级提升: addLV=%s" % addLV)
+    GameWorld.DebugLog("当前星级天赋: idList=%s,lvList=%s" % (idList, lvList))
+    GameWorld.DebugLog("未满级星级天赋ID: %s" % unfullLVIDList)
+    
+    # 有空余槽位,优先给空余槽位天赋,额外解锁的槽位是需要先选择的,所以一定不为空,故这里只判断常规槽位即可
+    if 0 in idList:
+        idWeightDict = {}
+        talentWeightList = []
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for index in range(ipyDataMgr.GetHeroTalentCount()):
+            talentIpyData = ipyDataMgr.GetHeroTalentByIndex(index)
+            talentID = talentIpyData.GetTalentID()
+            if talentID in idList:
+                # 天赋ID不可重复
+                continue
+            weight = talentIpyData.GetWashWeight()
+            talentWeightList.append([weight, talentID])
+            idWeightDict[talentID] = weight
+            
+        GameWorld.DebugLog("常规空槽位增加天赋数:%s" % addLV)
+        for _ in range(addLV):
+            if 0 not in idList:
+                break
+            randTalentID = GameWorld.GetResultByWeightList(talentWeightList)
+            if not randTalentID:
+                continue
+            # 移除确保不重复
+            randWeightID = [idWeightDict.get(randTalentID, 0), randTalentID]
+            if randWeightID in talentWeightList:
+                talentWeightList.remove(randWeightID)
+            zeroIndex = idList.index(0)
+            idList[zeroIndex] = randTalentID
+            lvList[zeroIndex] = 1
+            unfullLVIDList.append(randTalentID)
+            GameWorld.DebugLog("新增星级天赋ID: %s" % (randTalentID))
+            addLV -= 1
+            haveUp = True
+            
+    # 剩下的等级次数对已有天赋进行升级
+    if addLV > 0:
+        for _ in range(addLV):
+            if not unfullLVIDList:
+                break
+            randID = random.choice(unfullLVIDList)
+            if randID not in idList:
+                unfullLVIDList.remove(randID)
+                continue
+            randIndex = idList.index(randID)
+            idLV = lvList[randIndex]
+            
+            if idLV < talentMaxLV:
+                idLV += 1
+                lvList[randIndex] = idLV
+                GameWorld.DebugLog("升级星级天赋ID: %s,idLV=%s,index=%s" % (randID, idLV, randIndex))
+                
+            if idLV >= talentMaxLV:
+                unfullLVIDList.remove(randID)
+                GameWorld.DebugLog("    移除未满级ID: %s,unfullLVIDList=%s" % (randID, unfullLVIDList))
+                
+            haveUp = True
+            
+    if not haveUp:
+        return
+    GameWorld.DebugLog("更新星级天赋: idList=%s,lvList=%s" % (idList, lvList))
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentID)
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentIDLV)
+    for index, talentID in enumerate(idList):
+        if not talentID:
+            break
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentID, talentID)
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentIDLV, lvList[index])
+    return
+
+#// B2 32 武将突破 #tagCSHeroBreak
+#
+#struct    tagCSHeroBreak
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#};
+def OnHeroBreak(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    itemIndex = clientData.ItemIndex
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    quality = heroIpyData.GetQuality()
+    breakLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV)
+    GameWorld.DebugLog("请求武将突破: itemIndex=%s,heroID=%s,quality=%s,breakLV=%s" 
+                       % (itemIndex, heroID, quality, breakLV), playerID)
+    ipyData = IpyGameDataPY.GetIpyGameData("HeroQualityBreak", quality, breakLV)
+    if not ipyData:
+        return
+    nextBreakLV = breakLV + 1
+    if not IpyGameDataPY.GetIpyGameData("HeroQualityBreak", quality, nextBreakLV):
+        GameWorld.DebugLog("突破等级已满级: quality=%s,breakLV=%s" % (quality, breakLV), playerID)
+        return
+    costItemInfo = ipyData.GetUPCostItem()
+    if not costItemInfo:
+        return
+    costItemID, costItemCount = costItemInfo
+    if not costItemID or not costItemCount:
+        return
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    hasEnough, itemIndexList = ItemCommon.GetItem_FromPack_ByID(costItemID, itemPack, costItemCount)
+    if not hasEnough:
+        GameWorld.DebugLog("材料不足,武将无法突破! costItemID=%s, costItemCount=%s" % (costItemID, costItemCount))
+        return
+    ItemCommon.ReduceItem(curPlayer, itemPack, itemIndexList, costItemCount, True, "HeroBreak")
+    GameWorld.DebugLog("武将突破: itemIndex=%s,heroID=%s,nextBreakLV=%s" % (itemIndex, heroID, nextBreakLV), playerID)
+    SetHeroBreakLV(heroItem, nextBreakLV)
+    
+    # 刷属性,之后扩展
+    
+    return
+
+def SetHeroBreakLV(heroItem, breakLV):
+    ## 设置武将突破等级
+    heroItem.SetUserAttr(ShareDefine.Def_IudetHeroBreakLV, breakLV)
+    return
+
+#// B2 33 武将觉醒 #tagCSHeroAwake
+#
+#struct    tagCSHeroAwake
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#};
+def OnHeroAwake(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    itemIndex = clientData.ItemIndex
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    quality = heroIpyData.GetQuality()
+    starLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroStar)
+    awakeLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV)
+    GameWorld.DebugLog("请求武将觉醒: itemIndex=%s,heroID=%s,quality=%s,awakeLV=%s,starLV=%s" 
+                       % (itemIndex, heroID, quality, awakeLV, starLV), playerID)
+    awakeLimitStar = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 4)
+    commTalentSlot = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 1) # 常规天赋槽个数
+    if starLV < awakeLimitStar or starLV < commTalentSlot:
+        GameWorld.DebugLog("当前星级不可觉醒: starLV=%s < %s, %s" % (starLV, awakeLimitStar, commTalentSlot), playerID)
+        return
+    ipyData = IpyGameDataPY.GetIpyGameData("HeroQualityAwake", quality, awakeLV)
+    if not ipyData:
+        return
+    nextAwakeLV = awakeLV + 1
+    if not IpyGameDataPY.GetIpyGameData("HeroQualityAwake", quality, nextAwakeLV):
+        GameWorld.DebugLog("觉醒等级已满级: quality=%s,awakeLV=%s" % (quality, awakeLV), playerID)
+        return
+    costItemInfo = ipyData.GetUPCostItem()
+    if not costItemInfo:
+        return
+    costItemID, costItemCount = costItemInfo
+    if not costItemID or not costItemCount:
+        return
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    hasEnough, itemIndexList = ItemCommon.GetItem_FromPack_ByID(costItemID, itemPack, costItemCount)
+    if not hasEnough:
+        GameWorld.DebugLog("材料不足,武将无法觉醒! costItemID=%s, costItemCount=%s" % (costItemID, costItemCount))
+        return
+    ItemCommon.ReduceItem(curPlayer, itemPack, itemIndexList, costItemCount, True, "HeroAwake")
+    GameWorld.DebugLog("武将觉醒: itemIndex=%s,heroID=%s,nextBreakLV=%s" % (itemIndex, heroID, nextAwakeLV), playerID)
+    SetHeroAwakeLV(heroItem, nextAwakeLV)
+    
+    # 刷属性,之后扩展
+    
+    return
+
+def SetHeroAwakeLV(heroItem, awakeLV):
+    ## 设置武将觉醒等级
+    item = heroItem.GetItem()
+    item.SetUserAttr(ShareDefine.Def_IudetHeroAwakeLV, awakeLV)
+    unlockTalentSlotByAwake(item)
+    heroItem.Sync_Item()
+    return
+
+def unlockTalentSlotByAwake(singleItem):
+    ## 觉醒解锁天赋槽
+    heroID = singleItem.GetItemTypeID()
+    awakeLV = singleItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV)
+    awakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroAwake", heroID)
+    if not awakeIpyDataList:
+        return
+    maxUnlockSlot = 0
+    for ipyData in awakeIpyDataList[:awakeLV][::-1]: # 倒序遍历,第一个命中的就是最大的
+        unlockTalentSlot = ipyData.GetUnlockTalentSlot()
+        if unlockTalentSlot:
+            maxUnlockSlot = unlockTalentSlot
+            break
+    if not maxUnlockSlot:
+        return
+    idCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentID)
+    if idCount >= maxUnlockSlot:
+        return
+    commTalentSlot = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 1) # 常规天赋槽个数
+    if maxUnlockSlot <= commTalentSlot:
+        return
+    awakeRandCnt = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDAwakeRand)
+    if awakeRandCnt:
+        # 已经存在觉醒天赋随机选项,需要先选择后才能继续
+        return
+    
+    # 随机觉醒天赋选项
+    idList = []
+    for index in range(idCount):
+        talentID = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentID, index)
+        idList.append(talentID)
+        
+    GameWorld.DebugLog("觉醒解锁天赋槽: awakeLV=%s,maxUnlockSlot=%s,idList=%s" % (awakeLV, maxUnlockSlot, idList))
+    
+    idWeightDict = {}
+    talentWeightList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetHeroTalentCount()):
+        talentIpyData = ipyDataMgr.GetHeroTalentByIndex(index)
+        talentID = talentIpyData.GetTalentID()
+        if talentID in idList:
+            # 天赋ID不可重复
+            continue
+        weight = talentIpyData.GetAweakWeight()
+        talentWeightList.append([weight, talentID])
+        idWeightDict[talentID] = weight
+        
+    randTalentCnt = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 3)
+    for _ in range(randTalentCnt):
+        randTalentID = GameWorld.GetResultByWeightList(talentWeightList)
+        if not randTalentID:
+            continue
+        # 移除确保不重复
+        randWeightID = [idWeightDict.get(randTalentID, 0), randTalentID]
+        if randWeightID in talentWeightList:
+            talentWeightList.remove(randWeightID)
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentIDAwakeRand, randTalentID)
+        GameWorld.DebugLog("随机觉醒天赋选项: randTalentID=%s" % (randTalentID))
+        
+    return
+
+#// B2 34 武将觉醒选择天赋 #tagCSHeroAwakeSelectTalent
+#
+#struct    tagCSHeroAwakeSelectTalent
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#    BYTE        SelectIndex;    //选择新解锁槽位的天赋索引
+#};
+def OnHeroAwakeSelectTalent(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    itemIndex = clientData.ItemIndex
+    selectIndex = clientData.SelectIndex
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    heroID = heroItem.GetItemTypeID()
+    awakeRandCnt = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDAwakeRand)
+    if not awakeRandCnt or selectIndex >= awakeRandCnt:
+        GameWorld.DebugLog("不存在该觉醒天赋随机选项! heroID=%s,selectIndex=%s,awakeRandCnt=%s" % (heroID, selectIndex, awakeRandCnt), playerID)
+        return
+    selectTalentID = heroItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentIDAwakeRand, selectIndex)
+    if not selectTalentID:
+        return
+    
+    singleItem = heroItem.GetItem()
+    idCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentID)
+    lvCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDLV)
+    idList, lvList = [], [] # 记录在物品上的值,有顺序
+    for index in range(min(idCount, lvCount)):
+        talentID = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentID, index)
+        talentLV = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentIDLV, index)
+        idList.append(talentID)
+        lvList.append(talentLV)
+        
+    commTalentSlot = IpyGameDataPY.GetFuncCfg("HeroStarTalent", 1) # 常规天赋槽个数
+    if idCount < commTalentSlot:
+        idList += [0] * (commTalentSlot - idCount)
+        lvList += [0] * (commTalentSlot - idCount)
+        
+    if selectTalentID in idList:
+        GameWorld.ErrLog("选择天赋ID不能重复! heroID=%s,selectIndex=%s,selectTalentID=%s in %s" 
+                         % (heroID, selectIndex, selectTalentID, idList), playerID)
+        return
+    
+    idList.append(selectTalentID)
+    lvList.append(1)
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentIDAwakeRand)
+    
+    GameWorld.DebugLog("更新选择天赋: selectTalentID=%s,idList=%s,lvList=%s" % (selectTalentID, idList, lvList))
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentID)
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentIDLV)
+    for index, talentID in enumerate(idList):
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentID, talentID)
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentIDLV, lvList[index])
+            
+    unlockTalentSlotByAwake(singleItem)
+    
+    heroItem.Sync_Item()
+    
+    # 刷属性,之后扩展
+    
+    return
+
+#// B2 35 武将洗炼 #tagCSHeroWash
+#
+#struct    tagCSHeroWash
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#    BYTE        LockCnt;
+#    BYTE        LockTalentIndexs[LockCnt];    //锁定天赋索引列表
+#    BYTE        OPType;    // 操作类型:0-执行洗炼;1-替换原天赋;2-保留原天赋
+#};
+def OnHeroWash(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    itemIndex = clientData.ItemIndex
+    lockTalentIndexs = clientData.LockTalentIndexs
+    opType = clientData.OPType
+    
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    
+    if opType == 1:
+        HeroTalentWashReplace(curPlayer, itemIndex, heroItem)
+    elif opType == 2:
+        heroItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentWashID)
+    else:
+        HeroTalentWash(curPlayer, itemIndex, heroItem, lockTalentIndexs)
+        
+    return
+
+def HeroTalentWash(curPlayer, itemIndex, heroItem, lockTalentIndexs):
+    ## 武将洗炼
+    
+    heroID = heroItem.GetItemTypeID()
+    GameWorld.DebugLog("武将洗炼: itemIndex=%s,heroID=%s,lockTalentIndexs=%s" % (itemIndex, heroID, lockTalentIndexs))
+    washIDCnt = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentWashID)
+    if washIDCnt:
+        GameWorld.ErrLog("武将洗炼结果未处理,无法洗炼! washIDCnt=%s" % washIDCnt)
+        return
+    
+    washCostItemInfo = IpyGameDataPY.GetFuncEvalCfg("HeroWash", 1)
+    lockCostItemInfo = IpyGameDataPY.GetFuncEvalCfg("HeroWash", 2)
+    if not washCostItemInfo or not lockCostItemInfo:
+        return
+    washItemID, washCostItemCount = washCostItemInfo
+    lockItemID, lockCostItemCount = lockCostItemInfo
+    
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    hasEnough, washItemIndexList = ItemCommon.GetItem_FromPack_ByID(washItemID, itemPack, washCostItemCount)
+    if not hasEnough:
+        GameWorld.DebugLog("洗炼材料不足,武将无法洗炼! washItemID=%s,washCostItemCount=%s" % (washItemID, washCostItemCount))
+        return
+    lockItemIndexList = []
+    lockCostItemCountTotal = 0
+    if lockTalentIndexs:
+        lockCostItemCountTotal = len(lockTalentIndexs) * lockCostItemCount
+        hasEnough, lockItemIndexList = ItemCommon.GetItem_FromPack_ByID(lockItemID, itemPack, lockCostItemCountTotal)
+        if not hasEnough:
+            GameWorld.DebugLog("锁定材料不足,武将无法洗炼! lockItemID=%s,lockCostItemCount=%s,lockCostItemCountTotal=%s" 
+                               % (lockItemID, lockCostItemCount, lockCostItemCountTotal))
+            return
+    
+    ItemCommon.ReduceItem(curPlayer, itemPack, washItemIndexList, washCostItemCount, True, "HeroTalentWash")
+    ItemCommon.ReduceItem(curPlayer, itemPack, lockItemIndexList, lockCostItemCountTotal, True, "HeroTalentWash")
+    
+    singleItem = heroItem.GetItem()
+    idCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentID)
+    washIDList = []
+    for index in range(idCount):
+        if index in lockTalentIndexs:
+            talentID = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentID, index)
+            washIDList.append(talentID)
+        else:
+            washIDList.append(0)
+            
+    GameWorld.DebugLog("洗炼前: %s" % (washIDList))
+    
+    idWeightDict = {}
+    talentWeightList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetHeroTalentCount()):
+        talentIpyData = ipyDataMgr.GetHeroTalentByIndex(index)
+        talentID = talentIpyData.GetTalentID()
+        if talentID in washIDList:
+            # 天赋ID不可重复
+            continue
+        weight = talentIpyData.GetWashWeight()
+        talentWeightList.append([weight, talentID])
+        idWeightDict[talentID] = weight
+        
+    for index, talentID in enumerate(washIDList):
+        if talentID:
+            continue
+        randTalentID = GameWorld.GetResultByWeightList(talentWeightList)
+        if not randTalentID:
+            continue
+        # 移除确保不重复
+        randWeightID = [idWeightDict.get(randTalentID, 0), randTalentID]
+        if randWeightID in talentWeightList:
+            talentWeightList.remove(randWeightID)
+        washIDList[index] = randTalentID
+    GameWorld.DebugLog("洗炼后: %s" % (washIDList))
+    
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentWashID)
+    for talentID in washIDList:
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentWashID, talentID)
+        
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentWashLock)
+    for index in lockTalentIndexs:
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentWashLock, index)
+        
+    heroItem.Sync_Item()
+    GameWorld.DebugLog("武将洗炼结果! itemIndex=%s,heroID=%s,washIDList=%s,lockTalentIndexs=%s" 
+                       % (itemIndex, heroID, washIDList, lockTalentIndexs))
+    return
+
+def HeroTalentWashReplace(curPlayer, itemIndex, heroItem):
+    ## 武将洗炼替换
+    heroID = heroItem.GetItemTypeID()
+    singleItem = heroItem.GetItem()
+    
+    washIDList = []
+    idCount = singleItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentWashID)
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentID)
+    for index in range(idCount):
+        talentID = singleItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentWashID, index)
+        washIDList.append(talentID)
+        singleItem.AddUserAttr(ShareDefine.Def_IudetHeroTalentID, talentID)
+        
+    singleItem.ClearUserAttr(ShareDefine.Def_IudetHeroTalentWashID)
+    
+    heroItem.Sync_Item()
+    GameWorld.DebugLog("武将洗炼替换! itemIndex=%s,heroID=%s,washIDList=%s" % (itemIndex, heroID, washIDList))
+    
+    # 刷属性,之后扩展
+    
+    return
+
+#// B2 36 武将换肤 #tagCSHeroWearSkin
+#
+#struct    tagCSHeroWearSkin
+#{
+#    tagHead        Head;
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#    BYTE        SkinIndex;    //皮肤索引
+#};
+def OnHeroWearSkin(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    itemIndex = clientData.ItemIndex
+    skinIndex = clientData.SkinIndex
+    heroItem = GetHeroItem(curPlayer, itemIndex)
+    if not heroItem:
+        return
+    heroID = heroItem.GetItemTypeID()
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+    if not heroIpyData:
+        return
+    skinNPCIDList = heroIpyData.GetSkinNPCIDList()
+    if skinIndex > 0: # 0的为默认皮肤,不做限制
+        if skinIndex >= len(skinNPCIDList):
+            GameWorld.DebugLog("该武将不存在该皮肤! heroID=%s,skinIndex=%s" % (heroID, skinIndex))
+            return
+        skinState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkin % heroID)
+        if not skinState & pow(2, skinIndex):
+            GameWorld.DebugLog("该武将皮肤未解锁! heroID=%s,skinIndex=%s,skinState=%s" % (heroID, skinIndex, skinState))
+            return
+    heroItem.SetUserAttr(ShareDefine.Def_IudetHeroSkin, skinIndex)
+    
+    # 刷属性
+    
+    return
+
+def ActiveHeroSkin(curPlayer, heroID, skinIndex, isActive=True):
+    skinState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkin % heroID)
+    if isActive:
+        updState = skinState | pow(2, skinIndex)
+        GameWorld.DebugLog("激活武将皮肤: heroID=%s,skinIndex=%s,skinState=%s,updState=%s" 
+                           % (heroID, skinIndex, skinState, updState), curPlayer.GetPlayerID())
+    else:
+        updState = GameWorld.SetBitValue(skinState, skinIndex, 0)
+        GameWorld.DebugLog("失效武将皮肤: heroID=%s,skinIndex=%s,skinState=%s,updState=%s" 
+                           % (heroID, skinIndex, skinState, updState), curPlayer.GetPlayerID())
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroSkin % heroID, updState)
+    Sync_HeroInfo(curPlayer, [heroID])
+    return
+
+#// B4 12 战斗阵型保存 #tagCSHeroBattlePosSave
+#
+#struct    tagCSHeroBattlePos
+#{
+#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
+#    BYTE        PosNum;        //1~n上阵位置编号  
+#};
+#
+#struct    tagCSHeroBattlePosSave
+#{
+#    tagHead        Head;
+#    BYTE        FuncType;    //布阵功能类型:0-默认主阵型;其他待扩展,如某个活动的防守阵型
+#    BYTE        PosCnt;
+#    tagCSHeroBattlePos    HeroPosList[PosCnt];    // 保存的阵型,只要发送最终的阵型武将位置即可
+#};
+def OnHeroBattlePosSave(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    funcType = clientData.FuncType
+    heroPosList = clientData.HeroPosList
+    
+    heroPosDict = {}
+    indexList = []
+    for posInfo in heroPosList:
+        posNum = posInfo.PosNum
+        itemIndex = posInfo.ItemIndex
+        if itemIndex in indexList:
+            # 单英雄只能一个位置,一个位置只能对应唯一英雄单位
+            continue
+        indexList.append(itemIndex)
+        heroPosDict[posNum] = itemIndex
+        
+    # 主阵型
+    if funcType == 0:
+        MainBattlePosSave(curPlayer, heroPosDict)
+        
+    # 其他待扩展
+    elif funcType == 1:
+        pass
+    
+    return
+
+def MainBattlePosSave(curPlayer, heroPosDict):
+    GameWorld.DebugLog("保留主战斗阵型: %s" % heroPosDict, curPlayer.GetPlayerID())
+    curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero)
+    # 直接重置旧阵型
+    for index in range(curPack.GetCount()):
+        heroItem = curPack.GetAt(index)
+        if not heroItem or heroItem.IsEmpty():
+            continue
+        if not heroItem.GetUserAttr(ShareDefine.Def_IudetHeroPosNum):
+            continue
+        item = heroItem.GetItem()
+        item.ClearUserAttr(ShareDefine.Def_IudetHeroPosNum)
+        
+    # 更新新阵型
+    for posNum, itemIndex in heroPosDict.items():
+        if itemIndex < 0 or itemIndex >= curPack.GetCount():
+            continue
+        heroItem = curPack.GetAt(itemIndex)
+        if not heroItem or heroItem.IsEmpty():
+            continue
+        item = heroItem.GetItem()
+        item.SetUserAttr(ShareDefine.Def_IudetHeroPosNum, posNum)
+        
+    ResetHeroPack(curPlayer)
+    return
+
+def ResetHeroPack(curPlayer):
+    tick = GameWorld.GetGameWorld().GetTick()
+    curPlayer.SetResetItemTick(0)
+    ItemControler.ResetItem(curPlayer, ShareDefine.rptHero, 0, 0, tick)
+    return
+    
+def Sync_HeroInfo(curPlayer, heroIDList=None):
+    if heroIDList != None:
+        syncHeroIDList = heroIDList
+    else:
+        syncHeroIDList = []
+        ipyDataMgr = IpyGameDataPY.IPY_Data()
+        for index in range(ipyDataMgr.GetHeroCount()):
+            ipyData = ipyDataMgr.GetHeroByIndex(index)
+            syncHeroIDList.append(ipyData.GetHeroID())
+    
+    if not syncHeroIDList:
+        return
+    
+    syncInfoList = []
+    for heroID in syncHeroIDList:
+        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+        if not heroIpyData:
+            continue
+        heroIndex = heroIpyData.GetHeroIndex()
+        heroActState = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_HeroActState, heroIndex)
+        if not heroActState and heroIDList == None:
+            continue
+        
+        hero = ChPyNetSendPack.tagSCHero()
+        hero.HeroID = heroID
+        hero.IsActive = heroActState
+        hero.SkinState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkin % heroID)
+        syncInfoList.append(hero)
+        
+    if not syncInfoList:
+        return
+    
+    clientPack = ChPyNetSendPack.tagSCHeroInfo()
+    clientPack.HeroInfoList = syncInfoList
+    clientPack.HeroCnt = len(clientPack.HeroInfoList)    
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py
index 97a2280..60faf07 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py
@@ -17,10 +17,7 @@
 
 import GameWorld
 import PlayerRune
-import ShareDefine
-import GameFuncComm
 import IpyGameDataPY
-import IPY_GameWorld
 import FormulaControl
 import ChPyNetSendPack
 import PlayerControl
@@ -29,7 +26,6 @@
 import PlayerBossReborn
 import PlayerFeastTravel
 import PlayerFairyCeremony
-import PlayerNewFairyCeremony
 import PlayerActLunhuidian
 import PlayerActYunshi
 import PlayerActTask
@@ -37,7 +33,6 @@
 import ChConfig
 
 import random
-import time
 
 # 寻宝类型: >=100的为策划自行配置的自定义寻宝类型,<100的用于指定系统寻宝功能
 TreasureTypeList = (
@@ -48,14 +43,16 @@
 TreasureType_Gubao, # 古宝寻宝 5
 ) = range(1, 1 + 5)
 
+TreasureType_HeroComm = 11 # 英雄招募 - 普通
+TreasureType_HeroHigh = 12 # 英雄招募 - 高级
+TreasureType_HeroScore = 13 # 英雄招募 - 积分
+
 def DoTreasureOpen(curPlayer):
     ## 寻宝开启
     Sync_TreasureInfo(curPlayer)
     return
 
 def OnTreasureLogin(curPlayer):
-    #if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Treasure):
-    #    return
     Sync_TreasureInfo(curPlayer)
     return
 
@@ -269,7 +266,7 @@
         curRateList = [] # 可能会改变饼图,每次抽奖使用新的饼图对象,不要改变配置的饼图概率
         
         # 满幸运必出
-        if updLuck >= maxLuck and luckyGridNumList:
+        if maxLuck and updLuck >= maxLuck and luckyGridNumList:
             if luckyItemRateList:
                 curRateList = GetRemoveLimitGridRateList(luckyItemRateList, gridNumCountInfo, gridNumMaxLimitInfo)
             else:
@@ -403,7 +400,7 @@
     addScoreType = setIpyData.GetAwardMoneyType() # 额外奖励货币类型
     addScore = setIpyData.GetAwardMoneyValue() # 单次奖励货币数
     if addScoreType and addScore:
-        PlayerControl.GiveMoney(curPlayer, addScoreType, addScore)
+        PlayerControl.GiveMoney(curPlayer, addScoreType, addScore * treasureCount)
         
     if treasureType == TreasureType_Rune:
         PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RuneTreasure, treasureCount)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index edb33eb..42cde85 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1161,7 +1161,8 @@
 CDBPlayerRefresh_PayCoinDay, # 代币时效 269
 CDBPlayerRefresh_XianyuanScore, # 仙缘积分 270
 CDBPlayerRefresh_HuanjinggeScore, # 幻境阁积分 271
-) = range(146, 272)
+CDBPlayerRefresh_HeroScore, # 招募积分 272
+) = range(146, 273)
 
 TYPE_Price_Gold_Paper_Money = 5    # 金钱类型,(先用礼券,再用金子)
 TYPE_Price_Family_Contribution = 6 # 战盟贡献度(活跃度转换得来)
@@ -1200,6 +1201,7 @@
 TYPE_Price_Tuijinbi = 48    # 推金币
 TYPE_Price_XianyuanScore = 49    # 仙缘积分
 TYPE_Price_HuanjinggeScore = 50    # 幻境阁积分
+TYPE_Price_HeroScore = 51    # 招募积分
 TYPE_Price_PayCoinDay = 98    # 代币时效,每日过天重置
 TYPE_Price_PayCoin = 99    # 代币
 
@@ -1209,7 +1211,7 @@
                  16:"助战积分", 18:"荣誉", 19:"Boss积分", 23:"符印精华", 24:"符印碎片", 25:"寻宝积分", 26:"集市额度", 27:"丹精", 28:"魂尘", 
                  29:"聚魂碎片", 30:"核心环", 31:"功能特权令", 32:"环保值", 33:"GM令", 34:"古神币", 35:"功德点", 
                  39:"成就积分", 40:"万界积分", 41:"战锤", 42:"结晶", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 46:"古宝养成积分", 47:"天道果", 
-                 49:"仙缘积分", 50:"幻境阁积分",
+                 49:"仙缘积分", 50:"幻境阁积分", 51:"招募积分",
                  98:"代币时效", 99:"代币"
                  }
 
@@ -1254,6 +1256,7 @@
                            TYPE_Price_TiandaoFruit:CDBPlayerRefresh_TiandaoFruit,
                            TYPE_Price_XianyuanScore:CDBPlayerRefresh_XianyuanScore,
                            TYPE_Price_HuanjinggeScore:CDBPlayerRefresh_HuanjinggeScore,
+                           TYPE_Price_HeroScore:CDBPlayerRefresh_HeroScore,
                            TYPE_Price_PayCoinDay:CDBPlayerRefresh_PayCoinDay,
                            }
 
@@ -1333,8 +1336,9 @@
 rptDogzItem,        # 神兽物品背包 32
 rptDogzEquip,       # 神兽装备背包 33
 rptGarbage,         # 垃圾分类背包 34
+rptHero,            # 武将英雄背包 35
 rptMax,             # 最大背包类型数量,放在最后一个
-) = range(28, 28 + 8)  #C++定义的枚举到27
+) = range(28, 28 + 9)  #C++定义的枚举到27
 
 #虚拟背包类型, 从255递减
 Def_VPack_TypeList = (
@@ -1752,6 +1756,11 @@
 Def_IudetLegendAttrValueXian = 63  # 物品传奇属性值列表 - 仙
 Def_IudetLegendAttrIDJi = 55  # 物品传奇属性ID列表 - 极
 Def_IudetLegendAttrValueJi = 65  # 物品传奇属性值列表 - 极
+Def_IudetHeroTalentID = 71  # 英雄天赋ID列表
+Def_IudetHeroTalentIDLV = 73  # 英雄天赋ID等级列表
+Def_IudetHeroTalentWashLock = 75  # 英雄天赋洗炼锁定索引列表
+Def_IudetHeroTalentWashID = 77  # 英雄天赋洗炼随机ID列表
+Def_IudetHeroTalentIDAwakeRand = 79  # 英雄觉醒时随机天赋选项ID列表
 
 Def_IudetItemColor = 16  # 物品颜色,如果该值没有就取物品
 Def_IudetItemCount = 18  # 物品个数,支持20亿,目前仅特殊转化物品会用到
@@ -1768,6 +1777,12 @@
 Def_IudetGatherSoulLV = 46  # 聚魂等级
 Def_IudetExpireTime = 48 # 时效物品指定有效时间,时间单位由时效类型决定
 Def_IudetAuctionItemCreateTime = 50 # 拍品创建时间
+Def_IudetHeroLV = 70 # 英雄等级
+Def_IudetHeroStar = 72 # 英雄星级
+Def_IudetHeroBreakLV = 74 # 英雄突破等级
+Def_IudetHeroAwakeLV = 76 # 英雄觉醒等级
+Def_IudetHeroSkin = 78 # 英雄使用的皮肤索引
+Def_IudetHeroPosNum = 80 # 主阵型上阵位置
 
 # 200~300 宠物数据用
 Def_IudetPet_NPCID = 200  # npcID

--
Gitblit v1.8.0