hxp
2025-10-22 5925409bdea13d819e4e4356a51043de5f3f9bd8
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTreasure.py
@@ -17,27 +17,21 @@
import GameWorld
import PlayerRune
import ShareDefine
import GameFuncComm
import IpyGameDataPY
import IPY_GameWorld
import FormulaControl
import ChPyNetSendPack
import PlayerControl
import ItemControler
import NetPackCommon
import PlayerBossReborn
import PlayerFeastTravel
import PlayerFairyCeremony
import PlayerNewFairyCeremony
import PlayerActLunhuidian
import PlayerActYunshi
import PlayerActTask
import PlayerActivity
import ItemCommon
import PlayerHero
import PyGameData
import ChConfig
import random
import time
# 寻宝类型: >=100的为策划自行配置的自定义寻宝类型,<100的用于指定系统寻宝功能
TreasureTypeList = (
@@ -48,14 +42,11 @@
TreasureType_Gubao, # 古宝寻宝 5
) = range(1, 1 + 5)
def DoTreasureOpen(curPlayer):
    ## 寻宝开启
    Sync_TreasureInfo(curPlayer)
    return
TreasureType_HeroComm = 11 # 英雄招募 - 普通
TreasureType_HeroHigh = 12 # 英雄招募 - 高级
TreasureType_HeroScore = 13 # 英雄招募 - 积分
def OnTreasureLogin(curPlayer):
    #if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Treasure):
    #    return
    Sync_TreasureInfo(curPlayer)
    return
@@ -87,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)
@@ -222,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
@@ -252,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 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:
@@ -306,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)
@@ -340,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:
@@ -359,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:
@@ -372,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:
@@ -392,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)
        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:
@@ -441,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)
    
@@ -462,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: 原始概率 [(概率, 格子编号), ...]