hxp
2025-10-22 55c2c6434a554d87f7387f04077a28558db23be6
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py
@@ -23,13 +23,12 @@
import PlayerControl
import ItemControler
import NetPackCommon
import PlayerBossReborn
import PlayerFeastTravel
import PlayerFairyCeremony
import PlayerActLunhuidian
import PlayerActYunshi
import PlayerActTask
import PlayerActivity
import ItemCommon
import PlayerHero
import PyGameData
import ChConfig
import random
@@ -46,11 +45,6 @@
TreasureType_HeroComm = 11 # 英雄招募 - 普通
TreasureType_HeroHigh = 12 # 英雄招募 - 高级
TreasureType_HeroScore = 13 # 英雄招募 - 积分
def DoTreasureOpen(curPlayer):
    ## 寻宝开启
    Sync_TreasureInfo(curPlayer)
    return
def OnTreasureLogin(curPlayer):
    Sync_TreasureInfo(curPlayer)
@@ -84,6 +78,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)
@@ -219,19 +214,16 @@
        GameWorld.ErrLog("找不到该等级对应寻宝库配置!treasureType=%s,curLV=%s" % (treasureType, curPlayer.GetLV()), playerID)
        return
    
    luckyItemRateList = ipyData.GetLuckyItemRateList()
    luckyGridNumList = []
    if luckyItemRateList:
        for _, gridNum in luckyItemRateList:
            luckyGridNumList.append(gridNum)
    elif setIpyData.GetLuckyGridNum():
        luckyGridNumList = [setIpyData.GetLuckyGridNum()]
    GameWorld.DebugLog("luckyGridNumList=%s, %s" % (luckyGridNumList, luckyItemRateList), playerID)
    setLuckyGridNum = setIpyData.GetLuckyGridNum() # 标的格子
    luckyItemRateInfo = ipyData.GetLuckyItemRateInfo()
    luckyItemRateDict = {int(k):v for k, v in luckyItemRateInfo.items()}
    luckyValueList = sorted(luckyItemRateDict.keys())
    luckyGridNumList = [] # 幸运格子编号列表
    luckFormula = setIpyData.GetLuckyRateFormat() # 幸运物品概率公式
    addLuck = setIpyData.GetOnceLucky() # 增加幸运值
    maxLuck = setIpyData.GetFullLucky() # 满幸运值
    curLuck = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureLuck % (treasureType)) # 当前幸运值
    updLuck = curLuck
    maxLuck = max(luckyValueList) if luckyValueList else 0 # 满幸运值
    updLuck = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureLuck % (treasureType)) # 当前幸运值
    GameWorld.DebugLog("updLuck=%s,maxLuck=%s,setLuckyGridNum=%s,luckyItemRateDict=%s" % (updLuck, maxLuck, setLuckyGridNum, luckyItemRateDict), playerID)
    
    curTreasureCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreasureCount % (treasureType)) # 当前已寻宝次数
    updTreasureCount = curTreasureCount
@@ -249,46 +241,69 @@
        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
    rateByIndexCount = 0 # 第x次x抽必出可产出个数
    rateByIndexCountList = []
    if curIndexCount <= maxIndexCount and curIndexCount in beSureCountByIndexDict:
        rateByIndexCountList = [[10000, beSureCountByIndexDict[curIndexCount]]]
        rateByIndexCount = 1 # 可扩展支持产出多个,暂定单次抽奖仅定制产出1个
    # 单抽产出优先级: 幸运物品 > 必出 > 保底 > 普通
    # 连抽没有优先级限制,只要满足条件即可产出
    getGridResult = []
    for tIndex in range(treasureCount):
        updLuck = min(updLuck + addLuck, maxLuck)
        stageLuck, luckItemRateList = __getLuckyRateInfo(updLuck, luckyItemRateDict, luckyValueList)
        luckyGridNumList = []
        for _, gridNum in luckItemRateList:
            luckyGridNumList.append(gridNum)
        updTreasureCount += 1
        GameWorld.DebugLog("%s,累计次数=%s,幸运=%s" % (tIndex + 1, updTreasureCount, updLuck), playerID)
        GameWorld.DebugLog("%s,累计次数=%s,幸运=%s,阶段幸运=%s,幸运饼图=%s" % (tIndex + 1, updTreasureCount, updLuck, stageLuck, luckItemRateList), playerID)
        if gridNumMaxLimitInfo:
            GameWorld.DebugLog("    gridNumMaxLimitInfo=%s,gridNumCountInfo=%s" % (gridNumMaxLimitInfo, gridNumCountInfo), playerID)
        baseRateList, commItemRateList = GetUpdLuckyItemRateList(ipyData, luckyGridNumList, updLuck, luckFormula, costType) # 常规产出物品格子饼图,幸运物品概率已变更
        commItemRateList = GetRemoveLimitGridRateList(commItemRateList, gridNumCountInfo, gridNumMaxLimitInfo)        
        GameWorld.DebugLog("    基础饼图=%s" % baseRateList, playerID)
        GameWorld.DebugLog("    常规饼图=%s" % commItemRateList, playerID)
        GameWorld.DebugLog("    基础产出饼图=%s" % baseRateList, playerID)
        
        curRateList = [] # 可能会改变饼图,每次抽奖使用新的饼图对象,不要改变配置的饼图概率
        
        # 满幸运必出
        if maxLuck and updLuck >= maxLuck and luckyGridNumList:
            if luckyItemRateList:
                curRateList = GetRemoveLimitGridRateList(luckyItemRateList, gridNumCountInfo, gridNumMaxLimitInfo)
            else:
                curRateList = GetRemoveLimitGridRateList([(10000, luckyGridNumList[0])], gridNumCountInfo, gridNumMaxLimitInfo)
            GameWorld.DebugLog("    【满幸运饼图】: %s" % curRateList)
        if stageLuck and updLuck >= stageLuck and luckItemRateList:
            curRateList = GetRemoveLimitGridRateList(luckItemRateList, gridNumCountInfo, gridNumMaxLimitInfo)
            GameWorld.DebugLog("    【满幸运必出饼图】: %s" % curRateList, playerID)
            
        # 次数必出
        if not curRateList and updTreasureCount in beSureCountDict:
            besureGridRateList = beSureCountDict[updTreasureCount]
            curRateList = GetRemoveLimitGridRateList(besureGridRateList, gridNumCountInfo, gridNumMaxLimitInfo)
            GameWorld.DebugLog("    【第%s次数必出饼图】: %s" % (updTreasureCount, curRateList))
            GameWorld.DebugLog("    【第%s次数必出饼图】: %s" % (updTreasureCount, curRateList), playerID)
            
        # 满次数必出
        if not curRateList and ensureCount and updTreasureCount % ensureCount == 0 and ensureRateList:
            curRateList = GetRemoveLimitGridRateList(ensureRateList, gridNumCountInfo, gridNumMaxLimitInfo)
            GameWorld.DebugLog("    【满%s次数必出饼图】: %s" % (ensureCount, curRateList))
            GameWorld.DebugLog("    【满%s次数必出饼图】: %s" % (ensureCount, curRateList), playerID)
        # 第x次x抽必出,优先级较低
        if not curRateList and rateByIndexCountList and rateByIndexCount > 0:
            rateByIndexCount -= 1
            curRateList = rateByIndexCountList
            GameWorld.DebugLog("    【第x次x抽必出】: treasureIndex=%s,curIndexCount=%s,rateByIndexCount=%s,%s"
                               % (treasureIndex, curIndexCount, rateByIndexCount, rateByIndexCountList), playerID)
            
        doCount = 0
        while doCount <= 50: # 限制最大次数
            doCount += 1
            if doCount > 1 or not curRateList: # 重新随机的默认使用常规饼图
                curRateList = commItemRateList
                GameWorld.DebugLog("    使用常规饼图=%s" % curRateList, playerID)
                
            gridNum = GameWorld.GetResultByRandomList(curRateList)
            if gridNum in luckyGridNumList and gridNum in getGridResult:
@@ -303,8 +318,11 @@
            getGridResult.append(gridNum)
            GameWorld.DebugLog("    本次产出: gridNum=%s, %s" % (gridNum, getGridResult), playerID)
            if gridNum in luckyGridNumList:
                updLuck = 0
                GameWorld.DebugLog("    【产出幸运格子】: gridNum=%s" % (gridNum), playerID)
                if gridNum == setLuckyGridNum or updLuck >= maxLuck:
                    updLuck = 0
                else:
                    updLuck = stageLuck # 直接切换到下一阶段幸运
                GameWorld.DebugLog("    【产出幸运格子】: gridNum=%s,updLuck=%s" % (gridNum, updLuck), playerID)
            if gridNum in gridNumCountInfo:
                gridNumCountInfo[gridNum] = gridNumCountInfo[gridNum] + 1
                GameWorld.DebugLog("    【更新产出次数】: gridNum=%s, %s" % (gridNum, gridNumCountInfo), playerID)
@@ -337,9 +355,7 @@
                canRandItemList = []
                randItemIDList = randItemIDDict[itemID]
                for randItemID in randItemIDList:
                    itemData = GameWorld.GetGameData().GetItemByTypeID(randItemID)
                    if itemData.GetType() == ChConfig.Def_ItemType_Rune and not PlayerRune.GetIsOpenByRuneID(curPlayer, randItemID):
                        GameWorld.DebugLog("未解锁的符印不产出!itemID=%s,randItemID=%s" % (itemID, randItemID), playerID)
                    if not __checkItemCanTreasure(curPlayer, treasureType, randItemID):
                        continue
                    canRandItemList.append(randItemID)
                if not canRandItemList:
@@ -356,8 +372,9 @@
            itemWeightList = []
            for libItem in libItemList:
                itemWeight, itemID, itemCount = libItem.GetItemWeight(), libItem.GetItemID(), libItem.GetItemCount()
                itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
                if not itemData:
                if not itemWeight:
                    continue
                if not __checkItemCanTreasure(curPlayer, treasureType, itemID):
                    continue
                itemWeightList.append([itemWeight, [itemID, itemCount]])
            if not itemWeightList:
@@ -369,7 +386,8 @@
            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:
@@ -389,46 +407,45 @@
    # 加数据
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCountToday % (treasureType), updTreasureCountToday)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TreasureCount % (treasureType), updTreasureCount)
    for luckyGridNum in luckyGridNumList:
        if luckyGridNum in getGridResult:
            updLuck = 0
            break
    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))
        
    addScoreType = setIpyData.GetAwardMoneyType() # 额外奖励货币类型
    addScore = setIpyData.GetAwardMoneyValue() # 单次奖励货币数
    if addScoreType and addScore:
        PlayerControl.GiveMoney(curPlayer, addScoreType, addScore * treasureCount)
        
    if treasureType == TreasureType_Rune:
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RuneTreasure, treasureCount)
        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:
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_Treasure, treasureCount)
        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:
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_JSTreasure, treasureCount)
        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_GatherTheSoul:
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_TreasureGatherTheSoul, treasureCount)
    elif treasureType == TreasureType_Gubao:
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_TreasureGubao, treasureCount)
    if treasureType in [TreasureType_HeroComm, TreasureType_HeroHigh, TreasureType_HeroScore]:
        PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_HeroCall, 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)
        
    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:
@@ -438,11 +455,15 @@
            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)
    
@@ -459,6 +480,37 @@
    Sync_TreasureInfo(curPlayer, [treasureType])
    return
def __getLuckyRateInfo(curLuck, luckyItemRateDict, luckyValueList):
    if not luckyItemRateDict or not luckyValueList:
        return 0, []
    for luck in luckyValueList:
        if curLuck <= luck:
            return luck, luckyItemRateDict[luck]
    lastLuck = luckyValueList[-1]
    return lastLuck, luckyItemRateDict[lastLuck]
def __checkItemCanTreasure(curPlayer, treasureType, itemID):
    ## 检查物品ID是否可寻宝产出
    itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
    if not itemData:
        return
    playerID = curPlayer.GetPlayerID()
    if itemData.GetType() == ChConfig.Def_ItemType_Hero:
        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", itemID)
        if not heroIpyData:
            return
        if heroIpyData.GetRecruitBySelf() and not PlayerHero.GetHeroActivite(curPlayer, itemID):
            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)
            return
    return True
def GetRemoveLimitGridRateList(srcGridNumRateList, gridNumCountInfo, gridNumMaxLimitInfo):
    ## 获取移除限制产出的格子后的饼图列表
    # @param srcGridNumRateList: 原始概率 [(概率, 格子编号), ...]