501 【武将】武将时装-服务端(武将时装激活、升级、穿戴、属性;武将战斗预览;)
12个文件已修改
1个文件已删除
654 ■■■■■ 已修改文件
PySysDB/PySysDBPY.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 120 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TurnFight.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py 257 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -208,14 +208,18 @@
    list        AttrValueList;    // 属性值列表
};
//皮肤表
struct    HeroSkin
//皮肤时装属性表
struct    HeroSkinAttr
{
    DWORD        _SkinID;    //皮肤NPCID
    DWORD        NeedItemID;    //所需道具
    BYTE        StarMax;    //最高星级
    list        WearAttrIDList;    // 穿戴属性ID列表
    list        WearAttrValueList;    // 穿戴属性值列表
    list        AllBatAttrIDList;    // 全体上阵属性ID列表
    list        AllBatAttrValueList;    // 全体上阵属性值列表
    list        WearAttrPerStarAddList;    //穿戴每星加成值列表
    list        RoleAttrIDList;    // 主公属性ID列表
    list        RoleAttrValueList;    // 主公属性初始值列表
    list        RoleAttrPerStarAddList;    //主公每星加成值列表
};
//武将品质表
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -964,7 +964,7 @@
PacketCMD_7=0xB2
PacketSubCMD_7=0x36
PacketCallFunc_7=OnHeroWearSkin
PacketCallFunc_7=OnHeroSkinOP
PacketCMD_8=0xB2
PacketSubCMD_8=0x37
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -701,6 +701,40 @@
        lineupInfo["MGSkillIDList"] = mgSkillIDList
    return lineupInfo
def GetPlayerHeroBatViewLineupInfo(curPlayer, heroID, skinIndex):
    ## 获取玩家战斗预览阵容信息
    playerID = curPlayer.GetPlayerID()
    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
    if not heroIpyData:
        return
    skinIDList = heroIpyData.GetSkinIDList()
    skinID = skinIDList[skinIndex] if len(skinIDList) > skinIndex else 0
    heroBatAttrDict = IpyGameDataPY.GetFuncEvalCfg("HeroBatView", 1, {})
    heroViewInfo = IpyGameDataPY.GetFuncEvalCfg("HeroBatView", 2) # 预览时的武将 站位|等级|星级|突破等级|觉醒等级
    posNum = heroViewInfo[0] if len(heroViewInfo) > 0 else 2
    heroLV = heroViewInfo[1] if len(heroViewInfo) > 1 else 100
    star = heroViewInfo[2] if len(heroViewInfo) > 2 else 0
    breakLV = heroViewInfo[3] if len(heroViewInfo) > 3 else 0
    awakeLV = heroViewInfo[4] if len(heroViewInfo) > 4 else 0
    fightPower = 0
    skillIDlist = GetNPCHeroSkillIDList(heroID, heroIpyData, breakLV, awakeLV)
    heroDict = {}
    heroDict[str(posNum)] = {
                             "HeroID":heroID,
                             "SkinID":skinID,
                             "LV":heroLV,
                             "Star":star,
                             "BreakLV":breakLV,
                             "AwakeLV":awakeLV,
                             "FightPower":fightPower,
                             "AttrDict":{str(k):v for k, v in heroBatAttrDict.items() if v > 0},
                             "SkillIDList":skillIDlist,
                             }
    return {"PlayerID":playerID, "Hero":heroDict}
def GetNPCLineupInfo(lineupID, strongerLV=0, difficulty=0, isLog=True, viewNPCID=0):
    ## 获取NPC阵容信息
    # @param lineupID: 阵容ID
@@ -1200,6 +1234,13 @@
    playerServerID = GameWorld.GetPlayerServerID(curPlayer)
    guid = GameWorld.GetGUID()
    
    if mapID == ChConfig.Def_FBMapID_HeroBatView:
        if not valueList:
            return
        heroID = valueList[0]
        skinIndex = valueList[1] if len(valueList) > 1 else 0
        atkLineupInfo = GetPlayerHeroBatViewLineupInfo(curPlayer, heroID, skinIndex)
    else:
    atkBatPresetType = ChConfig.MapAtkBatPresetTypeDict.get(mapID, ShareDefine.BatPreset_Main)
    atkLineupInfo = GetPlayerLineupInfo(curPlayer, atkBatPresetType, exclusiveMapID=mapID)
    if not atkLineupInfo:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -241,12 +241,14 @@
Def_CalcAttr_Beauty, # 红颜 7
Def_CalcAttr_Dingjunge, # 定军阁 8
Def_CalcAttr_Mingge, # 命格 9
) = range(10)
Def_CalcAttr_HeroSkin, # 武将时装 10
) = range(11)
CalcAttrName = {
                Def_CalcAttr_LV:"主公等级",
                Def_CalcAttr_MainEquip:"主装备",
                Def_CalcAttr_HeroFates:"武将宿缘",
                Def_CalcAttr_HeroSkin:"武将时装",
                Def_CalcAttr_Realm:"官职",
                Def_CalcAttr_Gubao:"古宝",
                Def_CalcAttr_HJG:"幻境阁",
@@ -651,7 +653,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_HeroSkin = 279   #激活武将皮肤; A值-武将ID;B值-皮肤索引 废弃,直接按物品ID处理
Def_Effect_FamilyTaofaCnt = 280   #增加公会讨伐次数; A值-讨伐次数
Def_Effect_AddActivity = 281   #给活跃度
@@ -1882,6 +1884,7 @@
Def_FBMapID_MainBoss = 2 # 主线Boss
Def_FBMapID_ArenaBattle = 3 # 演武场
Def_FBMapID_HeroBatView = 30000 # 武将战斗预览
Def_FBMapID_Zhanchui = 30010 # 白骨盈野/战锤秘境
Def_FBMapID_Tianzi = 30020 # 天子考验
Def_FBMapID_Dingjunge = 30030 # 定军阁
@@ -3663,9 +3666,8 @@
Def_PDict_GoldRushAutoEndTime = "GoldRushAutoEndTime" # 自动淘金到期时间戳
#武将
Def_PDict_HeroSkin = "HeroSkin_%s" # 武将皮肤解锁状态,按皮肤索引二进制存储,参数(武将ID)
Def_PDict_HeroSkinInfo = "HeroSkinInfo_%s" # 武将皮肤,参数(武将ID) 皮肤星级*10 + 是否解锁
Def_PDict_HeroBook = "HeroBook_%s" # 武将图鉴激活等级,参数(武将ID) cccbbba a-初始激活状态1-英雄激活,2-初始图鉴激活; bbb-存星级图鉴激活等级;ccc-存突破图鉴激活等级
Def_PDict_HeroBookH = "HeroBookH_%s" # 武将图鉴历史最高等级,参数(武将ID) cccbbba: bbb-存星级图鉴最高等级;ccc-存突破图鉴最高等级
Def_PDict_HeroAwakeRebirthCnt = "HeroAwakeRebirthCnt" # 已觉醒过的武将今日已重生次数,共享次数
Def_PDict_HeroRecommend = "HeroRecommend_%s" # 阵容推荐领奖状态,参数(推荐ID) 根据武将ID所在索引位记录是否领取
Def_PDict_HeroFatesInfo = "HeroFatesInfo_%s" # 武将宿缘信息,参数(宿缘ID) 宿缘等级*10 + 宿缘状态
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -10307,6 +10307,70 @@
#------------------------------------------------------
# B2 36 武将皮肤操作 #tagCSHeroSkinOP
class  tagCSHeroSkinOP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HeroID", c_int),    #武将ID
                  ("SkinID", c_int),    #ʱװID
                  ("OPType", c_ubyte),    #操作 1-激活;2-佩戴;3-升星
                  ("ItemIndex", c_ushort),    #武将物品所在武将背包位置索引,仅佩戴时有效
                  ]
    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.HeroID = 0
        self.SkinID = 0
        self.OPType = 0
        self.ItemIndex = 0
        return
    def GetLength(self):
        return sizeof(tagCSHeroSkinOP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 36 武将皮肤操作 //tagCSHeroSkinOP:
                                Cmd:%s,
                                SubCmd:%s,
                                HeroID:%d,
                                SkinID:%d,
                                OPType:%d,
                                ItemIndex:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HeroID,
                                self.SkinID,
                                self.OPType,
                                self.ItemIndex
                                )
        return DumpString
m_NAtagCSHeroSkinOP=tagCSHeroSkinOP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSHeroSkinOP.Cmd,m_NAtagCSHeroSkinOP.SubCmd))] = m_NAtagCSHeroSkinOP
#------------------------------------------------------
# B2 31 武将升星 #tagCSHeroStarUP
class  tagCSHeroStarUP(Structure):
@@ -10441,62 +10505,6 @@
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
#------------------------------------------------------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -22496,16 +22496,12 @@
#------------------------------------------------------
# B1 22 武将信息 #tagSCHeroInfo
class  tagSCHero(Structure):
class  tagSCHeroSkin(Structure):
    _pack_ = 1
    _fields_ = [
                  ("HeroID", c_int),    # 武将ID
                  ("SkinState", c_int),    # 武将皮肤已解锁状态信息,按皮肤所在索引二进制位运算判断是否解锁,0索引位默认皮肤,不用验证
                  ("BookInitState", c_ubyte),    # 图鉴激活状态:0-未激活;1-可激活;2-已激活
                  ("BookStarLV", c_ushort),    # 图鉴星级等级
                  ("BookBreakLV", c_ushort),    # 图鉴突破等级
                  ("BookStarLVH", c_ushort),    # 图鉴星级历史最高等级
                  ("BookBreakLVH", c_ushort),    # 图鉴突破历史最高等级
                  ("SkinID", c_int),    #皮肤ID,只通知非默认皮肤
                  ("State", c_ubyte),    #是否已激活
                  ("Star", c_ubyte),    #星级
                  ]
    def __init__(self):
@@ -22518,39 +22514,91 @@
        return _pos + self.GetLength()
    def Clear(self):
        self.HeroID = 0
        self.SkinState = 0
        self.BookInitState = 0
        self.BookStarLV = 0
        self.BookBreakLV = 0
        self.BookStarLVH = 0
        self.BookBreakLVH = 0
        self.SkinID = 0
        self.State = 0
        self.Star = 0
        return
    def GetLength(self):
        return sizeof(tagSCHero)
        return sizeof(tagSCHeroSkin)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B1 22 武将信息 //tagSCHeroInfo:
                                SkinID:%d,
                                State:%d,
                                Star:%d
                                '''\
                                %(
                                self.SkinID,
                                self.State,
                                self.Star
                                )
        return DumpString
class  tagSCHero(Structure):
    HeroID = 0    #(DWORD HeroID)// 武将ID
    BookInitState = 0    #(BYTE BookInitState)// 图鉴激活状态:0-未激活;1-可激活;2-已激活
    SkinCnt = 0    #(BYTE SkinCnt)
    SkinList = list()    #(vector<tagSCHeroSkin> SkinList)// 非默认皮肤信息列表
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.HeroID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
        self.BookInitState,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.SkinCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SkinCnt):
            temSkinList = tagSCHeroSkin()
            _pos = temSkinList.ReadData(_lpData, _pos)
            self.SkinList.append(temSkinList)
        return _pos
    def Clear(self):
        self.HeroID = 0
        self.BookInitState = 0
        self.SkinCnt = 0
        self.SkinList = list()
        return
    def GetLength(self):
        length = 0
        length += 4
        length += 1
        length += 1
        for i in range(self.SkinCnt):
            length += self.SkinList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteDWORD(data, self.HeroID)
        data = CommFunc.WriteBYTE(data, self.BookInitState)
        data = CommFunc.WriteBYTE(data, self.SkinCnt)
        for i in range(self.SkinCnt):
            data = CommFunc.WriteString(data, self.SkinList[i].GetLength(), self.SkinList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                HeroID:%d,
                                SkinState:%d,
                                BookInitState:%d,
                                BookStarLV:%d,
                                BookBreakLV:%d,
                                BookStarLVH:%d,
                                BookBreakLVH:%d
                                SkinCnt:%d,
                                SkinList:%s
                                '''\
                                %(
                                self.HeroID,
                                self.SkinState,
                                self.BookInitState,
                                self.BookStarLV,
                                self.BookBreakLV,
                                self.BookStarLVH,
                                self.BookBreakLVH
                                self.SkinCnt,
                                "..."
                                )
        return DumpString
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Hero.py
@@ -38,11 +38,9 @@
        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 r")
        GameWorld.DebugAnswer(curPlayer, "武将皮肤: Hero sk 武将ID 皮肤索引 是否解锁")
        GameWorld.DebugAnswer(curPlayer, "切换皮肤: Hero ss 背包位置 皮肤索引")
        GameWorld.DebugAnswer(curPlayer, "重置宿缘: Hero sy 0")
        GameWorld.DebugAnswer(curPlayer, "设置宿缘: Hero sy 宿缘ID 等级 [是否激活]")
        GameWorld.DebugAnswer(curPlayer, "新增武将: MakeItemCount 英雄ID [个数]")
@@ -119,7 +117,7 @@
        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)
        PlayerHero.GMSetHeroSkin(curPlayer, heroID, skinIndex, isActive)
        return
    
    if value == "clear":
@@ -232,14 +230,6 @@
            return
        PlayerHero.SetHeroAwakeLV(heroItem, awakeLV)
        GameWorld.DebugAnswer(curPlayer, "设置武将觉醒: %s,itemIndex=%s" % (awakeLV, itemIndex))
    # 切换皮肤
    elif value == "ss":
        skinIndex = msgList[2] if len(msgList) > 2 else 0
        PlayerHero.ActiveHeroSkin(curPlayer, heroID, skinIndex, 1)
        if not PlayerHero.DoHeroWearSkin(curPlayer, itemIndex, skinIndex):
            GameWorld.DebugAnswer(curPlayer, "切换皮肤失败查看地图日志")
        return
    
    PlayerOnline.GetOnlinePlayer(curPlayer).OnHeroItemUpate(heroItem) # GM修改
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TurnFight.py
@@ -33,7 +33,7 @@
#  @remarks 函数详细说明.
def OnExec(curPlayer, msgList):
    if not msgList:
        GameWorld.DebugAnswer(curPlayer, "发起战斗: TurnFight mapID [lineID 玩家ID]")
        GameWorld.DebugAnswer(curPlayer, "发起战斗: TurnFight mapID [lineID 玩家ID V ...]")
        GameWorld.DebugAnswer(curPlayer, "设置属性: TurnFight a 属性ID 值 [阵营 位置] ")
        GameWorld.DebugAnswer(curPlayer, "击杀目标: TurnFight k 阵营 [位置 ...] ")
        GameWorld.DebugAnswer(curPlayer, "添加buff: TurnFight b 阵营  位置 buff归属阵营 位置 技能ID [ID ...]")
@@ -72,6 +72,7 @@
    clientData.FuncLineID = funcLineID
    clientData.TagType = 0 if not tagPlayerID else 1
    clientData.TagID = tagPlayerID
    clientData.ValueList = msgList[3:]
    index = curPlayer.GetIndex()
    tick = GameWorld.GetGameWorld().GetTick()
    if not TurnAttack.OnTurnFight(index, clientData, tick):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -216,12 +216,16 @@
                        ("list", "AttrValueList", 0),
                        ),
                "HeroSkin":(
                "HeroSkinAttr":(
                        ("DWORD", "SkinID", 1),
                        ("DWORD", "NeedItemID", 0),
                        ("BYTE", "StarMax", 0),
                        ("list", "WearAttrIDList", 0),
                        ("list", "WearAttrValueList", 0),
                        ("list", "AllBatAttrIDList", 0),
                        ("list", "AllBatAttrValueList", 0),
                        ("list", "WearAttrPerStarAddList", 0),
                        ("list", "RoleAttrIDList", 0),
                        ("list", "RoleAttrValueList", 0),
                        ("list", "RoleAttrPerStarAddList", 0),
                        ),
                "HeroQuality":(
@@ -1994,18 +1998,22 @@
    def GetAttrIDList(self): return self.attrTuple[2] #  属性ID列表 list
    def GetAttrValueList(self): return self.attrTuple[3] #  属性值列表 list
# 皮肤表
class IPY_HeroSkin():
# 皮肤时装属性表
class IPY_HeroSkinAttr():
    
    def __init__(self):
        self.attrTuple = None
        return
        
    def GetSkinID(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
    def GetNeedItemID(self): return self.attrTuple[1] # 所需道具 DWORD
    def GetStarMax(self): return self.attrTuple[2] # 最高星级 BYTE
    def GetWearAttrIDList(self): return self.attrTuple[3] #  穿戴属性ID列表 list
    def GetWearAttrValueList(self): return self.attrTuple[4] #  穿戴属性值列表 list
    def GetWearAttrPerStarAddList(self): return self.attrTuple[5] # 穿戴每星加成值列表 list
    def GetRoleAttrIDList(self): return self.attrTuple[6] #  主公属性ID列表 list
    def GetRoleAttrValueList(self): return self.attrTuple[7] #  主公属性初始值列表 list
    def GetRoleAttrPerStarAddList(self): return self.attrTuple[8] # 主公每星加成值列表 list
# 武将品质表
class IPY_HeroQuality():
@@ -4377,7 +4385,7 @@
        self.__LoadFileData("HeroAwake", onlyCheck)
        self.__LoadFileData("HeroFetter", onlyCheck)
        self.__LoadFileData("HeroLineupHalo", onlyCheck)
        self.__LoadFileData("HeroSkin", onlyCheck)
        self.__LoadFileData("HeroSkinAttr", onlyCheck)
        self.__LoadFileData("HeroQuality", onlyCheck)
        self.__LoadFileData("HeroQualityBreak", onlyCheck)
        self.__LoadFileData("HeroQualityAwake", onlyCheck)
@@ -4843,12 +4851,12 @@
        self.CheckLoadData("HeroLineupHalo")
        return self.ipyHeroLineupHaloCache[index]
    def GetHeroSkinCount(self):
        self.CheckLoadData("HeroSkin")
        return self.ipyHeroSkinLen
    def GetHeroSkinByIndex(self, index):
        self.CheckLoadData("HeroSkin")
        return self.ipyHeroSkinCache[index]
    def GetHeroSkinAttrCount(self):
        self.CheckLoadData("HeroSkinAttr")
        return self.ipyHeroSkinAttrLen
    def GetHeroSkinAttrByIndex(self, index):
        self.CheckLoadData("HeroSkinAttr")
        return self.ipyHeroSkinAttrCache[index]
    def GetHeroQualityCount(self):
        self.CheckLoadData("HeroQuality")
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -589,7 +589,6 @@
                            ChConfig.Def_Effect_AddFBCnt:"Item_AddFBCnt", # 增加副本可进入次数
                            ChConfig.Def_Effect_EmojiPack:"Item_EmojiPack",
                            ChConfig.Def_Effect_FamilyEmblem:"Item_FamilyEmblem",
                            ChConfig.Def_Effect_HeroSkin:"Item_HeroSkin",  # 武将皮肤
                            ChConfig.Def_Effect_FamilyTaofaCnt:"Item_FamilyTaofaCnt",  # 增加公会讨伐次数
                            }
    
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_HeroSkin.py
File was deleted
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
@@ -229,55 +229,21 @@
    GameWorld.DebugLog("设置武将图鉴激活状态:%s,bookState=%s,updBookState=%s" % (isAct, bookState, updBookState), curPlayer.GetPlayerID())
    return
#def GetHeroBookStarLV(curPlayer, heroID):
#    ## 武将图鉴星级等级
#    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
#    return GameWorld.GetValue(bookState, 4, 3)
#def SetHeroBookStarLV(curPlayer, heroID, starLV):
#    ## 设置武将图鉴星级等级,支持三位数 0~999 级
#    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
#    updBookState = GameWorld.SetValue(bookState, 4, 3, starLV)
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, updBookState)
#    GameWorld.DebugLog("设置武将图鉴星级等级:%s,bookState=%s,updBookState=%s" % (starLV, bookState, updBookState), curPlayer.GetPlayerID())
#    return
#def GetHeroBookStarLVH(curPlayer, heroID):
#    ## 武将图鉴星级历史最高等级
#    bookStateH = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBookH % heroID)
#    return GameWorld.GetValue(bookStateH, 4, 3)
#def SetHeroBookStarLVH(curPlayer, heroID, starLVH):
#    ## 设置武将图鉴星级历史最高等级,支持三位数 0~999 级
#    bookStateH = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBookH % heroID)
#    updBookStateH = GameWorld.SetValue(bookStateH, 4, 3, starLVH)
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBookH % heroID, updBookStateH)
#    GameWorld.DebugLog("设置武将图鉴星级历史最高等级:%s,bookStateH=%s,updBookStateH=%s" % (starLVH, bookStateH, updBookStateH), curPlayer.GetPlayerID())
#    Sync_HeroInfo(curPlayer, [heroID])
#    return
#def GetHeroBookBreakLV(curPlayer, heroID):
#    ## 武将图鉴突破等级
#    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
#    return GameWorld.GetValue(bookState, 7, 3)
#def SetHeroBookBreakLV(curPlayer, heroID, breakLV):
#    ## 设置武将图鉴突破等级,支持三位数 0~999 级
#    bookState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID)
#    updBookState = GameWorld.SetValue(bookState, 7, 3, breakLV)
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBook % heroID, updBookState)
#    GameWorld.DebugLog("设置武将图鉴突破等级:%s,bookState=%s,updBookState=%s" % (breakLV, bookState, updBookState), curPlayer.GetPlayerID())
#    return
#def GetHeroBookBreakLVH(curPlayer, heroID):
#    ## 武将图鉴突破历史最高等级
#    bookStateH = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBookH % heroID)
#    return GameWorld.GetValue(bookStateH, 7, 3)
#def SetHeroBookBreakLVH(curPlayer, heroID, breakLVH):
#    ## 设置武将图鉴突破历史最高等级,支持三位数 0~999 级
#    bookStateH = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBookH % heroID)
#    updBookStateH = GameWorld.SetValue(bookStateH, 7, 3, breakLVH)
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroBookH % heroID, updBookStateH)
#    GameWorld.DebugLog("设置武将图鉴突破历史最高等级:%s,bookStateH=%s,updBookStateH=%s" % (breakLVH, bookStateH, updBookStateH), curPlayer.GetPlayerID())
#    Sync_HeroInfo(curPlayer, [heroID])
#    return
## Def_PDict_HeroSkinInfo 星级*10+是否已激活
def GetHeroSkinState(curPlayer, skinID):
    ## 武将时装激活状态
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkinInfo % skinID) % 10
def SetHeroSkinState(curPlayer, skinID, state):
    info = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkinInfo % skinID)
    info = info / 10 * 10 + min(1, state)
    return PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroSkinInfo % skinID, info)
def GetHeroSkinStar(curPlayer, skinID):
    ## 武将时装星级
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkinInfo % skinID) / 10
def SetHeroSkinStar(curPlayer, skinID, star):
    info = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkinInfo % skinID)
    info = star * 10 + info % 10
    return PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HeroSkinInfo % skinID, info)
def GetHeroItem(curPlayer, itemIndex):
    curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero)
@@ -1020,19 +986,38 @@
    PlayerOnline.GetOnlinePlayer(curPlayer).OnHeroItemUpate(heroItem) # 替换洗炼天赋
    return
#// B2 36 武将换肤 #tagCSHeroWearSkin
#// B2 36 武将皮肤操作 #tagCSHeroSkinOP
#
#struct    tagCSHeroWearSkin
#struct    tagCSHeroSkinOP
#{
#    tagHead        Head;
#    WORD        ItemIndex;    //武将物品所在武将背包位置索引
#    BYTE        SkinIndex;    //皮肤索引
#    DWORD        HeroID;        //武将ID
#    DWORD        SkinID;        //ʱװID
#    BYTE        OPType;        //操作 1-激活;2-佩戴;3-升星
#    WORD        ItemIndex;    //武将物品所在武将背包位置索引,仅佩戴时有效
#};
def OnHeroWearSkin(index, clientData, tick):
def OnHeroSkinOP(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    heroID = clientData.HeroID
    skinID = clientData.SkinID
    opType = clientData.OPType
    itemIndex = clientData.ItemIndex
    skinIndex = clientData.SkinIndex
    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
    if not heroIpyData:
        return
    skinIDList = heroIpyData.GetSkinIDList()
    if skinID not in skinIDList:
        GameWorld.DebugLog("不存在该皮肤! heroID=%s,skinID=%s not in %s" % (heroID, skinID, skinIDList))
        return
    skinIndex = skinIDList.index(skinID)
    if opType == 1:
        ActiveHeroSkin(curPlayer, heroID, skinID)
    elif opType == 2:
    DoHeroWearSkin(curPlayer, itemIndex, skinIndex)
    elif opType == 3:
        DoHeroSkinStarUP(curPlayer, heroID, skinID)
    return
def DoHeroWearSkin(curPlayer, itemIndex, skinIndex):
@@ -1048,29 +1033,81 @@
        if skinIndex >= len(skinIDList):
            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))
        skinID = skinIDList[skinIndex]
        if not GetHeroSkinState(curPlayer, skinID):
            GameWorld.DebugLog("该武将皮肤未解锁! heroID=%s,skinIndex=%s" % (heroID, skinIndex))
            return
    heroItem.SetUserAttr(ShareDefine.Def_IudetHeroSkin, skinIndex)
    
    PlayerOnline.GetOnlinePlayer(curPlayer).OnHeroItemUpate(heroItem) # 切换皮肤
    return True
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])
def GMSetHeroSkin(curPlayer, heroID, skinIndex, isActive=1):
    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
    if not heroIpyData:
        return
    skinIDList = heroIpyData.GetSkinIDList()
    if not skinIDList or len(skinIDList) >= skinIndex:
        return
    skinID = skinIDList[skinIndex]
    __onHeroSkinActive(curPlayer, heroID, skinID, isActive)
    return
    
    #RefreshLordAttr(curPlayer)
def ActiveHeroSkin(curPlayer, heroID, skinID):
    skinIpyData = IpyGameDataPY.GetIpyGameData("HeroSkinAttr", skinID)
    if not skinIpyData:
        return
    if GetHeroSkinState(curPlayer, skinID):
        GameWorld.DebugLog("该武将皮肤已经激活了: heroID=%s,skinID=%s" % (heroID, skinID))
        return
    needItemID = skinIpyData.GetNeedItemID()
    needItemCnt = 1
    costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, needItemID, needItemCnt)
    lackCnt = needItemCnt - bindCnt - unBindCnt
    if lackCnt > 0:
        GameWorld.DebugLog("激活武将时装物品不足! heroID=%s,needItemID=%s,needItemCnt=%s,lackCnt=%s" % (heroID, needItemID, needItemCnt, lackCnt))
        return
    ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, needItemCnt, "HeroSkin")
    GameWorld.DebugLog("激活武将皮肤: heroID=%s,skinID=%s" % (heroID, skinID), curPlayer.GetPlayerID())
    __onHeroSkinActive(curPlayer, heroID, skinID, 1)
    return
def __onHeroSkinActive(curPlayer, heroID, skinID, isActive):
    SetHeroSkinState(curPlayer, skinID, isActive)
    Sync_HeroInfo(curPlayer, [heroID])
    RefreshLordAttr(curPlayer) # 时装激活 - 全体属性
    return
def DoHeroSkinStarUP(curPlayer, heroID, skinID):
    playerID = curPlayer.GetPlayerID()
    if not GetHeroSkinState(curPlayer, skinID):
        GameWorld.DebugLog("该武将时装未激活! heroID=%s,skinID=%s" % (heroID, skinID), playerID)
        return
    skinIpyData = IpyGameDataPY.GetIpyGameData("HeroSkinAttr", skinID)
    if not skinIpyData:
        return
    starMax = skinIpyData.GetStarMax()
    curStar = GetHeroSkinStar(curPlayer, skinID)
    if curStar >= starMax:
        GameWorld.DebugLog("武将时装星级已满! heroID=%s,skinID=%s,curStar=%s >= %s" % (heroID, skinID, curStar, starMax), playerID)
        return
    needItemID = skinIpyData.GetNeedItemID()
    needItemCnt = 1
    if not needItemID or not needItemCnt:
        return
    costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, needItemID, needItemCnt)
    lackCnt = needItemCnt - bindCnt - unBindCnt
    if lackCnt > 0:
        GameWorld.DebugLog("武将时装升星物品不足! heroID=%s,skinID=%s,needItemID=%s,needItemCnt=%s,lackCnt=%s" % (heroID, skinID, needItemID, needItemCnt, lackCnt))
        return
    ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, needItemCnt, "Hero")
    nextStar = curStar + 1
    GameWorld.DebugLog("武将时装升星! heroID=%s,skinID=%s,nextStar=%s" % (heroID, skinID, nextStar), playerID)
    SetHeroSkinStar(curPlayer, skinID, nextStar)
    Sync_HeroInfo(curPlayer, [heroID])
    RefreshLordAttr(curPlayer) # 时装升星 - 全体属性
    return
#// B2 37 武将图鉴激活升级 #tagCSHeroBookUP
@@ -1136,48 +1173,10 @@
                    
    Sync_HeroInfo(curPlayer, [heroID])
    
    #RefreshLordAttr(curPlayer) 图鉴属性去除了
    bookCnt = GetHeroBookActCnt(curPlayer)
    PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_HeroBook)
    PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_OSAHeroBook, bookCnt)
    return
#def __doHeroBookStarLVUP(curPlayer, heroID):
#    ## 图鉴星级升级,废弃
#    playerID = curPlayer.GetPlayerID()
#    if not GetHeroBookInitState(curPlayer, heroID):
#        GameWorld.DebugLog("该武将图鉴未激活! heroID=%s" % heroID, playerID)
#        return
#    bookStar = GetHeroBookStarLV(curPlayer, heroID)
#    bookStarH = GetHeroBookStarLVH(curPlayer, heroID)
#    if bookStar >= bookStarH:
#        GameWorld.DebugLog("该武将图鉴星级已达当前英雄最高星级! heroID=%s,bookStar=%s >= %s" % (heroID, bookStar, bookStarH), playerID)
#        return
#    GameWorld.DebugLog("武将图鉴星级升级! heroID=%s,bookStar=%s,bookStarH=%s" % (heroID, bookStar, bookStarH), playerID)
#    SetHeroBookStarLV(curPlayer, heroID, bookStar + 1)
#    Sync_HeroInfo(curPlayer, [heroID])
#
#    RefreshLordAttr(curPlayer)
#    return
#def __doHeroBookBreakLVUP(curPlayer, heroID):
#    ## 图鉴突破升级,废弃
#    playerID = curPlayer.GetPlayerID()
#    if not GetHeroBookInitState(curPlayer, heroID):
#        GameWorld.DebugLog("该武将图鉴未激活! heroID=%s" % heroID, playerID)
#        return
#    bookBreakLV = GetHeroBookBreakLV(curPlayer, heroID)
#    bookBreakLVH = GetHeroBookBreakLVH(curPlayer, heroID)
#    if bookBreakLV >= bookBreakLVH:
#        GameWorld.DebugLog("该武将图鉴突破等级已达当前英雄最高突破等级! heroID=%s,bookBreakLV=%s >= %s" % (heroID, bookBreakLV, bookBreakLVH), playerID)
#        return
#    GameWorld.DebugLog("武将图鉴突破升级! heroID=%s,bookBreakLV=%s,bookBreakLVH=%s" % (heroID, bookBreakLV, bookBreakLVH), playerID)
#    SetHeroBookBreakLV(curPlayer, heroID, bookBreakLV + 1)
#    Sync_HeroInfo(curPlayer, [heroID])
#
#    RefreshLordAttr(curPlayer)
#    return
#// B2 38 武将锁定 #tagCSHeroLock
#
@@ -1726,10 +1725,33 @@
def CalcHeroAddAttr(curPlayer):
    ## 计算武将对主公增加的属性
    
    skinAttrDict = {}
    fatesAttrDict = {}
    playerID = curPlayer.GetID()
    
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    # 武将时装
    for index in range(ipyDataMgr.GetHeroSkinAttrCount()):
        ipyData = ipyDataMgr.GetHeroSkinAttrByIndex(index)
        skinID = ipyData.GetSkinID()
        if not GetHeroSkinState(curPlayer, skinID):
            continue
        skinStar = GetHeroSkinStar(curPlayer, skinID)
        attrIDList = ipyData.GetRoleAttrIDList()
        attrValueList = ipyData.GetRoleAttrValueList()
        perStarAddList = ipyData.GetRoleAttrPerStarAddList()
        for i in range(min(len(attrIDList), len(attrValueList))):
            attrID = attrIDList[i]
            attrValuePerStar = perStarAddList[i] if len(perStarAddList) > i else 0
            attrValue = attrValueList[i] + attrValuePerStar * skinStar
            skinAttrDict[attrID] = skinAttrDict.get(attrID, 0) + attrValue
    GameWorld.DebugLog("时装属性: %s" % skinAttrDict, playerID)
    PlayerOnline.GetOnlinePlayer(curPlayer).SetCalcAttr(ChConfig.Def_CalcAttr_HeroSkin, skinAttrDict)
    # 宿缘
    for index in range(ipyDataMgr.GetHeroFatesCount()):
        ipyData = ipyDataMgr.GetHeroFatesByIndex(index)
        fatesID = ipyData.GetFatesID()
@@ -1770,18 +1792,21 @@
        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
        if not heroIpyData:
            continue
        if heroIDList == None and not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID) \
            and not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBookH % heroID):
        if heroIDList == None and not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID):
            continue
        skinIDList = heroIpyData.GetSkinIDList()
        
        hero = ChPyNetSendPack.tagSCHero()
        hero.HeroID = heroID
        hero.SkinState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkin % heroID)
        hero.BookInitState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroBook % heroID) % 10
        #hero.BookStarLV = GetHeroBookStarLV(curPlayer, heroID)
        #hero.BookBreakLV = GetHeroBookBreakLV(curPlayer, heroID)
        #hero.BookStarLVH = GetHeroBookStarLVH(curPlayer, heroID)
        #hero.BookBreakLVH = GetHeroBookBreakLVH(curPlayer, heroID)
        hero.SkinList = []
        for skinID in skinIDList[1:]: # 第1个默认激活的不同步
            skin = ChPyNetSendPack.tagSCHeroSkin()
            skin.SkinID = skinID
            skin.State = GetHeroSkinState(curPlayer, skinID)
            skin.Star = GetHeroSkinStar(curPlayer, skinID)
            hero.SkinList.append(skin)
        hero.SkinCnt = len(hero.SkinList)
        syncInfoList.append(hero)
        
    if not syncInfoList:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
@@ -750,6 +750,7 @@
    countryHeroInfo = {} # 国家武将统计 {country:[heroID, ...], ...}
    fetterHeroInfo = {} # 阵容羁绊武将统计信息 {fetterID:[heroID, ...], ...}
    heroSelfAttrInfo = {} # 武将自身属性 {heroID:{attrID:value, ...}, ...}
    heroSkinAttrInfo = {} # 武将时装属性 {heroID:{attrID:value, ...}, ...}
    heroLVAttrInfo = {} # 武将等级属性 {heroID:{attrID:value, ...}, ...}
    heroStarTalentInfo = {} # 武将星级天赋属性 {heroID:{attrID:value, ...}, ...}
    heroBreakAttrInfo = {} # 武将突破潜能属性 {heroID:{attrID:value, ...}, ...}
@@ -808,6 +809,21 @@
        for k, v in heroIpyData.GetBatAttrDict().items():
            selfAttrDict[int(k)] = v
        heroSelfAttrInfo[heroID] = selfAttrDict
        # 时装属性
        heroSkinAttrDict = {}
        skinIpyData = IpyGameDataPY.GetIpyGameDataNotLog("HeroSkinAttr", skinID)
        if skinIpyData:
            skinStar = PlayerHero.GetHeroSkinStar(curPlayer, skinID)
            wearAttrIDList = skinIpyData.GetWearAttrIDList()
            wearAttrValueList = skinIpyData.GetWearAttrValueList()
            wearAttrPerStarAddList = skinIpyData.GetWearAttrPerStarAddList()
            for i in range(min(len(wearAttrIDList), len(wearAttrValueList))):
                attrID = wearAttrIDList[i]
                attrValuePerStar = wearAttrPerStarAddList[i] if len(wearAttrPerStarAddList) > i else 0
                attrValue = wearAttrValueList[i] + attrValuePerStar * skinStar
                heroSkinAttrDict[attrID] = heroSkinAttrDict.get(attrID, 0) + attrValue
        heroSkinAttrInfo[heroID] = heroSkinAttrDict
        
        # 等级属性
        heroLVAttrDict = {}
@@ -950,6 +966,7 @@
    lvAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_LV)
    equipAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_MainEquip)
    fatesAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_HeroFates)
    skinAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_HeroSkin)
    realmAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Realm)
    gubaoAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Gubao)
    hjgAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_HJG)
@@ -962,6 +979,7 @@
    GameWorld.DebugLog("    国家武将统计=%s" % countryHeroInfo, playerID)
    GameWorld.DebugLog("    羁绊武将统计=%s" % fetterHeroInfo, playerID)
    GameWorld.DebugLog("    武将自身属性=%s" % heroSelfAttrInfo, playerID)
    GameWorld.DebugLog("    穿戴时装属性=%s" % heroSkinAttrInfo, playerID)
    GameWorld.DebugLog("    武将等级属性=%s" % heroLVAttrInfo, playerID)
    GameWorld.DebugLog("    武将吞噬属性=%s" % heroStarTalentInfo, playerID)
    GameWorld.DebugLog("    武将突破潜能=%s" % heroBreakAttrInfo, playerID)
@@ -972,6 +990,7 @@
    GameWorld.DebugLog("    主公等级属性=%s" % lvAttrDict, playerID)
    GameWorld.DebugLog("    主公装备属性=%s" % equipAttrDict, playerID)
    GameWorld.DebugLog("    主公宿缘属性=%s" % fatesAttrDict, playerID)
    GameWorld.DebugLog("    主公全体时装=%s" % skinAttrDict, playerID)
    GameWorld.DebugLog("    主公官职属性=%s" % realmAttrDict, playerID)
    GameWorld.DebugLog("    主公古宝属性=%s" % gubaoAttrDict, playerID)
    GameWorld.DebugLog("    主幻境阁属性=%s" % hjgAttrDict, playerID)
@@ -1011,6 +1030,7 @@
        lineupHero.heroBatAttrDict = {}
        lineupHero.fightPower = 0
        
        heroSkinAttrDict = heroSkinAttrInfo.get(heroID, {})
        heroLVAttrDict = heroLVAttrInfo.get(heroID, {})
        starTalentAttrDict = heroStarTalentInfo.get(heroID, {})
        breakAttrDict = heroBreakAttrInfo.get(heroID, {})
@@ -1031,6 +1051,9 @@
                
            fatesValue = fatesAttrDict.get(attrID, 0)
            fatesPer = fatesAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
            skinValue = skinAttrDict.get(attrID, 0)
            skinPer = skinAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
            
            realmValue = realmAttrDict.get(attrID, 0)
            realmPer = realmAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
@@ -1062,6 +1085,7 @@
                
            lineupHaloValue, lineupHaloPer = lineupHaloAttrInfo.get(attrID, 0), 0
            fetterValue, fetterPer = fetterAttrDict.get(attrID, 0), 0
            heroSkinValue, heroSkinPer = heroSkinAttrDict.get(attrID, 0), 0
            heroLVValue, heroLVPer = heroLVAttrDict.get(attrID, 0), 0
            starTalentValue, starTalentPer = starTalentAttrDict.get(attrID, 0), 0
            breakLVValue, breakLVPer = breakAttrDict.get(attrID, 0), 0
@@ -1070,6 +1094,7 @@
                heroSelfPer = selfAttrDict.get(attrPerID, 0) / 10000.0
                lineupHaloPer = lineupHaloAttrInfo.get(attrPerID, 0) / 10000.0
                fetterPer = fetterAttrDict.get(attrPerID, 0) / 10000.0
                heroSkinPer = heroSkinAttrDict.get(attrPerID, 0) / 10000.0
                heroLVPer = heroLVAttrDict.get(attrPerID, 0) / 10000.0
                starTalentPer = starTalentAttrDict.get(attrPerID, 0) / 10000.0
                breakLVPer = breakAttrDict.get(attrPerID, 0) / 10000.0
@@ -1078,9 +1103,10 @@
            # 计算
            attrParamDict = {"lvValue":lvValue, "equipValue":equipValue, "realmValue":realmValue, "realmPer":realmPer, "cardPer":cardPer,
                             "gubaoValue":gubaoValue, "gubaoPer":gubaoPer, "hjgValue":hjgValue, "hjgPer":hjgPer, "horseValue":horseValue, "horsePer":horsePer,
                             "beautyValue":beautyValue, "beautyPer":beautyPer, "fatesValue":fatesValue, "fatesPer":fatesPer,
                             "beautyValue":beautyValue, "beautyPer":beautyPer, "fatesValue":fatesValue, "fatesPer":fatesPer, "skinValue":skinValue, "skinPer":skinPer,
                             "dingjungeValue":dingjungeValue, "dingjungePer":dingjungePer, "minggeValue":minggeValue, "minggePer":minggePer,
                             "heroSelfValue":heroSelfValue, "heroSelfPer":heroSelfPer, "inheritPer":inheritPer, "heroLVValue":heroLVValue, "heroLVPer":heroLVPer,
                             "heroSkinValue":heroSkinValue, "heroSkinPer":heroSkinPer,
                             "lineupHaloValue":lineupHaloValue, "lineupHaloPer":lineupHaloPer, "fetterValue":fetterValue, "fetterPer":fetterPer,
                             "starTalentValue":starTalentValue, "starTalentPer":starTalentPer, "breakLVValue":breakLVValue, "breakLVPer":breakLVPer,
                             "awakeTalentValue":awakeTalentValue, "awakeTalentPer":awakeTalentPer,