hch
2025-11-26 ac36bdcfa7db1557790a5b912c3248b22625841f
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 PyGameData
import PlayerTask
import FBCommon
import ObjPool
# 红颜解锁方式
(
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 = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TravelCnt)
        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