ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py
@@ -23,16 +23,28 @@
import PlayerControl
import ItemControler
import NetPackCommon
import PlayerBossReborn
import PlayerFeastTravel
import PlayerActLunhuidian
import PlayerActYunshi
import PlayerActTask
import PlayerActivity
import PlayerSuccess
import PlayerGoldInvest
import OpenServerActivity
import PlayerBillboard
import ShareDefine
import ItemCommon
import PlayerHero
import PyGameData
import ChConfig
import random
(
CostType_Money, # 消耗货币 0
CostType_DayFree, # 每日免费 1
CostType_Item, # 消耗道具 2
CostType_ADFree, # 广告免费 3
) = range(4)
CostFreeTypes = [CostType_DayFree, CostType_ADFree]
# 寻宝类型: >=100的为策划自行配置的自定义寻宝类型,<100的用于指定系统寻宝功能
TreasureTypeList = (
@@ -46,11 +58,8 @@
TreasureType_HeroComm = 11 # 英雄招募 - 普通
TreasureType_HeroHigh = 12 # 英雄招募 - 高级
TreasureType_HeroScore = 13 # 英雄招募 - 积分
def DoTreasureOpen(curPlayer):
    ## 寻宝开启
    Sync_TreasureInfo(curPlayer)
    return
#武将招募的所有类型
TreasureType_HeroCallList = [TreasureType_HeroComm, TreasureType_HeroHigh, TreasureType_HeroScore]
def OnTreasureLogin(curPlayer):
    Sync_TreasureInfo(curPlayer)
@@ -68,6 +77,18 @@
        syncTypeList.append(treasureType)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCountToday % (treasureType), 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureFreeCount % (treasureType), 0)
        # 每日心愿重置
        wishLibSelect = ipyData.GetWishLibSelect()
        wishReset = ipyData.GetWishReset()
        if wishReset == 1:
            for libIDStr, wishCnt in wishLibSelect.items():
                for wishIndex in range(wishCnt):
                    wishID, outCnt = GetWishInfo(curPlayer, treasureType, libIDStr, wishIndex)
                    SetWishInfo(curPlayer, treasureType, libIDStr, wishIndex, wishID, 0)
                    GameWorld.DebugLog("寻宝每日心愿重置: treasureType=%s,libID=%s,wishIndex=%s,wishID=%s,昨日心愿产出次数=%s"
                                       % (treasureType, libIDStr, wishIndex, wishID, outCnt))
    if syncTypeList:
        Sync_TreasureInfo(curPlayer, syncTypeList)
    return
@@ -84,6 +105,7 @@
            ItemControler.RecycleItem(curPlayer, costItemID, recycleItemMail)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureFreeCount % (treasureType), 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCount % (treasureType), 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCountEx % (treasureType), 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCountToday % (treasureType), 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureLuck % (treasureType), 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCntAward % (treasureType), 0)
@@ -101,6 +123,98 @@
        return True
    return False
def GetWishInfo(curPlayer, treasureType, libID, wishIndex):
    ## 心愿信息
    # @return: 心愿ID, 已产出次数
    info = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureWish % (treasureType, libID, wishIndex))
    wishID, outCnt = info / 100, info % 100
    return wishID, outCnt
def SetWishInfo(curPlayer, treasureType, libID, wishIndex, wishID, outCnt):
    info = wishID * 100 + min(outCnt, 99)
    info = PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureWish % (treasureType, libID, wishIndex), info)
    return info
#// A5 69 寻宝心愿物品选择 #tagCSTreasureWishSelect
#
#struct tagCSTreasureWishSelect
#{
#    tagHead        Head;
#    BYTE        TreasureType;    //寻宝类型
#    BYTE        WishCnt;
#    WORD        WishIDList[WishCnt];    // 选择的寻宝物品库中的数据ID,注意不是库ID
#};
def OnTreasureWishSelect(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    treasureType = clientData.TreasureType
    reqSelectWishIDList = clientData.WishIDList
    setIpyData = IpyGameDataPY.GetIpyGameData("TreasureSet", treasureType)
    if not setIpyData:
        return
    wishLibSelect = setIpyData.GetWishLibSelect()
    if not wishLibSelect:
        GameWorld.DebugLog("该寻宝类型没有心愿物品功能! treasureType=%s" % (treasureType))
        return
    GameWorld.DebugLog("寻宝选择心愿物品: treasureType=%s,reqSelectWishIDList=%s" % (treasureType, reqSelectWishIDList))
    selectLibItemDict = {} # 重新选择的心愿物品汇总 {libID:[wishID, ...], ...}
    for wishID in reqSelectWishIDList:
        libItemIpyData = IpyGameDataPY.GetIpyGameDataByCondition("TreasureItemLib", {"ID":wishID}, False)
        if not libItemIpyData:
            return
        itemID = libItemIpyData.GetItemID()
        if not libItemIpyData.GetWishOutCnt():
            GameWorld.DebugLog("非心愿物品,不可选择! wishID=%s" % (wishID))
            return
        # 按所属库归类汇总
        libID = libItemIpyData.GetLibID()
        if libID not in selectLibItemDict:
            selectLibItemDict[libID] = []
        selectLibWishIDList = selectLibItemDict[libID]
        if wishID not in selectLibWishIDList:
            selectLibWishIDList.append(wishID)
        # 武将招募,额外限制
        if treasureType in TreasureType_HeroCallList:
            heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", itemID)
            if not heroIpyData:
                return
            if heroIpyData.GetRecruitBySelf() and not PlayerHero.GetHeroActivite(curPlayer, itemID):
                GameWorld.DebugLog("需要激活本体的武将未激活不可选择!itemID=%s" % itemID)
                return
    hisOutDict = {} # 历史选择已产出过的心愿物品记录 {wishID:outCnt, ...}
    for libIDStr, wishCnt in wishLibSelect.items():
        libID = int(libIDStr)
        selectLibWishIDList = selectLibItemDict.get(libID, [])
        if len(selectLibWishIDList) != wishCnt:
            GameWorld.DebugLog("选择心愿库的物品数量与设定的心愿物品数量不一致!libID=%s,wishCnt=%s,selectCnt=%s,%s"
                               % (libID, wishCnt, len(selectLibWishIDList), selectLibWishIDList))
            return
        for wishIndex in range(wishCnt):
            wishID, outCnt = GetWishInfo(curPlayer, treasureType, libID, wishIndex)
            if not outCnt:
                continue
            if wishID not in selectLibWishIDList:
                GameWorld.DebugLogEx("已经产出过的心愿物品不可从选择中去除! outCnt=%s,wishID=%s not in %s", outCnt, wishID, selectLibWishIDList)
                return
            hisOutDict[wishID] = outCnt
    # 验证通过,保存
    for libID, wishIDList in selectLibItemDict.items():
        for wishIndex, wishID in enumerate(wishIDList):
            outCnt = hisOutDict.get(wishID, 0)
            SetWishInfo(curPlayer, treasureType, libID, wishIndex, wishID, outCnt)
            GameWorld.DebugLog("保存心愿选择: libID=%s,wishIndex=%s,wishID=%s,outCnt=%s" % (libID, wishIndex, wishID, outCnt))
    Sync_TreasureInfo(curPlayer, [treasureType])
    return
#// A5 68 请求寻宝 #tagCMRequestTreasure
#
#struct tagCMRequestTreasure
@@ -112,12 +226,15 @@
#};
def OnRequestTreasure(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerLV = curPlayer.GetLV()
    playerID = curPlayer.GetPlayerID()
    treasureType = clientData.TreasureType
    treasureIndex = clientData.TreasureIndex
    costType = clientData.CostType
    DoTreasure(curPlayer, treasureType, costType, treasureIndex)
    return
def DoTreasure(curPlayer, treasureType, costType, treasureIndex=0):
    playerLV = curPlayer.GetLV()
    playerID = curPlayer.GetPlayerID()
    GameWorld.DebugLog("玩家寻宝: treasureType=%s,treasureIndex=%s,costType=%s,playerLV=%s" 
                       % (treasureType, treasureIndex, costType, playerLV), playerID)
    
@@ -132,6 +249,9 @@
    if not treasureCountList:
        GameWorld.DebugLog("没有寻宝次数列表配置!", playerID)
        return
    if costType == CostType_ADFree:
        treasureIndex = 0
        GameWorld.DebugLog("广告寻宝强制设置: treasureIndex=%s" % treasureIndex, playerID)
    if treasureIndex < 0 or treasureIndex >= len(treasureCountList):
        GameWorld.ErrLog("寻宝次数索引不存在!treasureType=%s,treasureIndex=%s" % (treasureType, treasureIndex), playerID)
        return
@@ -154,7 +274,7 @@
            return
        
    # 免费次数
    if costType == 1:
    if costType == CostType_DayFree:
        dailyFreeCount = setIpyData.GetDailyFreeCount()
        if not dailyFreeCount:
            GameWorld.ErrLog("该寻宝类型索引不支持免费次数寻宝!treasureType=%s,treasureIndex=%s" % (treasureType, treasureIndex), playerID)
@@ -164,9 +284,11 @@
        if updFreeCountToday > dailyFreeCount:
            GameWorld.DebugLog("今日免费次数不足,无法使用免费寻宝! freeCountToday=%s + %s > %s" % (freeCountToday, treasureCount, dailyFreeCount), playerID)
            return
    # 广告免费
    elif costType == CostType_ADFree:
        pass
    # 寻宝道具, 目前默认消耗1个
    elif costType == 2:
    elif costType == CostType_Item:
        costItemID = setIpyData.GetCostItemID()
        costItemList = setIpyData.GetCostItemCountList() # 消耗道具物品ID列表
        if not costItemID or not costItemList or treasureIndex >= len(costItemList):
@@ -239,15 +361,64 @@
    GameWorld.DebugLog("beSureCountDict=%s" % beSureCountDict, playerID)
    GameWorld.DebugLog("ensureCount=%s, %s" % (ensureCount, ensureRateList), playerID)
    notifyGridNumList = setIpyData.GetNotifyGridNumList() # 额外需要广播的格子,幸运必出、次数必出可不配置
    notifyKey = setIpyData.GetNotifyKey()
    notifyKeyDict = setIpyData.GetNotifyKeyDict()
    gridNumMaxLimitInfo = setIpyData.GetGridNumMaxLimitInfo() # {"格子":最大可产出次数, ...}
    gridNumCountInfo = {} # 有限制产出次数的格子已经产出数
    for gridNumStr in gridNumMaxLimitInfo.keys():
        gridNumCountInfo[int(gridNumStr)] = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureGridCnt % (treasureType, gridNumStr))
    GameWorld.DebugLog("gridNumMaxLimitInfo=%s,gridNumCountInfo=%s" % (gridNumMaxLimitInfo, gridNumCountInfo), playerID)
    
    treasureCountEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureCountEx % (treasureType)) # 当前第x次单抽、x抽
    curIndexCount, maxIndexCount = 0, 0
    beSureCountByIndexDict = {}
    beSureCountByIndexList = ipyData.GetGridItemRateList4() # 第x次x抽必出,最多支持定制到9次
    if beSureCountByIndexList and treasureIndex < len(beSureCountByIndexList):
        beSureCountByIndexDict = beSureCountByIndexList[treasureIndex]
        maxIndexCount = min(9, max(beSureCountByIndexDict))
        curIndexCount = GameWorld.GetDataByDigitPlace(treasureCountEx, treasureIndex) + 1
    beSureCountByIndexCfg = []
    if curIndexCount <= maxIndexCount and curIndexCount in beSureCountByIndexDict:
        beSureCountByIndexCfg = beSureCountByIndexDict[curIndexCount]
    gridItemInfoDict = ipyData.GetGridItemInfo() # 格子对应物品信息 {"格子编号":[物品ID, 数量], ...}
    gridLibInfoDict = ipyData.GetGridLibInfo() # 格子编号对应库ID {"编号":物品库ID, ...}
    # 心愿
    wishSelectState = False # 心愿物品是否已选择
    canOutWishDict = {} # 还可产出的心愿物品 {libID:{wishID:[wishIndex, canOut], ...}, ...}
    wishOutputRule = setIpyData.GetWishOutput() # 心愿产出规则:心愿产出完毕后:  0 - 可继续产出该库物品; 1 - 不可再产出该库物品
    wishLibSelect = setIpyData.GetWishLibSelect()
    for libIDStr, selectCnt in wishLibSelect.items():
        libID = int(libIDStr)
        if libID not in canOutWishDict:
            canOutWishDict[libID] = {}
        for wishIndex in range(selectCnt):
            wishID, outCnt = GetWishInfo(curPlayer, treasureType, libID, wishIndex)
            if not wishID:
                continue
            wishSelectState = True
            libItemIpyData = IpyGameDataPY.GetIpyGameDataByCondition("TreasureItemLib", {"ID":wishID}, False)
            if not libItemIpyData:
                continue
            outCntLimit = libItemIpyData.GetWishOutCnt()
            if not outCntLimit:
                # 非心愿物品
                continue
            if outCnt >= outCntLimit:
                # 该心愿物品产出次数已用完
                continue
            libWishCanOutDict = canOutWishDict[libID]
            canOut = outCntLimit - outCnt
            libWishCanOutDict[wishID] = [wishIndex, canOut]
    if canOutWishDict:
        if not wishSelectState:
            GameWorld.DebugLog("心愿物品还未选择!", playerID)
        else:
            GameWorld.DebugLog("还可产出的心愿库对应WishID还可产出次数: %s" % canOutWishDict, playerID)
    # 单抽产出优先级: 幸运物品 > 必出 > 保底 > 普通
    # 连抽没有优先级限制,只要满足条件即可产出
    luckyOut = False # 幸运物品理论产出状态,不一定是真实产出,可能受终身卡限制
    getGridResult = []
    for tIndex in range(treasureCount):
        updLuck = min(updLuck + addLuck, maxLuck)
@@ -266,11 +437,24 @@
        
        curRateList = [] # 可能会改变饼图,每次抽奖使用新的饼图对象,不要改变配置的饼图概率
        
        # 满幸运必出
        if stageLuck and updLuck >= stageLuck and luckItemRateList:
            curRateList = GetRemoveLimitGridRateList(luckItemRateList, gridNumCountInfo, gridNumMaxLimitInfo)
            GameWorld.DebugLog("    【满幸运必出饼图】: %s" % curRateList, playerID)
        # 第x次x抽必出,优先级最高,无视其他
        if not curRateList and beSureCountByIndexCfg:
            if tIndex == 0:
                curRateList = [[10000, beSureCountByIndexCfg[0]]]
            else:
                curRateList = beSureCountByIndexCfg[1]
            GameWorld.DebugLog("    【第x次x抽必出】: treasureIndex=%s,curIndexCount=%s,%s"
                               % (treasureIndex, curIndexCount, curRateList), playerID)
            
        # 满幸运必出
        if not curRateList and stageLuck and updLuck >= stageLuck and luckItemRateList:
            luckyOut = True
            if treasureType in TreasureType_HeroCallList and not PlayerGoldInvest.GetInvestState(curPlayer, ChConfig.InvestType_Life):
                GameWorld.DebugLog("    【满幸运必出饼图】: 终身卡未开通,武将招募幸运不产出", playerID)
            else:
                curRateList = GetRemoveLimitGridRateList(luckItemRateList, gridNumCountInfo, gridNumMaxLimitInfo)
                GameWorld.DebugLog("    【满幸运必出饼图】: %s" % curRateList, playerID)
        # 次数必出
        if not curRateList and updTreasureCount in beSureCountDict:
            besureGridRateList = beSureCountDict[updTreasureCount]
@@ -294,19 +478,34 @@
                GameWorld.DebugLog("    幸运物品已经出过,不再重复产出! gridNum=%s in %s" % (gridNum, getGridResult))
                continue
            
            # 其他产出限制...
            # 心愿产出限制
            gridNumStr = str(gridNum)
            wishLibID = 0
            if wishLibSelect and gridNumStr in gridLibInfoDict and gridLibInfoDict[gridNumStr] in canOutWishDict:
                wishLibID = gridLibInfoDict[gridNumStr]
                if wishOutputRule == 1: # 心愿物品产出完毕后,不可再产出该库物品,该模式下,未选择心愿的,也视为无可产出的心愿物品
                    if not canOutWishDict[wishLibID]:
                        GameWorld.DebugLog("    没有可产出的心愿物品,不产出! gridNum=%s,wishLibID=%s" % (gridNum, wishLibID), playerID)
                        continue
            if not gridNum:
                continue
            
            getGridResult.append(gridNum)
            GameWorld.DebugLog("    本次产出: gridNum=%s, %s" % (gridNum, getGridResult), playerID)
            if gridNum in luckyGridNumList:
            GameWorld.DebugLog("    本次产出: gridNum=%s, %s, doCount=%s" % (gridNum, getGridResult, doCount), playerID)
            if gridNum in luckyGridNumList or luckyOut:
                luckyOut = False
                if gridNum == setLuckyGridNum or updLuck >= maxLuck:
                    updLuck = 0
                else:
                    updLuck = stageLuck # 直接切换到下一阶段幸运
                GameWorld.DebugLog("    【产出幸运格子】: gridNum=%s,updLuck=%s" % (gridNum, updLuck), playerID)
                if gridNum in luckyGridNumList:
                    GameWorld.DebugLog("    【产出幸运格子】: gridNum=%s,updLuck=%s" % (gridNum, updLuck), playerID)
                else:
                    GameWorld.DebugLog("    【理论产出幸运格子,实际没有产出】: gridNum=%s,updLuck=%s,luckyGridNumList=%s" % (gridNum, updLuck, luckyGridNumList), playerID)
            if wishLibID:
                GameWorld.DebugLog("    【产出的是心愿库物品】: gridNum=%s,wishLibID=%s" % (gridNum, wishLibID), playerID)
            if gridNum in gridNumCountInfo:
                gridNumCountInfo[gridNum] = gridNumCountInfo[gridNum] + 1
                GameWorld.DebugLog("    【更新产出次数】: gridNum=%s, %s" % (gridNum, gridNumCountInfo), playerID)
@@ -319,12 +518,11 @@
    
    isBind = 0 # 暂时默认不绑定
    job = curPlayer.GetJob()
    gridItemInfoDict = ipyData.GetGridItemInfo() # 格子对应物品信息 {"格子编号":[物品ID, 数量], ...}
    gridLibInfoDict = ipyData.GetGridLibInfo() # 格子编号对应库ID {"编号":物品库ID, ...}
    jobItemList = ipyData.GetJobItemList()
    treasureResult = []
    randItemIDDict = IpyGameDataPY.GetFuncEvalCfg("TreasureSet", 2)
    
    wishAddOutDict = {} # 本次心愿物品预计增加产出 {wishID:addOut, ...}
    for gridNum in getGridResult:
        gridNum = str(gridNum)
        if gridNum in gridItemInfoDict:
@@ -353,30 +551,48 @@
            libItemList = IpyGameDataPY.GetIpyGameDataList("TreasureItemLib", libID)
            if not libItemList:
                return
            libWishCanOutDict = canOutWishDict.get(libID, {})
            wishWeightList = [] # 心愿物品权重
            itemWeightList = []
            for libItem in libItemList:
                curID = libItem.GetID()
                itemWeight, itemID, itemCount = libItem.GetItemWeight(), libItem.GetItemID(), libItem.GetItemCount()
                if not itemWeight:
                    continue
                if not __checkItemCanTreasure(curPlayer, treasureType, itemID):
                    continue
                itemWeightList.append([itemWeight, [itemID, itemCount]])
                if curID in libWishCanOutDict:
                    _, canOut = libWishCanOutDict[curID]
                    if canOut - wishAddOutDict.get(curID, 0) > 0:
                        wishWeightList.append([itemWeight, [itemID, itemCount, curID]])
            if not itemWeightList:
                GameWorld.ErrLog("寻宝随机格子没有可随机的物品!treasureType=%s,treasureIndex=%s,gridNum=%s,libID=%s" 
                                 % (treasureType, treasureIndex, gridNum, libID), playerID)
                return
            itemID, itemCount = GameWorld.GetResultByWeightList(itemWeightList)
            # 优先产出选择的心愿物品
            if wishWeightList:
                itemID, itemCount, curID = GameWorld.GetResultByWeightList(wishWeightList)
                wishAddOutDict[curID] = wishAddOutDict.get(curID, 0) + 1
                GameWorld.DebugLog("优先产出心愿物品: gridNum=%s,libID=%s,wishID=%s,itemID=%s" % (gridNum, libID, curID, itemID), playerID)
            else:
                itemID, itemCount = GameWorld.GetResultByWeightList(itemWeightList)
        else:
            GameWorld.ErrLog("寻宝格子不存在!treasureType=%s,gridNum=%s" % (treasureType, gridNum), playerID)
            return
        
        treasureResult.append([gridNum, itemID, itemCount, isBind])
        isTrans = 0 # 是否转化
        treasureResult.append([gridNum, itemID, itemCount, isTrans])
        
    # 扣消耗
    if costType == 1:
    if costType == CostType_DayFree:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureFreeCount % (treasureType), updFreeCountToday)
        GameWorld.DebugLog("消耗免费次数,更新今日已使用免费次数: %s" % updFreeCountToday, playerID)
    elif costType == 2:
    elif costType == CostType_ADFree:
        GameWorld.DebugLog("广告寻宝免费", playerID)
    elif costType == CostType_Item:
        ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, delCostItemCount, ChConfig.ItemDel_Treasure)
        GameWorld.DebugLog("扣除寻宝道具,costItemID=%s,delCostItemCount=%s" % (costItemID, delCostItemCount), playerID)
        if lackCountCostMoney:
@@ -393,48 +609,71 @@
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureLuck % (treasureType), updLuck)
    for gridNum, updCount in gridNumCountInfo.items():
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureGridCnt % (treasureType, gridNum), updCount)
    if curIndexCount <= maxIndexCount:
        treasureCountEx = GameWorld.ChangeDataByDigitPlace(treasureCountEx, treasureIndex, curIndexCount)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCountEx % (treasureType), treasureCountEx)
        GameWorld.DebugLog("更新第x次x抽次数: treasureIndex=%s,curIndexCount=%s,maxIndexCount=%s,treasureCountEx=%s" % (treasureIndex, curIndexCount, maxIndexCount, treasureCountEx), playerID)
    # 心愿产出次数
    for curID, addOut in wishAddOutDict.items():
        for libID, libWishCanOutDict in canOutWishDict.items():
            if curID not in libWishCanOutDict:
                continue
            wishIndex, canOut = libWishCanOutDict[curID]
            wishID, outCnt = GetWishInfo(curPlayer, treasureType, libID, wishIndex)
            updOut = outCnt + addOut
            SetWishInfo(curPlayer, treasureType, libID, wishIndex, wishID, updOut)
            GameWorld.DebugLog("更新心愿物品已产出次数: libID=%s,wishIndex=%s,wishID=%s,updOut=%s" % (libID, wishIndex, wishID, updOut), playerID)
    addScoreType = setIpyData.GetAwardMoneyType() # 额外奖励货币类型
    addScore = setIpyData.GetAwardMoneyValue() # 单次奖励货币数
    if addScoreType and addScore:
        PlayerControl.GiveMoney(curPlayer, addScoreType, addScore * treasureCount)
        
    if treasureType == TreasureType_Rune:
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_RuneTreasure, treasureCount)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_RuneTreasure, treasureCount)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_TreasureRune, treasureCount)
    elif treasureType == TreasureType_Jipin:
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_Treasure, treasureCount)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_Treasure, treasureCount)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_TreasureJipin, treasureCount)
    elif treasureType == TreasureType_Jueshi:
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_JSTreasure, treasureCount)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_JSTreasure, treasureCount)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_TreasureJueshi, treasureCount)
    elif treasureType == TreasureType_Gubao:
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_TreasureGubao, treasureCount)
    if treasureType in TreasureType_HeroCallList:
        PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_HeroCall, treasureCount)
        heroCallCnt = GetHeroCallCnt(curPlayer)
        if OpenServerActivity.GetOSAState(curPlayer, ShareDefine.Def_BT_OSA_HeroCall) == 1:
            PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_OSA_HeroCall, heroCallCnt)
        PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_OSAHeroCall, heroCallCnt)
        
    PlayerActLunhuidian.AddLunhuidianValue(curPlayer, PlayerActLunhuidian.AwardType_Treasure, treasureType, treasureCount)
    
    # 给物品
    mailItemList = []
    itemControl = ItemControler.PlayerItemControler(curPlayer)
    for gridNum, itemID, itemCount, isBind in treasureResult:
        itemObj = ItemControler.GetOutPutItemObj(itemID, itemCount, False, curPlayer=curPlayer)
    for tResult in treasureResult:
        gridNum, itemID, itemCount = tResult[:3]
        PyGameData.g_transItemSign = 0
        itemObj = ItemControler.GetOutPutItemObj(itemID, itemCount, isBind, curPlayer=curPlayer)
        mailItemDict = ItemCommon.GetMailItemDict(itemObj)
        
        if int(gridNum) in notifyGridNumList and notifyKey:
            PlayerControl.WorldNotify(0, notifyKey, [curPlayer.GetPlayerName(), itemID, itemObj.GetUserData(), itemCount])
        if int(gridNum) in notifyGridNumList and notifyKeyDict:
            notifyKey = notifyKeyDict.get(int(gridNum), notifyKeyDict.get(0, ""))
            if treasureType in TreasureType_HeroCallList:
                if PlayerHero.GetHeroActivite(curPlayer, itemID):
                    notifyKey = ""
                    GameWorld.DebugLog("招募武将非首次获得的不广播了! itemID=%s" % itemID, playerID)
                elif notifyKey:
                    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", itemID)
                    if heroIpyData:
                        heroQuality = heroIpyData.GetQuality()
                        PlayerControl.WorldNotify(0, notifyKey, [curPlayer.GetPlayerName(), heroQuality, itemID])
            elif notifyKey:
                PlayerControl.WorldNotify(0, notifyKey, [curPlayer.GetPlayerName(), itemID, itemObj.GetUserData(), itemCount])
            
        if mailItemList or not itemControl.PutInItem(packType, itemObj, event=[ChConfig.ItemGive_Treasure, False, {}]):
            mailItemList.append(mailItemDict)
            itemObj.Clear()
            
        # 检查物品转化
        if PyGameData.g_transItemSign:
            tResult[3] = 1 # 有转化物品时设置转化标记
    if mailItemList:
        PlayerControl.SendMailByKey("HappyXBUnEnough", [playerID], mailItemList)
        
    GameWorld.DebugLog("寻宝成功: treasureType=%s,updTreasureCount=%s(%s),updLuck=%s,addScoreType=%s,addScore=%s,gridNumCountInfo=%s"
                       % (treasureType, updTreasureCount, updTreasureCountToday, updLuck, addScoreType, addScore, gridNumCountInfo), playerID)
    GameWorld.DebugLog("寻宝成功: treasureType=%s,updTreasureCount=%s(%s),updLuck=%s,addScoreType=%s,addScore=%s,gridNumCountInfo=%s,treasureCountEx=%s"
                       % (treasureType, updTreasureCount, updTreasureCountToday, updLuck, addScoreType, addScore, gridNumCountInfo, treasureCountEx), playerID)
    GameWorld.DebugLog("    treasureResult=%s" % (treasureResult), playerID)
    GameWorld.DebugLog("    mailItemList=%s" % (mailItemList), playerID)
    
@@ -450,6 +689,13 @@
    
    Sync_TreasureInfo(curPlayer, [treasureType])
    return
def GetHeroCallCnt(curPlayer):
    ## 获取武将招募总次数
    callCount = 0
    for treasureType in TreasureType_HeroCallList:
        callCount += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureCount % (treasureType))
    return callCount
def __getLuckyRateInfo(curLuck, luckyItemRateDict, luckyValueList):
    if not luckyItemRateDict or not luckyValueList:
@@ -472,12 +718,12 @@
        if not heroIpyData:
            return
        if heroIpyData.GetRecruitBySelf() and not PlayerHero.GetHeroActivite(curPlayer, itemID):
            GameWorld.DebugLog("武将未激活不产出!itemID=%s" % itemID, playerID)
            GameWorld.DebugLog("武将未激活不产出! itemID=%s" % itemID, playerID)
            return
        
    elif itemData.GetType() == ChConfig.Def_ItemType_Rune:
        if not PlayerRune.GetIsOpenByRuneID(curPlayer, itemID):
            GameWorld.DebugLog("未解锁的符印不产出!itemID=%s" % itemID, playerID)
            GameWorld.DebugLog("未解锁的符印不产出! itemID=%s" % itemID, playerID)
            return
        
    return True
@@ -505,7 +751,7 @@
def GetUpdLuckyItemRateList(ipyData, luckyGridNumList, curLuck, luckFormula, costType):
    # 获取幸运物品提升概率后的饼图
    treasureType = ipyData.GetTreasureType()
    srcPieList = ipyData.GetGridItemRateListFree() if costType == 1 else ipyData.GetGridItemRateList1()
    srcPieList = ipyData.GetGridItemRateListFree() if costType in CostFreeTypes else ipyData.GetGridItemRateList1()
    if not srcPieList:
        srcPieList = ipyData.GetGridItemRateList1()
        
@@ -602,6 +848,18 @@
            gridLimit.GridCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureGridCnt % (tType, gridNum))
            tTypeInfo.GridLimitCntList.append(gridLimit)
        tTypeInfo.GridLimitCnt = len(tTypeInfo.GridLimitCntList)
        wishLibSelect = setIpyData.GetWishLibSelect()
        for libIDStr, wishCnt in wishLibSelect.items():
            libID = int(libIDStr)
            for wishIndex in range(wishCnt):
                wishID, outCnt = GetWishInfo(curPlayer, tType, libID, wishIndex)
                wish = ChPyNetSendPack.tagMCTreasureWish()
                wish.WishID = wishID
                wish.OutCnt = outCnt
                tTypeInfo.WishList.append(wish)
        tTypeInfo.WishCnt = len(tTypeInfo.WishList)
        treasureInfoPack.TreasuerInfoList.append(tTypeInfo)
    treasureInfoPack.InfoCount = len(treasureInfoPack.TreasuerInfoList)
    NetPackCommon.SendFakePack(curPlayer, treasureInfoPack)