121 【武将】武将系统-服务端(武将招募;武将背包;武将养成系统;)
15个文件已修改
3个文件已添加
2246 ■■■■■ 已修改文件
PySysDB/PySysDBPY.h 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 520 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItemCount.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py 923 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/MapServerConfig.ini
@@ -1,7 +1,7 @@
[RolePackConfig]
;2000///<所有背包总量限制
;玩家背包配置
PackTypeCnt=35
PackTypeCnt=36
;已删除物品rptDeleted//已无用
PackCnt00=0
@@ -73,3 +73,5 @@
PackCnt33=150
;垃圾分类背包
PackCnt34=30
;武将英雄背包
PackCnt35=500
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
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为通用技能
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):
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):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
New file
@@ -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
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):
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
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", # 增加爵位经验
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,6 +1980,59 @@
 
    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 版重整物品
@@ -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
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
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py
New file
@@ -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
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))
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -5677,7 +5677,19 @@
    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
##初始化寻宝背包
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
New file
@@ -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
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)
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