hxp
2025-11-21 caba629e01f8f603b8e05f588688c40e82eb6c88
358 【内政】红颜系统-服务端
20个文件已修改
3个文件已添加
1625 ■■■■ 已修改文件
PySysDB/PySysDBPY.h 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 317 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Beauty.py 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/FBPass.py 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Arena.py 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 146 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBeauty.py 626 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerChatBox.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerGoldRush.py 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHJG.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -955,6 +955,52 @@
    list        LVUPNeedItemInfo;    //升级所需物品 [[物品ID,个数], ...]
};
//红颜表
struct Beauty
{
    WORD        _BeautyID;    //红颜ID
    BYTE        BeautyQuality;    //品质
    BYTE        UnlockWay;    //解锁方式
    DWORD        UnlockValue;    //解锁方式值
    BYTE        UnlockNeedCnt;    //解锁所需个数
    list        TalentAttrIDList;    //天赋属性ID列表
    list        TalentAttrValueList;    //天赋属性初始值
    list        TalentPerLVAddList;    //天赋属性每级成长
    BYTE        EffType;    //天赋效果类型
    BYTE        EffTypeValue;    //效果类型值
    BYTE        EffValue;    //效果初始值
    DWORD        EffPerLVAdd;    //天赋效果每级成长
};
//红颜品质升级表
struct BeautyQualityLV
{
    BYTE        _BeautyQuality;
    WORD        _BeautyLV;
    WORD        LVNeedExp;    //升到本级所需经验
    list        AttrIDList;    //本级属性ID列表
    list        AttrValueList;    //本级属性值列表
    list        AwardItemList;    //本级奖励
};
//红颜时装表
struct    BeautySkin
{
    WORD        SkinID;    //ʱװID
    WORD        _BeautyID;
    BYTE        UnlockWay;    //解锁方式
    DWORD        UnlockValue;    //解锁方式值
    BYTE        UnlockNeedCnt;    //解锁所需个数
    BYTE        UpNeedCnt;    //升级所需个数
    BYTE        StarMax;    //最高星级
    list        AttrIDList;    //属性ID列表
    list        InitAttrValueList;    //初始属性值列表
    list        AttrPerStarAddList;    //每星加成值列表
};
//玩家等级表
struct PlayerLV
@@ -1460,19 +1506,6 @@
    dict        Reward;    //奖励 {"职业":[[物品ID,个数],...], ...}
    BYTE        VIPLimit;    //需要VIP几
    list        VIPAward;    //vip奖励[[物品ID,个数],...]
};
//仙宝寻主表
struct tagXBXZ
{
    DWORD        _ID;    //ID
    BYTE        Type;    //类型
    DWORD        NeedCnt;    //需要数量
    list        Condition;    //条件
    WORD        MWID;    //法宝ID
    list        AwardItem;    //奖励物品列表
    list        Money;    //金钱
};
//寻宝设定表
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1132,6 +1132,26 @@
PacketSubCMD_3=0x18
PacketCallFunc_3=OnGubaoLVUp
;红颜
[PlayerBeauty]
ScriptName = Player\PlayerBeauty.py
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 3
PacketCMD_1=0xB2
PacketSubCMD_1=0x19
PacketCallFunc_1=OnBeautyActivate
PacketCMD_2=0xB2
PacketSubCMD_2=0x20
PacketCallFunc_2=OnBeautyLVUP
PacketCMD_3=0xB2
PacketSubCMD_3=0x21
PacketCallFunc_3=OnBeautySkinOP
;主线战斗
[GameLogic_MainLevel]
ScriptName = GameWorldLogic\FBProcess\GameLogic_MainLevel.py
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -219,7 +219,8 @@
Def_CalcAttr_Gubao, # 古宝 4
Def_CalcAttr_HJG, # 幻境阁 5
Def_CalcAttr_Horse, # 坐骑 6
) = range(7)
Def_CalcAttr_Beauty, # 红颜 7
) = range(8)
CalcAttrName = {
                Def_CalcAttr_LV:"主公等级",
@@ -229,6 +230,7 @@
                Def_CalcAttr_Gubao:"古宝",
                Def_CalcAttr_HJG:"幻境阁",
                Def_CalcAttr_Horse:"坐骑",
                Def_CalcAttr_Beauty:"红颜",
                }
##-----------------------------------------------------------------------------------------------
@@ -3511,6 +3513,11 @@
Def_PDict_EmojiPackState = "EmojiPackState_%s"  # 表情包状态,参数(key编号)
Def_PDict_EmojiPackEndTime = "EmojiPackEndTime_%s"  # 到期时间戳,0为永久,参数(表情包ID)
#红颜
Def_PDict_BeautyLVInfo = "BeautyLVInfo_%s"  # 红颜等级信息,参数(红颜ID) 经验*10000+等级*10+是否已激活
Def_PDict_BeautyAwardLV = "BeautyAwardLV_%s"  # 红颜已领取到的奖励等级,参数(红颜ID)
Def_PDict_BeautySkinInfo = "BeautySkinInfo_%s"  # 红颜时装信息,参数(时装ID) 星级*100+是否使用+是否已激活
#周狂欢
Def_PDict_WeekPartyActID = "WeekPartyActID"  # 玩家身上的活动ID,唯一标识,取活动开始日期time值
Def_PDict_WeekPartyID = "WeekPartyID"  # 玩家身上的活动ID,配置ID,用于补发上次活动用
@@ -3763,6 +3770,7 @@
#竞技场
Def_PDict_ArenaScore = "ArenaScore" # 当前积分
Def_PDict_ArenaWinCnt = "ArenaWinCnt" # 累计胜利次数
#功能系统特权
Def_PDict_FuncSysPrivilegeActTime = "FuncSysPrivilegeActTime_%s" # 系统功能特权激活时间戳,参数(系统功能ID)
@@ -4767,7 +4775,7 @@
Def_RewardType_FamilyTaofaBox,  # 公会讨伐领取宝箱奖励 3
Def_RewardType_LineupRecommend,  # 阵容推荐奖励 4
Def_RewardType_LVAward,  # 玩家等级奖励5
Def_RewardType_XBXZ, # 仙宝寻主奖励6
Def_RewardType_BeautyLVAward, # 红颜等级奖励 6
Def_RewardType_DayRealmPoint, # 每日任务修行点奖励7
Def_RewardType_FirstCharge, # 首充礼包奖励8
Def_RewardType_MWSoulAward, # 法宝之魂奖励9 -废弃
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -11575,6 +11575,178 @@
#------------------------------------------------------
# B2 19 红颜激活 #tagCSBeautyActivate
class  tagCSBeautyActivate(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("BeautyID", c_ushort),    #红颜ID
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB2
        self.SubCmd = 0x19
        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 = 0x19
        self.BeautyID = 0
        return
    def GetLength(self):
        return sizeof(tagCSBeautyActivate)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 19 红颜激活 //tagCSBeautyActivate:
                                Cmd:%s,
                                SubCmd:%s,
                                BeautyID:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.BeautyID
                                )
        return DumpString
m_NAtagCSBeautyActivate=tagCSBeautyActivate()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSBeautyActivate.Cmd,m_NAtagCSBeautyActivate.SubCmd))] = m_NAtagCSBeautyActivate
#------------------------------------------------------
# B2 20 红颜好感度升级 #tagCSBeautyLVUP
class  tagCSBeautyLVUP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("BeautyID", c_ushort),    #红颜ID
                  ("ItemID", c_int),    #使用物品ID
                  ("IsQuick", c_ubyte),    # 是否快速升级,0-只消耗1个道具;1-消耗升1级的道具
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB2
        self.SubCmd = 0x20
        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 = 0x20
        self.BeautyID = 0
        self.ItemID = 0
        self.IsQuick = 0
        return
    def GetLength(self):
        return sizeof(tagCSBeautyLVUP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 20 红颜好感度升级 //tagCSBeautyLVUP:
                                Cmd:%s,
                                SubCmd:%s,
                                BeautyID:%d,
                                ItemID:%d,
                                IsQuick:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.BeautyID,
                                self.ItemID,
                                self.IsQuick
                                )
        return DumpString
m_NAtagCSBeautyLVUP=tagCSBeautyLVUP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSBeautyLVUP.Cmd,m_NAtagCSBeautyLVUP.SubCmd))] = m_NAtagCSBeautyLVUP
#------------------------------------------------------
# B2 21 红颜时装操作 #tagCSBeautySkinOP
class  tagCSBeautySkinOP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("BeautyID", c_ushort),    #红颜ID
                  ("SkinID", c_ushort),    #ʱװID
                  ("OPType", c_ubyte),    #操作 1-激活;2-佩戴;3-升星
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB2
        self.SubCmd = 0x21
        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 = 0x21
        self.BeautyID = 0
        self.SkinID = 0
        self.OPType = 0
        return
    def GetLength(self):
        return sizeof(tagCSBeautySkinOP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B2 21 红颜时装操作 //tagCSBeautySkinOP:
                                Cmd:%s,
                                SubCmd:%s,
                                BeautyID:%d,
                                SkinID:%d,
                                OPType:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.BeautyID,
                                self.SkinID,
                                self.OPType
                                )
        return DumpString
m_NAtagCSBeautySkinOP=tagCSBeautySkinOP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSBeautySkinOP.Cmd,m_NAtagCSBeautySkinOP.SubCmd))] = m_NAtagCSBeautySkinOP
#------------------------------------------------------
# B2 12 领取功能系统特权奖励 #tagCMGetFuncSysPrivilegeAward
class  tagCMGetFuncSysPrivilegeAward(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -8964,114 +8964,6 @@
#------------------------------------------------------
# A3 48 仙宝寻主领奖记录 #tagMCXBXZAwardRecordList
class  tagMCXBXZAwardRecord(Structure):
    _pack_ = 1
    _fields_ = [
                  ("RecordIndex", c_ushort),    #第几个记录值 每个key存31个id   0-30为0, 31-61为1..
                  ("Record", c_int),    #对应是否领取值
                  ]
    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.RecordIndex = 0
        self.Record = 0
        return
    def GetLength(self):
        return sizeof(tagMCXBXZAwardRecord)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A3 48 仙宝寻主领奖记录 //tagMCXBXZAwardRecordList:
                                RecordIndex:%d,
                                Record:%d
                                '''\
                                %(
                                self.RecordIndex,
                                self.Record
                                )
        return DumpString
class  tagMCXBXZAwardRecordList(Structure):
    Head = tagHead()
    RecordCnt = 0    #(WORD RecordCnt)//记录个数
    RecordList = list()    #(vector<tagMCXBXZAwardRecord> RecordList)//记录列表
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x48
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.RecordCnt,_pos = CommFunc.ReadWORD(_lpData, _pos)
        for i in range(self.RecordCnt):
            temRecordList = tagMCXBXZAwardRecord()
            _pos = temRecordList.ReadData(_lpData, _pos)
            self.RecordList.append(temRecordList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xA3
        self.Head.SubCmd = 0x48
        self.RecordCnt = 0
        self.RecordList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 2
        for i in range(self.RecordCnt):
            length += self.RecordList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteWORD(data, self.RecordCnt)
        for i in range(self.RecordCnt):
            data = CommFunc.WriteString(data, self.RecordList[i].GetLength(), self.RecordList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                RecordCnt:%d,
                                RecordList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.RecordCnt,
                                "..."
                                )
        return DumpString
m_NAtagMCXBXZAwardRecordList=tagMCXBXZAwardRecordList()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCXBXZAwardRecordList.Head.Cmd,m_NAtagMCXBXZAwardRecordList.Head.SubCmd))] = m_NAtagMCXBXZAwardRecordList
#------------------------------------------------------
# A4 11 传功邀请信息 #tagGCChuangongInviteInfo
class  tagGCChuangongInviteInfo(Structure):
@@ -15003,6 +14895,7 @@
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("Score", c_int),    #当前积分
                  ("WinCnt", c_int),    #累计胜利次数
                  ]
    def __init__(self):
@@ -15020,6 +14913,7 @@
        self.Cmd = 0xA9
        self.SubCmd = 0x23
        self.Score = 0
        self.WinCnt = 0
        return
    def GetLength(self):
@@ -15032,12 +14926,14 @@
        DumpString = '''// A9 23 演武场玩家信息 //tagSCArenaPlayerInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                Score:%d
                                Score:%d,
                                WinCnt:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.Score
                                self.Score,
                                self.WinCnt
                                )
        return DumpString
@@ -32317,6 +32213,207 @@
#------------------------------------------------------
# B1 30 红颜信息 #tagSCBeautyInfo
class  tagSCBeautySkin(Structure):
    _pack_ = 1
    _fields_ = [
                  ("SkinID", c_ushort),    #ʱװID
                  ("State", c_ubyte),    #是否已激活
                  ("Used", c_ubyte),    #是否已穿戴该时装,某个红颜的所有时装穿戴可能都为0,则前端取默认时装进行展示,如果有同步已穿戴的则以后端为准
                  ("Star", c_ubyte),    #时装星级,激活时为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.SkinID = 0
        self.State = 0
        self.Used = 0
        self.Star = 0
        return
    def GetLength(self):
        return sizeof(tagSCBeautySkin)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B1 30 红颜信息 //tagSCBeautyInfo:
                                SkinID:%d,
                                State:%d,
                                Used:%d,
                                Star:%d
                                '''\
                                %(
                                self.SkinID,
                                self.State,
                                self.Used,
                                self.Star
                                )
        return DumpString
class  tagSCBeauty(Structure):
    BeautyID = 0    #(WORD BeautyID)//红颜ID
    State = 0    #(BYTE State)//是否已激活
    LV = 0    #(WORD LV)//红颜好感等级,激活时为0级
    Exp = 0    #(WORD Exp)//当前等级经验
    AwardLV = 0    #(WORD AwardLV)//已经领取到的奖励等级记录
    SkinCnt = 0    #(BYTE SkinCnt)
    SkinList = list()    #(vector<tagSCBeautySkin> SkinList)//时装皮肤列表,默认解锁的不通知,有变化的才会同步
    data = None
    def __init__(self):
        self.Clear()
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        self.BeautyID,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.State,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.Exp,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.AwardLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
        self.SkinCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.SkinCnt):
            temSkinList = tagSCBeautySkin()
            _pos = temSkinList.ReadData(_lpData, _pos)
            self.SkinList.append(temSkinList)
        return _pos
    def Clear(self):
        self.BeautyID = 0
        self.State = 0
        self.LV = 0
        self.Exp = 0
        self.AwardLV = 0
        self.SkinCnt = 0
        self.SkinList = list()
        return
    def GetLength(self):
        length = 0
        length += 2
        length += 1
        length += 2
        length += 2
        length += 2
        length += 1
        for i in range(self.SkinCnt):
            length += self.SkinList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteWORD(data, self.BeautyID)
        data = CommFunc.WriteBYTE(data, self.State)
        data = CommFunc.WriteWORD(data, self.LV)
        data = CommFunc.WriteWORD(data, self.Exp)
        data = CommFunc.WriteWORD(data, self.AwardLV)
        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 = '''
                                BeautyID:%d,
                                State:%d,
                                LV:%d,
                                Exp:%d,
                                AwardLV:%d,
                                SkinCnt:%d,
                                SkinList:%s
                                '''\
                                %(
                                self.BeautyID,
                                self.State,
                                self.LV,
                                self.Exp,
                                self.AwardLV,
                                self.SkinCnt,
                                "..."
                                )
        return DumpString
class  tagSCBeautyInfo(Structure):
    Head = tagHead()
    Count = 0    #(BYTE Count)
    BeautyList = list()    #(vector<tagSCBeauty> BeautyList)
    data = None
    def __init__(self):
        self.Clear()
        self.Head.Cmd = 0xB1
        self.Head.SubCmd = 0x30
        return
    def ReadData(self, _lpData, _pos=0, _Len=0):
        self.Clear()
        _pos = self.Head.ReadData(_lpData, _pos)
        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
        for i in range(self.Count):
            temBeautyList = tagSCBeauty()
            _pos = temBeautyList.ReadData(_lpData, _pos)
            self.BeautyList.append(temBeautyList)
        return _pos
    def Clear(self):
        self.Head = tagHead()
        self.Head.Clear()
        self.Head.Cmd = 0xB1
        self.Head.SubCmd = 0x30
        self.Count = 0
        self.BeautyList = list()
        return
    def GetLength(self):
        length = 0
        length += self.Head.GetLength()
        length += 1
        for i in range(self.Count):
            length += self.BeautyList[i].GetLength()
        return length
    def GetBuffer(self):
        data = ''
        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
        data = CommFunc.WriteBYTE(data, self.Count)
        for i in range(self.Count):
            data = CommFunc.WriteString(data, self.BeautyList[i].GetLength(), self.BeautyList[i].GetBuffer())
        return data
    def OutputString(self):
        DumpString = '''
                                Head:%s,
                                Count:%d,
                                BeautyList:%s
                                '''\
                                %(
                                self.Head.OutputString(),
                                self.Count,
                                "..."
                                )
        return DumpString
m_NAtagSCBeautyInfo=tagSCBeautyInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCBeautyInfo.Head.Cmd,m_NAtagSCBeautyInfo.Head.SubCmd))] = m_NAtagSCBeautyInfo
#------------------------------------------------------
# B1 27 聊天气泡框信息 #tagSCChatBoxInfo
class  tagSCChatBox(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Arena.py
@@ -32,6 +32,7 @@
        GameWorld.DebugAnswer(curPlayer, "重置玩家竞技场: Arena 0")
        GameWorld.DebugAnswer(curPlayer, "设置玩家榜积分: Arena 积分")
        GameWorld.DebugAnswer(curPlayer, "直接匹配到目标: Arena m 对手ID 对手ID ...")
        GameWorld.DebugAnswer(curPlayer, "设置累计胜利数: Arena w 胜利数")
        GameWorld.DebugAnswer(curPlayer, "重置赛季直接用 test_OnWeek")
        return
    
@@ -54,5 +55,11 @@
        gmMatchIDList = msgList[1:]
        PlayerArena.GMArenaMatch(curPlayer, gmMatchIDList)
        
    elif value1 == "w":
        winCnt = msgList[1] if len(msgList) > 1 else 0
        GameWorld.DebugAnswer(curPlayer, "设置竞技场胜利数: %s" % winCnt)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaWinCnt, winCnt)
        PlayerArena.Sync_ArenaInfo(curPlayer)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Beauty.py
New file
@@ -0,0 +1,110 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.Beauty
#
# @todo:红颜
# @author hxp
# @date 2025-11-21
# @version 1.0
#
# 详细描述: 红颜
#
#-------------------------------------------------------------------------------
#"""Version = 2025-11-21 17:00"""
#-------------------------------------------------------------------------------
import GameWorld
import IpyGameDataPY
import PlayerControl
import PlayerBeauty
import ChConfig
def OnExec(curPlayer, msgList):
    if not msgList:
        GameWorld.DebugAnswer(curPlayer, "重置红颜: Beauty 0 [红颜ID]")
        GameWorld.DebugAnswer(curPlayer, "设置红颜: Beauty 红颜ID [等级 经验 领奖等级]")
        GameWorld.DebugAnswer(curPlayer, "红颜时装: Beauty s 时装ID [星级]")
        GameWorld.DebugAnswer(curPlayer, "演武场胜利数: Arena w 胜利数")
        GameWorld.DebugAnswer(curPlayer, "副本过关进度: FBPass")
        return
    beautyIDList, skinIDList = [], []
    value1 = msgList[0]
    if value1 == 0:
        setBeautyID = msgList[1] if len(msgList) > 1 else 0
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        for index in range(ipyDataMgr.GetBeautyCount()):
            ipyData = ipyDataMgr.GetBeautyByIndex(index)
            beautyID = ipyData.GetBeautyID()
            if setBeautyID and setBeautyID != beautyID:
                continue
            if not PlayerBeauty.GetBeautyState(curPlayer, beautyID):
                continue
            beautyIDList.append(beautyID)
            ipyDataList = IpyGameDataPY.GetIpyGameDataList("BeautySkin", beautyID)
            if ipyDataList:
                for skinIpyData in ipyDataList:
                    skinID = skinIpyData.GetSkinID()
                    if not PlayerBeauty.GetBeautySkinState(curPlayer, skinID):
                        continue
                    skinIDList.append(skinID)
                    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautySkinInfo % skinID, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautyLVInfo % beautyID, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautyAwardLV % beautyID, 0)
        GameWorld.DebugAnswer(curPlayer, "重置红颜OK")
    elif value1 == "s":
        skinID = msgList[1] if len(msgList) > 1 else 0
        star = msgList[2] if len(msgList) > 2 else 0
        ipyData = IpyGameDataPY.GetIpyGameDataByCondition("BeautySkin", {"SkinID":skinID}, False)
        if not ipyData:
            GameWorld.DebugAnswer(curPlayer, "不存在红颜时装skinID:%s" % skinID)
            return
        beautyID = ipyData.GetBeautyID()
        star = min(star, ipyData.GetStarMax())
        PlayerBeauty.DoBeautyActivate(curPlayer, beautyID)
        PlayerBeauty.SetBeautySkinState(curPlayer, skinID, 1)
        PlayerBeauty.SetBeautySkinStar(curPlayer, skinID, star)
        beautyIDList, skinIDList = [beautyID], [skinID]
        GameWorld.DebugAnswer(curPlayer, "红颜ID:%s,时装ID:%s,星:%s" % (beautyID, skinID, star))
    elif value1 > 0:
        beautyID = value1
        lv = msgList[1] if len(msgList) > 1 else None
        exp = msgList[2] if len(msgList) > 2 else 0
        awardLV = msgList[3] if len(msgList) > 3 else None
        ipyData = IpyGameDataPY.GetIpyGameData("Beauty", beautyID)
        if not ipyData:
            GameWorld.DebugAnswer(curPlayer, "不存在红颜! %s" % beautyID)
            return
        quality = ipyData.GetBeautyQuality()
        PlayerBeauty.DoBeautyActivate(curPlayer, beautyID)
        if lv == None:
            lv, exp, awardLV = 0, 0, 0
        if not IpyGameDataPY.GetIpyGameData("BeautyQualityLV", quality, lv):
            GameWorld.DebugAnswer(curPlayer, "不存在红颜等级! ID:%s,品质:%s,LV:%s" % (beautyID, quality, lv))
            return
        PlayerBeauty.SetBeautyLVInfo(curPlayer, beautyID, lv, exp)
        lv, exp = PlayerBeauty.GetBeautyLVInfo(curPlayer, beautyID)
        if awardLV != None:
            awardLV = min(lv, awardLV)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautyAwardLV % beautyID, awardLV)
        awardLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyAwardLV % beautyID)
        GameWorld.DebugAnswer(curPlayer, "红颜ID:%s, 品质:%s, LV:%s-%s, 奖励LV:%s" % (beautyID, quality, lv, exp, awardLV))
        beautyIDList = [beautyID]
    PlayerBeauty.RefreshBeautyAttr(curPlayer)
    PlayerBeauty.SyncBeautyInfo(curPlayer, beautyIDList, skinIDList)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/FBPass.py
New file
@@ -0,0 +1,40 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.FBPass
#
# @todo:设置副本过关进度
# @author hxp
# @date 2025-11-21
# @version 1.0
#
# 详细描述: 设置副本过关进度
#
#-------------------------------------------------------------------------------
#"""Version = 2025-11-21 17:00"""
#-------------------------------------------------------------------------------
import GameWorld
import IpyGameDataPY
import PlayerControl
import FBCommon
import ChConfig
def OnExec(curPlayer, paramList):
    if not paramList:
        GameWorld.DebugAnswer(curPlayer, "副本过关进度: FBPass mapID lineID")
        return
    mapID = paramList[0]
    funcLineID = paramList[1] if len(paramList) > 1 else 0
    if not IpyGameDataPY.GetIpyGameData("FBLine", mapID, funcLineID):
        GameWorld.DebugAnswer(curPlayer, "不存在该副本线路:%s-%s" % (mapID, funcLineID))
        return
    GameWorld.DebugAnswer(curPlayer, "副本过关进度:%s-%s" % (mapID, funcLineID))
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FBPassLineID % mapID, funcLineID)
    FBCommon.Sync_FBPlayerFBInfoData(curPlayer, mapID)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Arena.py
@@ -25,6 +25,7 @@
import PlayerBillboard
import PlayerZhanling
import ItemControler
import PlayerBeauty
import PlayerArena
import PlayerGubao
import PyGameData
@@ -125,7 +126,13 @@
        GameWorld.DebugLog("scoreIndex=%s,winScoreInfo=%s" % (scoreIndex, winScoreInfo), playerID)
        
    # 无论胜负,只要挑战都给固定奖励
    awardItemList = IpyGameDataPY.GetFuncEvalCfg("ArenaSet", 4)
    awardItemList = []
    awardItemList += IpyGameDataPY.GetFuncEvalCfg("ArenaSet", 4)
    exItemRate, exItemID = PlayerBeauty.GetBeautyEffInfo(curPlayer, PlayerBeauty.EffType_ArenaItemEx) # 概率额外获得1个物品
    if exItemRate and exItemID:
        if GameWorld.CanHappen(exItemRate):
            awardItemList.append([exItemID, 1])
            GameWorld.DebugLog("红颜概率额外获得1个物品: exItemRate=%s, exItemID=%s, awardItemList=%s" % (exItemRate, exItemID, awardItemList))
    overMsg.update({"tagPlayerID":tagPlayerID, "atkAddScore":atkAddScore, "defDecScore":defDecScore,
                    FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList)})
    
@@ -142,6 +149,11 @@
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
    GameWorld.DebugLog("score=%s,atkAddScore=%s,updScore=%s" % (score, atkAddScore, updScore), playerID)
    
    if isWin:
        winCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaWinCnt)
        updWinCnt = PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaWinCnt, winCnt + 1)
        GameWorld.DebugLog("updWinCnt=%s" % (updWinCnt), playerID)
    tagViewCache = turnFight.tagViewCache
    gameRecMgr = DBDataMgr.GetGameRecMgr()
    atkRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_ArenaRecord, playerID)
@@ -208,7 +220,7 @@
        return
    
    tagPlayerID, isWin, atkAddScore, defDecScore, awardItemList = awardData
    GameWorld.DebugLog("竞技场结算奖励: tagPlayerID=%s,isWin=%s,atkAddScore=%s,defDecScore=%s,awardItemList=%s" % (tagPlayerID, isWin, atkAddScore, defDecScore, awardItemList))
    if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_ArenaTicket, 1):
        return
    
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
@@ -26,6 +26,7 @@
import ItemControler
import IPY_GameWorld
import NetPackCommon
import PlayerBeauty
import PlayerArena
import PlayerLLMJ
import ItemCommon
@@ -121,12 +122,18 @@
    # 其他战利品掉落
    bootyDropNeedDict = IpyGameDataPY.GetFuncEvalCfg("MainBootyDrop", 1, {})
    bootyDropCntDict = IpyGameDataPY.GetFuncEvalCfg("MainBootyDrop", 2, {})
    for itemID, dropUpper in DailyBootyUpperList:
    for itemID, baseUpper in DailyBootyUpperList:
        if spaceCount <= 0:
            GameWorld.DebugLog("掉落背包已满!", playerID)
            break
        if dropUpper <= 0:
        if baseUpper <= 0:
            continue
        dropUpper = baseUpper
        addPer = 0
        addPer += PlayerBeauty.GetBeautyEffInfo(curPlayer, PlayerBeauty.EffType_BootyPer)[0] # 战利品上限提高百分比
        if addPer:
            dropUpper = int(baseUpper * (100 + addPer) / 100.0)
            GameWorld.DebugLog("红颜提高战利品掉落上限: itemID=%s,baseUpper=%s,addPer=%s,dropUpper=%s" % (itemID, baseUpper, addPer, dropUpper))
        todyDropCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BootyDropToday % itemID)
        if todyDropCnt >= dropUpper:
            GameWorld.DebugLog("战利品已达今日掉落上限! itemID=%s,todyDropCnt=%s >= %s" % (itemID, todyDropCnt, dropUpper), playerID)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Zhanchui.py
@@ -17,6 +17,7 @@
import GameWorld
import ItemControler
import PlayerBeauty
import FBCommon
def OnTurnFightRequest(curPlayer, mapID, funcLineID, tagType, tagID, valueList):
@@ -74,13 +75,35 @@
def OnPlayerFBSweepResult(curPlayer, mapID, lineID, sweepCnt, dataEx, askRet):
    ## 扫荡结果,次数消耗已在外层处理扣除
    
    itemList = FBCommon.GetSweepAwardList(mapID, lineID, sweepCnt)
    GameWorld.DebugLog("白骨盈野扫荡: mapID=%s,lineID=%s,sweepCnt=%s" % (mapID, lineID, sweepCnt))
    itemList = []
    itemList += FBCommon.GetSweepAwardList(mapID, lineID, sweepCnt)
    GameWorld.DebugLog("白骨盈野扫荡: mapID=%s,lineID=%s,sweepCnt=%s,itemList=%s" % (mapID, lineID, sweepCnt, itemList))
    
    addPer = PlayerBeauty.GetBeautyEffInfo(curPlayer, PlayerBeauty.EffType_FBZhanchuiAwardPer)[0] # 扫荡奖励百分比
    if addPer:
        GameWorld.DebugLog("红颜额外增加扫荡奖励百分比: %s, itemList=%s" % (addPer, itemList))
        itemListEx = []
        for itemInfo in itemList:
            itemID = itemInfo[0]
            itemCount = itemInfo[1]
            addCount = int(itemCount * addPer / 100.0)
            if addCount > 0:
                itemListEx.append([itemID, addCount, 1]) # 标记是红颜效果额外获得的
        itemList += itemListEx
        GameWorld.DebugLog("itemListEx=%s,itemList=%s" % (itemListEx, itemList))
    ItemControler.GivePlayerItemOrMail(curPlayer, itemList, event=["Zhanchui", False, {}], isNotifyAward=False)
    
    isPass = 1
    overDict = {FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(itemList), FBCommon.Over_isSweep:1}
    jsonItemList = []
    for itemInfo in itemList:
        itemID = itemInfo[0]
        itemCount = itemInfo[1]
        itemDict = {"ItemID":itemInfo[0], "Count":itemInfo[1]}
        if len(itemInfo) > 2:
            itemDict['BeautyEx'] = itemInfo[2]
        jsonItemList.append(itemDict)
    overDict = {FBCommon.Over_itemInfo:jsonItemList, FBCommon.Over_isSweep:1}
    FBCommon.NotifyFBOver(curPlayer, mapID, lineID, isPass, overDict)
    
    return True
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -795,6 +795,43 @@
                        ("list", "LVUPNeedItemInfo", 0),
                        ),
                "Beauty":(
                        ("WORD", "BeautyID", 1),
                        ("BYTE", "BeautyQuality", 0),
                        ("BYTE", "UnlockWay", 0),
                        ("DWORD", "UnlockValue", 0),
                        ("BYTE", "UnlockNeedCnt", 0),
                        ("list", "TalentAttrIDList", 0),
                        ("list", "TalentAttrValueList", 0),
                        ("list", "TalentPerLVAddList", 0),
                        ("BYTE", "EffType", 0),
                        ("BYTE", "EffTypeValue", 0),
                        ("BYTE", "EffValue", 0),
                        ("DWORD", "EffPerLVAdd", 0),
                        ),
                "BeautyQualityLV":(
                        ("BYTE", "BeautyQuality", 1),
                        ("WORD", "BeautyLV", 1),
                        ("WORD", "LVNeedExp", 0),
                        ("list", "AttrIDList", 0),
                        ("list", "AttrValueList", 0),
                        ("list", "AwardItemList", 0),
                        ),
                "BeautySkin":(
                        ("WORD", "SkinID", 0),
                        ("WORD", "BeautyID", 1),
                        ("BYTE", "UnlockWay", 0),
                        ("DWORD", "UnlockValue", 0),
                        ("BYTE", "UnlockNeedCnt", 0),
                        ("BYTE", "UpNeedCnt", 0),
                        ("BYTE", "StarMax", 0),
                        ("list", "AttrIDList", 0),
                        ("list", "InitAttrValueList", 0),
                        ("list", "AttrPerStarAddList", 0),
                        ),
                "PlayerLV":(
                        ("WORD", "LV", 1),
                        ("DWORD", "Exp", 0),
@@ -1185,16 +1222,6 @@
                        ("dict", "Reward", 0),
                        ("BYTE", "VIPLimit", 0),
                        ("list", "VIPAward", 0),
                        ),
                "XBXZ":(
                        ("DWORD", "ID", 1),
                        ("BYTE", "Type", 0),
                        ("DWORD", "NeedCnt", 0),
                        ("list", "Condition", 0),
                        ("WORD", "MWID", 0),
                        ("list", "AwardItem", 0),
                        ("list", "Money", 0),
                        ),
                "TreasureSet":(
@@ -3319,6 +3346,58 @@
    def GetLessEqualLV(self): return self.attrTuple[1] # 小于等于等级 BYTE
    def GetLVUPNeedItemInfo(self): return self.attrTuple[2] # 升级所需物品 [[物品ID,个数], ...] list
# 红颜表
class IPY_Beauty():
    def __init__(self):
        self.attrTuple = None
        return
    def GetBeautyID(self): return self.attrTuple[0] # 红颜ID WORD
    def GetBeautyQuality(self): return self.attrTuple[1] # 品质 BYTE
    def GetUnlockWay(self): return self.attrTuple[2] # 解锁方式 BYTE
    def GetUnlockValue(self): return self.attrTuple[3] # 解锁方式值 DWORD
    def GetUnlockNeedCnt(self): return self.attrTuple[4] # 解锁所需个数 BYTE
    def GetTalentAttrIDList(self): return self.attrTuple[5] # 天赋属性ID列表 list
    def GetTalentAttrValueList(self): return self.attrTuple[6] # 天赋属性初始值 list
    def GetTalentPerLVAddList(self): return self.attrTuple[7] # 天赋属性每级成长 list
    def GetEffType(self): return self.attrTuple[8] # 天赋效果类型 BYTE
    def GetEffTypeValue(self): return self.attrTuple[9] # 效果类型值 BYTE
    def GetEffValue(self): return self.attrTuple[10] # 效果初始值 BYTE
    def GetEffPerLVAdd(self): return self.attrTuple[11] # 天赋效果每级成长 DWORD
# 红颜品质升级表
class IPY_BeautyQualityLV():
    def __init__(self):
        self.attrTuple = None
        return
    def GetBeautyQuality(self): return self.attrTuple[0] # BYTE
    def GetBeautyLV(self): return self.attrTuple[1] # WORD
    def GetLVNeedExp(self): return self.attrTuple[2] # 升到本级所需经验 WORD
    def GetAttrIDList(self): return self.attrTuple[3] # 本级属性ID列表 list
    def GetAttrValueList(self): return self.attrTuple[4] # 本级属性值列表 list
    def GetAwardItemList(self): return self.attrTuple[5] # 本级奖励 list
# 红颜时装表
class IPY_BeautySkin():
    def __init__(self):
        self.attrTuple = None
        return
    def GetSkinID(self): return self.attrTuple[0] # ʱװID WORD
    def GetBeautyID(self): return self.attrTuple[1] # WORD
    def GetUnlockWay(self): return self.attrTuple[2] # 解锁方式 BYTE
    def GetUnlockValue(self): return self.attrTuple[3] # 解锁方式值 DWORD
    def GetUnlockNeedCnt(self): return self.attrTuple[4] # 解锁所需个数 BYTE
    def GetUpNeedCnt(self): return self.attrTuple[5] # 升级所需个数 BYTE
    def GetStarMax(self): return self.attrTuple[6] # 最高星级 BYTE
    def GetAttrIDList(self): return self.attrTuple[7] # 属性ID列表 list
    def GetInitAttrValueList(self): return self.attrTuple[8] # 初始属性值列表 list
    def GetAttrPerStarAddList(self): return self.attrTuple[9] # 每星加成值列表 list
# 玩家等级表
class IPY_PlayerLV():
    
@@ -3900,21 +3979,6 @@
    def GetReward(self): return self.attrTuple[3] # 奖励 {"职业":[[物品ID,个数],...], ...} dict
    def GetVIPLimit(self): return self.attrTuple[4] # 需要VIP几 BYTE
    def GetVIPAward(self): return self.attrTuple[5] # vip奖励[[物品ID,个数],...] list
# 仙宝寻主表
class IPY_XBXZ():
    def __init__(self):
        self.attrTuple = None
        return
    def GetID(self): return self.attrTuple[0] # ID DWORD
    def GetType(self): return self.attrTuple[1] # 类型 BYTE
    def GetNeedCnt(self): return self.attrTuple[2] # 需要数量 DWORD
    def GetCondition(self): return self.attrTuple[3] # 条件 list
    def GetMWID(self): return self.attrTuple[4] # 法宝ID WORD
    def GetAwardItem(self): return self.attrTuple[5] # 奖励物品列表 list
    def GetMoney(self): return self.attrTuple[6] # 金钱 list
# 寻宝设定表
class IPY_TreasureSet():
@@ -5631,6 +5695,9 @@
        self.__LoadFileData("GubaoResonance", onlyCheck)
        self.__LoadFileData("GubaoStar", onlyCheck)
        self.__LoadFileData("GubaoLV", onlyCheck)
        self.__LoadFileData("Beauty", onlyCheck)
        self.__LoadFileData("BeautyQualityLV", onlyCheck)
        self.__LoadFileData("BeautySkin", onlyCheck)
        self.__LoadFileData("PlayerLV", onlyCheck)
        self.__LoadFileData("SpecMapPlayerAttrFormat", onlyCheck)
        self.__LoadFileData("GMAttr", onlyCheck)
@@ -5669,7 +5736,6 @@
        self.__LoadFileData("CTGSelectItem", onlyCheck)
        self.__LoadFileData("FirstCharge", onlyCheck)
        self.__LoadFileData("LVAward", onlyCheck)
        self.__LoadFileData("XBXZ", onlyCheck)
        self.__LoadFileData("TreasureSet", onlyCheck)
        self.__LoadFileData("TreasureHouse", onlyCheck)
        self.__LoadFileData("TreasureItemLib", onlyCheck)
@@ -6494,6 +6560,27 @@
        self.CheckLoadData("GubaoLV")
        return self.ipyGubaoLVCache[index]
    def GetBeautyCount(self):
        self.CheckLoadData("Beauty")
        return self.ipyBeautyLen
    def GetBeautyByIndex(self, index):
        self.CheckLoadData("Beauty")
        return self.ipyBeautyCache[index]
    def GetBeautyQualityLVCount(self):
        self.CheckLoadData("BeautyQualityLV")
        return self.ipyBeautyQualityLVLen
    def GetBeautyQualityLVByIndex(self, index):
        self.CheckLoadData("BeautyQualityLV")
        return self.ipyBeautyQualityLVCache[index]
    def GetBeautySkinCount(self):
        self.CheckLoadData("BeautySkin")
        return self.ipyBeautySkinLen
    def GetBeautySkinByIndex(self, index):
        self.CheckLoadData("BeautySkin")
        return self.ipyBeautySkinCache[index]
    def GetPlayerLVCount(self):
        self.CheckLoadData("PlayerLV")
        return self.ipyPlayerLVLen
@@ -6759,13 +6846,6 @@
    def GetLVAwardByIndex(self, index):
        self.CheckLoadData("LVAward")
        return self.ipyLVAwardCache[index]
    def GetXBXZCount(self):
        self.CheckLoadData("XBXZ")
        return self.ipyXBXZLen
    def GetXBXZByIndex(self, index):
        self.CheckLoadData("XBXZ")
        return self.ipyXBXZCache[index]
    def GetTreasureSetCount(self):
        self.CheckLoadData("TreasureSet")
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
@@ -2005,11 +2005,11 @@
        return False
    
    if isAuctionItem:
        ipyData = None #IpyGameDataPY.GetIpyGameData("AuctionItem", itemID)
        if not ipyData:
            GameWorld.ErrLog("非拍卖物品,默认转为非拍品! itemID=%s,itemCount=%s,isAuctionItem=%s"
                             % (itemID, itemCount, isAuctionItem), curPlayer.GetPlayerID())
            isAuctionItem = 0
        #ipyData = None #IpyGameDataPY.GetIpyGameData("AuctionItem", itemID)
        #if not ipyData:
        #    GameWorld.ErrLog("非拍卖物品,默认转为非拍品! itemID=%s,itemCount=%s,isAuctionItem=%s"
        #                     % (itemID, itemCount, isAuctionItem), curPlayer.GetPlayerID())
        isAuctionItem = 0
    
    defaultPack = IPY_GameWorld.rptItem if not packIndexList else packIndexList[0]
    packIndex = ChConfig.GetItemPackType(curItemData, defaultPack)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -131,6 +131,7 @@
import PlayerTalk
import PlayerHero
import PlayerOnline
import PlayerBeauty
import TurnAttack
import PlayerHJG
import ObjPool
@@ -732,6 +733,7 @@
        UpdatePlayerName.OnPlayerLogin(curPlayer)
        PlayerActivity.OnPlayerLogin(curPlayer)
        PlayerLLMJ.OnPlayerLogin(curPlayer)
        PlayerBeauty.OnPlayerLogin(curPlayer)
        
        # 上线查询一次充值订单
        curPlayer.SendDBQueryRecharge()
@@ -3233,6 +3235,9 @@
    # 功能开启奖励
    elif rewardType == ChConfig.Def_RewardType_OpenFunc:
        GameFuncComm.GetFuncOpenAward(curPlayer, dataEx)
    # 红颜等级奖励
    elif rewardType == ChConfig.Def_RewardType_BeautyLVAward:
        PlayerBeauty.GetBeautyLVAward(curPlayer, dataEx)
        
        
    # 每日免费直购礼包
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
@@ -373,5 +373,6 @@
def Sync_ArenaInfo(curPlayer):
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCArenaPlayerInfo)
    clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
    clientPack.WinCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaWinCnt)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBeauty.py
New file
@@ -0,0 +1,626 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.PlayerBeauty
#
# @todo:红颜
# @author hxp
# @date 2025-11-21
# @version 1.0
#
# 详细描述: 红颜
#
#-------------------------------------------------------------------------------
#"""Version = 2025-11-21 17:00"""
#-------------------------------------------------------------------------------
import ChConfig
import GameWorld
import ItemCommon
import PlayerOnline
import PlayerControl
import IpyGameDataPY
import ChPyNetSendPack
import PlayerGoldRush
import NetPackCommon
import ItemControler
import PlayerTask
import FBCommon
import ObjPool
import PyGameData
# 红颜解锁方式
(
UnlockWay_Item, # 物品解锁 1
UnlockWay_TaskID, # 完成主线任务ID 2
UnlockWay_ArenaWinCnt, # 演武场胜利次数 3
UnlockWay_GoldRushWorker, # 拥有监工数量 4
UnlockWay_FBZhanchui, # 白骨盈野过关 5
UnlockWay_OfficialRank, # 官职达到 6
UnlockWay_TravelCnt, # 游历次数 7
) = range(1, 1 + 7)
# 皮肤解锁方式
UnlockWaySkin_Default = 1 # 默认解锁 1
UnlockWaySkin_Item = 2 # 物品解锁 2
# 红颜效果类型
(
EffType_BootyPer, # 1. 主线战利品上限提高百分比(对所有主线战利品生效)  Value:百分比
EffType_ArenaItemEx, # 2. 演武场挑战胜利,概率额外获得1个物品的概率    TypeValue:物品ID  Value:概率
EffType_TravelEnergy, # 3.游历体力上限增加     Value:增加上限
EffType_FBZhanchuiAwardPer, # 4.白骨盈野扫荡奖励增加百分比     Value:百分比
) = range(1, 1 + 4)
def OnPlayerLogin(curPlayer):
    SyncBeautyInfo(curPlayer)
    return
## Def_PDict_BeautyLVInfo 经验*10000+等级*10+是否已激活
def GetBeautyState(curPlayer, beautyID):
    ## 红颜激活状态
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyLVInfo % beautyID) % 10
def SetBeautyState(curPlayer, beautyID, state):
    ## 设置红颜激活状态
    lvInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyLVInfo % beautyID)
    lvInfo = lvInfo / 10 * 10 + min(1, state)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautyLVInfo % beautyID, lvInfo)
    return lvInfo
def GetBeautyLVInfo(curPlayer, beautyID):
    ## 获取红颜等级经验
    lvInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyLVInfo % beautyID)
    exp = lvInfo / 10000
    lv = lvInfo % 10000 / 10
    return lv, exp
def SetBeautyLVInfo(curPlayer, beautyID, lv, exp):
    lvInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyLVInfo % beautyID)
    lvInfo = min(exp, 200000) * 10000 + min(lv, 999) * 10 + lvInfo % 10
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautyLVInfo % beautyID, lvInfo)
    return lvInfo
## Def_PDict_BeautySkinInfo 星级*100+是否使用+是否已激活
def GetBeautySkinState(curPlayer, skinID):
    ## 红颜时装激活状态
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID) % 10
def SetBeautySkinState(curPlayer, skinID, state):
    info = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID)
    info = info / 10 * 10 + min(1, state)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautySkinInfo % skinID, info)
    return info
def GetBeautySkinUsed(curPlayer, skinID):
    ## 是否使用中
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID) % 100 / 10
def SetBeautySkinUsed(curPlayer, skinID, isUsed):
    info = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID)
    info = info / 100 * 100 + min(1, isUsed) * 10 + info % 10
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautySkinInfo % skinID, info)
    return info
def GetBeautySkinStar(curPlayer, skinID):
    ## 红颜时装星级
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID) / 100
def SetBeautySkinStar(curPlayer, skinID, star):
    info = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID)
    info = star * 100 + info % 100
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautySkinInfo % skinID, info)
    return info
def IsBeautySkinCanUse(curPlayer, beautyID, skinID, ipyData=None):
    ## 红颜时装是否可用
    if GetBeautySkinState(curPlayer, skinID):
        return True
    if not ipyData:
        ipyData = GetBeautySkinIpyData(curPlayer, beautyID, skinID)
    if ipyData:
        unlockWay = ipyData.GetUnlockWay()
        if unlockWay == UnlockWaySkin_Default: # 默认激活的
            return True
    return False
#// B2 19 红颜激活 #tagCSBeautyActivate
#
#struct    tagCSBeautyActivate
#{
#    tagHead         Head;
#    WORD        BeautyID;    //红颜ID
#};
def OnBeautyActivate(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    beautyID = curPackData.BeautyID
    if GetBeautyState(curPlayer, beautyID):
        GameWorld.DebugLog("红颜已经激活过! beautyID=%s" % beautyID, playerID)
        return
    ipyData = IpyGameDataPY.GetIpyGameData("Beauty", beautyID)
    if not ipyData:
        return
    unlockWay = ipyData.GetUnlockWay()
    unlockValue = ipyData.GetUnlockValue()
    unlockNeedCnt = ipyData.GetUnlockNeedCnt()
    if unlockWay == UnlockWay_Item:
        needItemID = unlockValue
        needItemCnt = unlockNeedCnt
        itemCount = ItemControler.GetItemCountByID(curPlayer, needItemID)
        if itemCount < needItemCnt:
            GameWorld.DebugLog("激活红颜物品不足! beautyID=%s,needItemID=%s,itemCount=%s < %s" % (beautyID, needItemID, itemCount, needItemCnt), playerID)
            return
        ItemControler.DelItemCountByID(curPlayer, needItemID, needItemCnt)
    elif unlockWay == UnlockWay_TaskID:
        taskID = unlockValue
        if not PlayerTask.IsTaskFinish(curPlayer, taskID):
            GameWorld.DebugLog("激活红颜所需任务未完成! beautyID=%s,taskID=%s" % (beautyID, taskID), playerID)
            return
    elif unlockWay == UnlockWay_ArenaWinCnt:
        needWinCnt = unlockNeedCnt
        winCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaWinCnt)
        if winCnt < needWinCnt:
            GameWorld.DebugLog("激活红颜所需演武场胜利次数不足! beautyID=%s,winCnt=%s < %s" % (beautyID, winCnt, needWinCnt), playerID)
            return
    elif unlockWay == UnlockWay_GoldRushWorker:
        needWorkerCnt = unlockNeedCnt
        workerTotal = PlayerGoldRush.GetWorkerTotal(curPlayer)
        if workerTotal < needWorkerCnt:
            GameWorld.DebugLog("激活红颜所需监工不足! beautyID=%s,workerTotal=%s < %s" % (beautyID, workerTotal, needWorkerCnt), playerID)
            return
    elif unlockWay == UnlockWay_FBZhanchui:
        mapID = ChConfig.Def_FBMapID_Zhanchui
        funcLineID = unlockValue
        isPass = FBCommon.IsFBPass(curPlayer, mapID, funcLineID)
        if not isPass:
            GameWorld.DebugLog("激活红颜所需副本未过关! beautyID=%s,mapID=%s,funcLineID=%s" % (beautyID, mapID, funcLineID), playerID)
            return
    elif unlockWay == UnlockWay_OfficialRank:
        realmLV = curPlayer.GetOfficialRank()
        needRealmLV = unlockValue
        if realmLV < needRealmLV:
            GameWorld.DebugLog("激活红颜所需官职不足! beautyID=%s,realmLV=%s < %s" % (beautyID, realmLV, needRealmLV), playerID)
            return
    elif unlockWay == UnlockWay_TravelCnt:
        travelCnt = 0
        needTravelCnt = unlockNeedCnt
        if travelCnt < needTravelCnt:
            GameWorld.DebugLog("激活红颜所需游历次数不足! beautyID=%s,travelCnt=%s < %s" % (beautyID, travelCnt, needTravelCnt), playerID)
            return
    else:
        GameWorld.DebugLog("该红颜不支持激活! beautyID=%s,unlockWay=%s" % (beautyID, unlockWay), playerID)
        return
    DoBeautyActivate(curPlayer, beautyID)
    return
def DoBeautyActivate(curPlayer, beautyID):
    ## 执行激活红颜逻辑
    if GetBeautyState(curPlayer, beautyID):
        return
    lv, exp = 0, 0
    SetBeautyState(curPlayer, beautyID, 1)
    SetBeautyLVInfo(curPlayer, beautyID, lv, exp)
    GameWorld.DebugLog("红颜激活成功! beautyID=%s" % beautyID, curPlayer.GetPlayerID())
    RefreshBeautyAttr(curPlayer)
    SyncBeautyInfo(curPlayer, [beautyID])
    return
#// B2 20 红颜好感度升级 #tagCSBeautyLVUP
#
#struct    tagCSBeautyLVUP
#{
#    tagHead         Head;
#    WORD        BeautyID;    //红颜ID
#    DWORD        ItemID;        //使用物品ID
#    BYTE        IsQuick;        // 是否快速升级,0-只消耗1个道具;1-消耗升1级的道具
#};
def OnBeautyLVUP(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    beautyID = curPackData.BeautyID
    itemID = curPackData.ItemID
    isQuick = curPackData.IsQuick
    if not GetBeautyState(curPlayer, beautyID):
        GameWorld.DebugLog("红颜未激活! beautyID=%s" % beautyID, playerID)
        return
    ipyData = IpyGameDataPY.GetIpyGameData("Beauty", beautyID)
    if not ipyData:
        return
    quality = ipyData.GetBeautyQuality()
    curLV, curExp = GetBeautyLVInfo(curPlayer, beautyID)
    isCommItem = True # 是否使用的常规通用物品
    commItemIDList = IpyGameDataPY.GetFuncEvalCfg("BeautyLVUP", 1)
    commExpList = IpyGameDataPY.GetFuncEvalCfg("BeautyLVUP", 2)
    if itemID in commItemIDList:
        index = commItemIDList.index(itemID)
        perExp = commExpList[index] if len(commExpList) > index else 0
    else:
        isCommItem = False
        unlockWay = ipyData.GetUnlockWay()
        unlockValue = ipyData.GetUnlockValue()
        if unlockWay != UnlockWay_Item:
            GameWorld.DebugLog("非道具激活的不支持专属信物ID升级! beautyID=%s,unlockWay=%s" % (beautyID, unlockWay), playerID)
            return
        if itemID != unlockValue:
            GameWorld.DebugLog("非该红颜专属信物ID! beautyID=%s,itemID=%s != %s" % (beautyID, itemID, unlockValue), playerID)
            return
        perExp = IpyGameDataPY.GetFuncCfg("BeautyLVUP", 3)
    if perExp <= 0:
        return
    nextLV = curLV + 1
    nextLVIpyData = IpyGameDataPY.GetIpyGameData("BeautyQualityLV", quality, nextLV)
    if not nextLVIpyData:
        GameWorld.DebugLog("红颜已满级! beautyID=%s,quality=%s,curLV=%s" % (beautyID, quality, curLV), playerID)
        return
    lvNeedExp = nextLVIpyData.GetLVNeedExp()
    costItemCount = 0
    needExp = lvNeedExp - curExp # 升级还需经验
    if needExp > 0:
        if isQuick:
            costItemCount = needExp / perExp
            if needExp % perExp > 0:
                costItemCount += 1
        else:
            costItemCount = 1
        if costItemCount < 1:
            return
        if isCommItem:
            costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, itemID, costItemCount)
            lackCnt = costItemCount - bindCnt - unBindCnt
            if lackCnt > 0:
                costItemCount -= lackCnt
                GameWorld.DebugLog("消耗道具不足,有多少消耗多少! itemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s"
                                   % (itemID, costItemCount, bindCnt, unBindCnt, lackCnt))
            # 扣除消耗
            if costItemCount > 0:
                ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, costItemCount, "Beauty")
        else:
            itemCount = ItemControler.GetItemCountByID(curPlayer, itemID)
            if itemCount < costItemCount:
                costItemCount = itemCount
            if costItemCount > 0:
                ItemControler.SetItemCountByID(curPlayer, itemID, itemCount - costItemCount)
    addExp = costItemCount * perExp
    updExp = curExp + addExp
    GameWorld.DebugLog("红颜加经验: beautyID=%s,quality=%s,curLV=%s,curExp=%s,addExp=%s,updExp=%s/%s,itemID=%s,costItemCount=%s,perExp=%s"
                       % (beautyID, quality, curLV, curExp, addExp, updExp, lvNeedExp, itemID, costItemCount, perExp))
    updLV = curLV
    if updExp >= lvNeedExp:
        updExp -= lvNeedExp
        updLV += 1
        GameWorld.DebugLog("    升级: updLV=%s,updExp=%s" % (updLV, updExp))
    SetBeautyLVInfo(curPlayer, beautyID, updLV, updExp)
    SyncBeautyInfo(curPlayer, [beautyID])
    # 有升级额外处理
    if updLV > updLV:
        RefreshBeautyAttr(curPlayer)
    return
def GetBeautyLVAward(curPlayer, beautyID):
    ## 领取红颜等级奖励
    if not GetBeautyState(curPlayer, beautyID):
        GameWorld.DebugLog("红颜未激活! beautyID=%s" % beautyID)
        return
    ipyData = IpyGameDataPY.GetIpyGameData("Beauty", beautyID)
    if not ipyData:
        return
    quality = ipyData.GetBeautyQuality()
    curLV = GetBeautyLVInfo(curPlayer, beautyID)[0]
    awardLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyAwardLV % beautyID)
    if awardLV >= curLV:
        GameWorld.DebugLog("当前没有红颜等级奖励可领取! beautyID=%s,quality=%s,awardLV=%s >= curLV=%s" % (beautyID, quality, awardLV, curLV))
        return
    GameWorld.DebugLog("领取红颜等级奖励: beautyID=%s,quality=%s,curLV=%s,awardLV=%s" % (beautyID, quality, curLV, awardLV))
    updAwardLV = awardLV
    itemDict = {}
    for getLV in range(awardLV + 1, curLV + 1):
        lvIpyData = IpyGameDataPY.GetIpyGameData("BeautyQualityLV", quality, getLV)
        if not lvIpyData:
            break
        itemList = lvIpyData.GetAwardItemList()
        for itemInfo in itemList:
            itemID = itemInfo[0]
            itemCount = itemInfo[1]
            itemDict[itemID] = itemDict.get(itemID, 0) + itemCount
        updAwardLV = getLV
    if not itemDict:
        return
    awardItemList = [[itemID, itemCount] for itemID, itemCount in itemDict.items()]
    GameWorld.DebugLog("    updAwardLV=%s,awardItemList=%s" % (updAwardLV, awardItemList))
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BeautyAwardLV % beautyID, updAwardLV)
    SyncBeautyInfo(curPlayer, [beautyID])
    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["BeautyLVAward", False, {}])
    return
#// B2 21 红颜时装操作 #tagCSBeautySkinOP
#
#struct    tagCSBeautySkinOP
#{
#    tagHead         Head;
#    WORD        BeautyID;    //红颜ID
#    WORD        SkinID;        //ʱװID
#    BYTE        OPType;        //操作 1-激活;2-佩戴;3-升星
#};
def OnBeautySkinOP(index, curPackData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    beautyID = curPackData.BeautyID
    skinID = curPackData.SkinID
    opType = curPackData.OPType
    if not GetBeautyState(curPlayer, beautyID):
        GameWorld.DebugLog("红颜未激活! beautyID=%s" % beautyID, playerID)
        return
    if opType == 1:
        OnBeautySkinActivate(curPlayer, beautyID, skinID)
    elif opType == 2:
        OnUseBeautySkin(curPlayer, beautyID, skinID)
    elif opType == 3:
        OnBeautySkinStarUP(curPlayer, beautyID, skinID)
    return
def GetBeautySkinIpyData(curPlayer, beautyID, skinID):
    ipyDataList = IpyGameDataPY.GetIpyGameDataList("BeautySkin", beautyID)
    if not ipyDataList:
        return
    for ipyData in ipyDataList:
        if ipyData.GetSkinID() == skinID:
            return ipyData
    return
def OnBeautySkinActivate(curPlayer, beautyID, skinID):
    ## 红颜时装激活
    if GetBeautySkinState(curPlayer, skinID):
        GameWorld.DebugLog("红颜皮肤已激活! beautyID=%s,skinID=%s" % (beautyID, skinID))
        return
    ipyData = GetBeautySkinIpyData(curPlayer, beautyID, skinID)
    if not ipyData:
        return
    unlockWay = ipyData.GetUnlockWay()
    unlockValue = ipyData.GetUnlockValue()
    unlockNeedCnt = ipyData.GetUnlockNeedCnt()
    if unlockWay == UnlockWaySkin_Item:
        needItemID = unlockValue
        needItemCnt = unlockNeedCnt
        itemCount = ItemControler.GetItemCountByID(curPlayer, needItemID)
        if itemCount < needItemCnt:
            GameWorld.DebugLog("激活红颜时装物品不足! beautyID=%s,needItemID=%s,itemCount=%s < %s" % (beautyID, needItemID, itemCount, needItemCnt))
            return
        ItemControler.DelItemCountByID(curPlayer, needItemID, needItemCnt)
    else:
        GameWorld.DebugLog("红颜皮肤不需要激活! beautyID=%s,skinID=%s" % (beautyID, skinID))
        return
    SetBeautySkinState(curPlayer, skinID, 1)
    GameWorld.DebugLog("红颜皮肤激活: beautyID=%s,skinID=%s" % (beautyID, skinID))
    RefreshBeautyAttr(curPlayer)
    SyncBeautyInfo(curPlayer, [beautyID], [skinID])
    return
def OnUseBeautySkin(curPlayer, beautyID, skinID):
    playerID = curPlayer.GetPlayerID()
    if not IsBeautySkinCanUse(curPlayer, beautyID, skinID):
        GameWorld.DebugLog("该红颜时装不可用! beautyID=%s,skinID=%s" % (beautyID, skinID), playerID)
        return
    GameWorld.DebugLog("穿戴 红颜时装! beautyID=%s,skinID=%s" % (beautyID, skinID), playerID)
    ipyDataList = IpyGameDataPY.GetIpyGameDataList("BeautySkin", beautyID)
    if not ipyDataList:
        return
    skinIDList = []
    for ipyData in ipyDataList:
        ipySkinID = ipyData.GetSkinID()
        if ipySkinID == skinID:
            SetBeautySkinUsed(curPlayer, skinID, 1)
        elif GetBeautySkinUsed(curPlayer, ipySkinID):
            SetBeautySkinUsed(curPlayer, ipySkinID, 0)
        else:
            continue
        skinIDList.append(ipySkinID)
    SyncBeautyInfo(curPlayer, [beautyID], skinIDList)
    return
def OnBeautySkinStarUP(curPlayer, beautyID, skinID):
    playerID = curPlayer.GetPlayerID()
    if not IsBeautySkinCanUse(curPlayer, beautyID, skinID):
        GameWorld.DebugLog("该红颜时装不可用! beautyID=%s,skinID=%s" % (beautyID, skinID), playerID)
        return
    ipyData = GetBeautySkinIpyData(curPlayer, beautyID, skinID)
    if not ipyData:
        return
    starMax = ipyData.GetStarMax()
    curStar = GetBeautySkinStar(curPlayer, skinID)
    if curStar >= starMax:
        GameWorld.DebugLog("红颜时装星级已满! skinID=%s,curStar=%s >= %s" % (skinID, curStar, starMax), playerID)
        return
    if ipyData.GetUnlockWay() != UnlockWaySkin_Item:
        return
    needItemID = ipyData.GetUnlockValue()
    needItemCnt = ipyData.GetUpNeedCnt()
    if not needItemID or not needItemCnt:
        return
    itemCount = ItemControler.GetItemCountByID(curPlayer, needItemID)
    if itemCount < needItemCnt:
        GameWorld.DebugLog("红颜时装升星物品不足! skinID=%s,needItemID=%s,itemCount=%s < %s" % (skinID, needItemID, itemCount, needItemCnt))
        return
    ItemControler.DelItemCountByID(curPlayer, needItemID, needItemCnt)
    nextStar = curStar + 1
    GameWorld.DebugLog("红颜时装升星! skinID=%s,nextStar=%s" % (skinID, nextStar), playerID)
    SetBeautySkinStar(curPlayer, skinID, nextStar)
    RefreshBeautyAttr(curPlayer)
    SyncBeautyInfo(curPlayer, [beautyID], [skinID])
    return
def RefreshBeautyAttr(curPlayer):
    CalcBeautyAttr(curPlayer)
    PlayerOnline.GetOnlinePlayer(curPlayer).RefreshRoleAttr()
    return
def CalcBeautyAttr(curPlayer):
    playerID = curPlayer.GetPlayerID()
    attrDict = {}
    effTypeDict = {} # 特殊效果缓存
    talentLVUPPer = IpyGameDataPY.GetFuncCfg("BeautyLVUP", 4) # 每x级好感度提升一级天赋效果
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in range(ipyDataMgr.GetBeautyCount()):
        ipyData = ipyDataMgr.GetBeautyByIndex(index)
        beautyID = ipyData.GetBeautyID()
        if not GetBeautyState(curPlayer, beautyID):
            continue
        quality = ipyData.GetBeautyQuality()
        beautyLV = GetBeautyLVInfo(curPlayer, beautyID)[0]
        # 等级属性
        for lv in range(beautyLV + 1):
            lvIpyData = IpyGameDataPY.GetIpyGameData("BeautyQualityLV", quality, lv)
            if not lvIpyData:
                continue
            lvAttrIDList = lvIpyData.GetAttrIDList()
            lvAttrValueList = lvIpyData.GetAttrValueList()
            for lvIndex, attrID in enumerate(lvAttrIDList):
                attrValue = lvAttrValueList[lvIndex] if len(lvAttrValueList) > lvIndex else 0
                attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
        #GameWorld.DebugLog("红颜等级属性: beautyID=%s,quality=%s,beautyLV=%s,%s" % (beautyID, quality, beautyLV, attrDict), playerID)
        # 天赋属性
        talentAttrIDList = ipyData.GetTalentAttrIDList()
        talentAttrValueList = ipyData.GetTalentAttrValueList()
        talentPerLVAddList = ipyData.GetTalentPerLVAddList()
        talentLV = beautyLV / talentLVUPPer
        for tIndex, attrID in enumerate(talentAttrIDList):
            initValue = talentAttrValueList[tIndex] if len(talentAttrValueList) > tIndex else 0
            perLVAdd = talentPerLVAddList[tIndex] if len(talentPerLVAddList) > tIndex else 0
            attrValue = initValue + perLVAdd * talentLV
            attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
        #GameWorld.DebugLog("红颜天赋属性: beautyID=%s,talentLV=%s,%s" % (beautyID, talentLV, attrDict), playerID)
        # 特殊效果
        effType = ipyData.GetEffType()
        effTypeValue = ipyData.GetEffTypeValue()
        effValue = ipyData.GetEffValue()
        effPerLVAdd = ipyData.GetEffPerLVAdd()
        if effType:
            effValue = effValue + effPerLVAdd * talentLV
            effTypeDict[effType] = [effValue, effTypeValue]
            #GameWorld.DebugLog("红颜特殊效果: beautyID=%s,effType=%s,talentLV=%s,%s" % (beautyID, effType, talentLV, effTypeDict), playerID)
        # ʱװ
        ipyDataList = IpyGameDataPY.GetIpyGameDataList("BeautySkin", beautyID)
        if not ipyDataList:
            continue
        for skinIpyData in ipyDataList:
            skinID = skinIpyData.GetSkinID()
            if not IsBeautySkinCanUse(curPlayer, beautyID, skinID, skinIpyData):
                continue
            attrIDList = skinIpyData.GetAttrIDList()
            initAttrValueList = skinIpyData.GetInitAttrValueList()
            perStarAddList = skinIpyData.GetAttrPerStarAddList()
            star = GetBeautySkinStar(curPlayer, skinID)
            for sIndex, attrID in enumerate(attrIDList):
                initValue = initAttrValueList[sIndex] if len(initAttrValueList) > sIndex else 0
                perStarAdd = perStarAddList[sIndex] if len(perStarAddList) > sIndex else 0
                attrValue = initValue + perStarAdd * star
                attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
            #GameWorld.DebugLog("红颜时装属性: beautyID=%s,skinID=%s,star=%s,%s" % (beautyID, skinID, star, attrDict), playerID)
    # 保存计算值
    GameWorld.DebugLog("红颜属性: %s" % attrDict, playerID)
    GameWorld.DebugLog("红颜效果: %s" % effTypeDict, playerID)
    PyGameData.g_beautyEffTypeDict[playerID] = effTypeDict
    PlayerOnline.GetOnlinePlayer(curPlayer).SetCalcAttr(ChConfig.Def_CalcAttr_Beauty, attrDict)
    return
def GetBeautyEffInfo(curPlayer, effType):
    ## 获取红颜特殊效果信息
    # @return: effValue, effTypeValue
    effTypeDict = PyGameData.g_beautyEffTypeDict.get(curPlayer.GetPlayerID(), {})
    return effTypeDict.get(effType, [0, 0])
def SyncBeautyInfo(curPlayer, beautyIDList=None, skinIDList=None):
    if beautyIDList == None:
        syncBeautyIDList = []
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        for index in range(ipyDataMgr.GetBeautyCount()):
            ipyData = ipyDataMgr.GetBeautyByIndex(index)
            syncBeautyIDList.append(ipyData.GetBeautyID())
    else:
        syncBeautyIDList = beautyIDList
    beautyList = []
    for beautyID in syncBeautyIDList:
        state = GetBeautyState(curPlayer, beautyID)
        if not state and beautyIDList == None:
            continue
        lv, exp = GetBeautyLVInfo(curPlayer, beautyID)
        beauty = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCBeauty)
        beauty.BeautyID = beautyID
        beauty.State = state
        beauty.LV = lv
        beauty.Exp = exp
        beauty.AwardLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautyAwardLV % beautyID)
        beauty.SkinList = []
        ipyDataList = IpyGameDataPY.GetIpyGameDataList("BeautySkin", beautyID)
        if ipyDataList:
            for ipyData in ipyDataList:
                skinID = ipyData.GetSkinID()
                skinInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BeautySkinInfo % skinID)
                if skinIDList != None:
                    if skinID not in skinIDList:
                        continue
                else:
                    if not skinInfo:
                        continue
                beautySkin = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCBeautySkin)
                beautySkin.SkinID = skinID
                beautySkin.State = 1 if IsBeautySkinCanUse(curPlayer, beautyID, skinID, ipyData) else 0
                beautySkin.Used = GetBeautySkinUsed(curPlayer, skinID)
                beautySkin.Star = GetBeautySkinStar(curPlayer, skinID)
                beauty.SkinList.append(beautySkin)
        beauty.SkinCnt = len(beauty.SkinList)
        beautyList.append(beauty)
    if not beautyList:
        return
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCBeautyInfo)
    clientPack.BeautyList = beautyList
    clientPack.Count = len(clientPack.BeautyList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerChatBox.py
@@ -206,7 +206,7 @@
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    itemCount = ipyData.GetUpNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py
@@ -219,7 +219,7 @@
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    itemCount = ipyData.GetUpNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
@@ -419,7 +419,7 @@
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    itemCount = ipyData.GetUpNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerGoldRush.py
@@ -269,13 +269,7 @@
            if campID != cID:
                atWorkCnt += wCnt
            
    workersTotal = 0 # 总工人数
    workerState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GoldRushWorkerState)
    for index in range(ipyDataMgr.GetGoldRushWorkerCount()):
        ipyData = ipyDataMgr.GetGoldRushWorkerByIndex(index)
        workerID = ipyData.GetWorkerID()
        if workerState & pow(2, workerID):
            workersTotal += 1
    workersTotal = GetWorkerTotal(curPlayer) # 总工人数
    idleWorkers = workersTotal - atWorkCnt # 空闲工人数
    if idleWorkers <= 0:
        GameWorld.DebugLog("没有空闲工人,无法开始淘金! atWorkCnt=%s >= %s" % (atWorkCnt, workersTotal))
@@ -323,6 +317,18 @@
                       % (updWorkerCnt, realNeedSeconds, GameWorld.ChangeTimeNumToStr(endTime), campInfo))
    return
def GetWorkerTotal(curPlayer):
    ## 获取监工总数
    workersTotal = 0 # 总工人数
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    workerState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GoldRushWorkerState)
    for index in range(ipyDataMgr.GetGoldRushWorkerCount()):
        ipyData = ipyDataMgr.GetGoldRushWorkerByIndex(index)
        workerID = ipyData.GetWorkerID()
        if workerState & pow(2, workerID):
            workersTotal += 1
    return workersTotal
def __onGoldRushCancel(curPlayer, campID):
    ## 取消
    refreshCnt, goldID, workerCnt = GetCampInfo(curPlayer, campID)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHJG.py
@@ -401,7 +401,7 @@
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    itemCount = ipyData.GetUpNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
@@ -623,7 +623,7 @@
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    itemCount = ipyData.GetUpNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHorse.py
@@ -437,7 +437,7 @@
    if ipyData.GetUnlockWay() != 2:
        return
    itemID = ipyData.GetUnlockValue()
    itemCount = ipyData.GetUnlockNeedCnt()
    itemCount = ipyData.GetUpNeedCnt()
    if not itemID or not itemCount:
        return
    needItemList = [[itemID, itemCount]]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
@@ -24,6 +24,7 @@
import IpyGameDataPY
import FormulaControl
import PlayerPrestigeSys
import PlayerBeauty
import PlayerFamily
import PlayerHorse
import PlayerGubao
@@ -422,6 +423,7 @@
    PlayerGubao.CalcGubaoAttr(curPlayer)
    PlayerHJG.CalcHJGAttr(curPlayer)
    PlayerHorse.CalcHorseAttr(curPlayer)
    PlayerBeauty.CalcBeautyAttr(curPlayer)
    return
def doRefreshLineupAttr(curPlayer, olPlayer, lineup):
@@ -647,6 +649,7 @@
    gubaoAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Gubao)
    hjgAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_HJG)
    horseAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Horse)
    beautyAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_Beauty)
    
    GameWorld.DebugLog("    国家武将统计=%s" % countryHeroInfo, playerID)
    GameWorld.DebugLog("    羁绊武将统计=%s" % fetterHeroInfo, playerID)
@@ -665,6 +668,7 @@
    GameWorld.DebugLog("    主公古宝属性=%s" % gubaoAttrDict, playerID)
    GameWorld.DebugLog("    主幻境阁属性=%s" % hjgAttrDict, playerID)
    GameWorld.DebugLog("    主公坐骑属性=%s" % horseAttrDict, playerID)
    GameWorld.DebugLog("    主公红颜属性=%s" % beautyAttrDict, playerID)
    
    PlayerLV = curPlayer.GetLV()
    OfficialLV = curPlayer.GetOfficialRank()
@@ -708,6 +712,9 @@
            horseValue = horseAttrDict.get(attrID, 0)
            horsePer = horseAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
            
            beautyValue = beautyAttrDict.get(attrID, 0)
            beautyPer = beautyAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0
            lineupInitAddPer, lineupLVAddPer, lineupBreakLVAddPer, lineupStarAddPer = 0, 0, 0, 0
            if attrID in ChConfig.BaseAttrIDList:
                lineupInitAddPer, lineupLVAddPer, lineupBreakLVAddPer, lineupStarAddPer = InitAddPer, LVAddPer, BreakLVAddPer, StarAddPer
@@ -734,7 +741,8 @@
                
            # 计算
            attrParamDict = {"lvValue":lvValue, "equipValue":equipValue, "bookValue":bookValue, "bookPer":bookPer, "realmValue":realmValue, "realmPer":realmPer, 
                             "gubaoValue":gubaoValue, "gubaoPer":gubaoPer, "hjgValue":hjgValue, "hjgPer":hjgPer, "horseValue":horseValue, "horsePer":horsePer,
                             "gubaoValue":gubaoValue, "gubaoPer":gubaoPer, "hjgValue":hjgValue, "hjgPer":hjgPer, "horseValue":horseValue, "horsePer":horsePer,
                             "beautyValue":beautyValue, "beautyPer":beautyPer,
                             "lineupInitAddPer":lineupInitAddPer, "lineupLVAddPer":lineupLVAddPer, "lineupBreakLVAddPer":lineupBreakLVAddPer, "lineupStarAddPer":lineupStarAddPer,
                             "heroSelfValue":heroSelfValue, "heroSelfPer":heroSelfPer, "inheritPer":inheritPer,
                             "lineupHaloValue":lineupHaloValue, "lineupHaloPer":lineupHaloPer, "fetterValue":fetterValue, "fetterPer":fetterPer,
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -37,6 +37,8 @@
g_arenaPlayerMatchDict = {} # 本服竞技场玩家匹配记录缓存 {playerID:[tagPlayerID, ...], ...}
g_beautyEffTypeDict = {} # 红颜特殊效果缓存 {playerID:{effType:[effValue, effTypeValue], ...}, ...}
g_mapIDTxtInfo = {} # MapID.txt 加载的信息
g_realmDiffPlayerDict = {} # 境界难度玩家信息 {realm:[playerID, ...], ...}
g_realmDiffNPCRefresh = {} # {(lineID, realm):{refreshID:tagNPCRefresh, ...}}