From 8a5cd920235eefda418bba0e949ba522cab72a4c Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 11 八月 2022 16:18:29 +0800
Subject: [PATCH] 9685 【后台】开服时间整合(清档完毕后入库存档)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Chests.py |  185 ++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 155 insertions(+), 30 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Chests.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Chests.py
index 199fcec..c8b0ebe 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Chests.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_Chests.py
@@ -23,9 +23,12 @@
 import IPY_GameWorld
 import ItemControler
 import PlayerRune
+import NPCCommon
 import ChConfig
+import ChEquip
 import ChItem
 
+import random
 import math
 #---------------------------------------------------------------------
 
@@ -38,13 +41,16 @@
         return
     
     showType = chestsIpyData.GetShowType() # 规定有开箱表现的默认只能开启1个
-    if showType:
-        useCnt = 1
-        
-    isBind = int(curRoleItem.GetIsBind() or chestsIpyData.GetIsBind()) # 奖励物品是否绑定
+    #if showType:
+    #    useCnt = 1
+    useCnt = min(curRoleItem.GetCount(), useCnt)
+    
+    isBind = int(chestsIpyData.GetIsBind()) # 奖励物品是否绑定
     costItemID = chestsIpyData.GetCostItemID()
     costItemCountTotal = chestsIpyData.GetCostItemCount() * useCnt
     costGoldTotal = chestsIpyData.GetCostGold() * useCnt
+    auctionItemCanSell = chestsIpyData.GetAucionItemCanSell()
+    aucionItemDiffSellIDList = chestsIpyData.GetAucionItemDiffSellIDList()
     
     if costGoldTotal and not PlayerControl.HaveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGoldTotal):
         return
@@ -62,15 +68,15 @@
     awardInfo = GetChestsAwardInfo(curPlayer, chestsItemID, useCnt, exData)
     if not awardInfo:
         return
-    needSpaceMax, needSpaceDict, jobAwardItemDict, moneyType, moneyCount, notifyItemList = awardInfo
-    GameWorld.DebugLog("    needSpaceDict=%s,jobAwardItemDict=%s,moneyType=%s,moneyCount=%s,notifyItemList=%s" 
-                       % (needSpaceDict, jobAwardItemDict, moneyType, moneyCount, notifyItemList))
+    needSpaceDict, jobAwardItemList, moneyType, moneyCount, notifyItemList, updOpenCount = awardInfo
+    GameWorld.DebugLog("    needSpaceDict=%s,jobAwardItemList=%s,moneyType=%s,moneyCount=%s,notifyItemList=%s,updOpenCount=%s,auctionItemCanSell=%s,aucionItemDiffSellIDList=%s" 
+                       % (needSpaceDict, jobAwardItemList, moneyType, moneyCount, notifyItemList, updOpenCount, auctionItemCanSell, aucionItemDiffSellIDList))
     
     for packType, needSpace in needSpaceDict.items():
         packSpace = ItemCommon.GetItemPackSpace(curPlayer, packType, needSpace)
         if packSpace < needSpace:
             #PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_676165", [packType])
-            PlayerControl.NotifyCode(curPlayer, "OpenBoxItem", [packType, chestsItemID, needSpaceMax - packSpace])
+            PlayerControl.NotifyCode(curPlayer, "OpenBoxItem", [packType, chestsItemID, needSpace - packSpace])
             return
         
     # 扣除消耗
@@ -80,13 +86,20 @@
         infoDict = {ChConfig.Def_Cost_Reason_SonKey:chestsItemID}
         PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGoldTotal, ChConfig.Def_Cost_UseItem, infoDict)
         
-    saveDataDict = {"AwardItem":jobAwardItemDict}
+    # 更新开启次数
+    if updOpenCount:
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ChestsOpenCount % chestsItemID, updOpenCount)
+        GameWorld.DebugLog("    更新宝箱开启次数: %s" % updOpenCount)
+        
+    saveDataDict = {"AwardItem":jobAwardItemList}
     ItemCommon.DelItem(curPlayer, curRoleItem, useCnt, True, ChConfig.ItemDel_Chests, saveDataDict)
     
     # 给奖励
     syncItemList = []
-    for itemID, itemCount in jobAwardItemDict.items():
-        curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isBind)
+    for itemID, itemCount in jobAwardItemList:
+        canSell = (not auctionItemCanSell) if itemID in aucionItemDiffSellIDList else auctionItemCanSell
+        isAuctionItem = 1 if canSell and IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", itemID) else 0
+        curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isAuctionItem, curPlayer=curPlayer)
         if not curItem:
             GameWorld.ErrLog("宝箱创建奖励物品异常!chestsItemID=%s,useCnt=%s,itemID=%s,itemCount=%s,isBind=%s" 
                              % (chestsItemID, useCnt, itemID, itemCount, isBind), curPlayer.GetPlayerID())
@@ -115,14 +128,13 @@
 def GetChestsAwardInfo(curPlayer, chestsItemID, useCount, exData=0):
     '''获取宝箱开启奖励
     @return: None - 获取宝箱奖励失败
-    @return: needSpaceMax, needSpaceDict, jobAwardItemDict{itemID:itemCount, ...}
+    @return: needSpaceDict, jobAwardItemList [[itemID, itemCount], ...]
     '''
     
     awardIpyData = __GetChestsAwardIpyDataByLV(curPlayer, chestsItemID)
     if not awardIpyData:
         return
     
-    needSpaceMax = 0
     awardItemDict = {}
     job = curPlayer.GetJob()
     jobItemList = awardIpyData.GetJobItemList()
@@ -147,33 +159,67 @@
         if not isSelectOK:
             GameWorld.ErrLog("选择的物品错误, 该宝箱没有该物品!chestsItemID=%s,selectItemID=%s" % (chestsItemID, selectItemID))
             return
-        needSpaceMax += 1
         
     # 固定产出物品
     if awardIpyData.GetFixedItemDict():
         for itemID, itemCount in awardIpyData.GetFixedItemDict().items():
-            needSpaceMax += 1
             __AddAwardItem(awardItemDict, itemID, itemCount * useCount)
             
     # 随机物品库1
     if awardIpyData.GetRandItemList1() and awardIpyData.GetRandTimeList1():
         if not __AddChestsRandAwardItem(curPlayer, chestsItemID, useCount, awardItemDict, awardIpyData.GetRandItemList1(), awardIpyData.GetRandTimeList1()):
             return
-        needSpaceMax += __GetMaxRandTime(awardIpyData.GetRandTimeList1())
+        
+    # 根据宝箱开启次数特殊产出
+    updOpenCount = 0
+    randItemList2DoCount = useCount
+    randItemByUseCountDict = awardIpyData.GetRandItemByUseCount()
+    if randItemByUseCountDict:
+        maxOpenCount = max(randItemByUseCountDict)
+        hisOpenCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ChestsOpenCount % chestsItemID)
+        if hisOpenCount < maxOpenCount:
+            updOpenCount = min(hisOpenCount + useCount, maxOpenCount)
+            for specUseCount, randItemList in randItemByUseCountDict.items():
+                if not (hisOpenCount < specUseCount <= updOpenCount):
+                    GameWorld.DebugLog("    不满足特殊次数产出: hisOpenCount=%s,specUseCount=%s,updOpenCount=%s" 
+                                       % (hisOpenCount, specUseCount, updOpenCount))
+                    continue
+                randItemList2DoCount -= 1
+                randItemInfo = GameWorld.GetResultByRandomList(randItemList)
+                GameWorld.DebugLog("    根据开启次数特殊产出: specUseCount=%s, %s, randItemList2DoCount=%s" 
+                                   % (specUseCount, randItemInfo, randItemList2DoCount))
+                if not randItemInfo:
+                    continue
+                if len(randItemInfo) != 2:
+                    GameWorld.ErrLog("宝箱开启次数特殊产出随机库配置错误!chestsItemID=%s" % chestsItemID)
+                    return
+                itemID, itemCount = randItemInfo
+                if not itemID:
+                    continue
+                __AddAwardItem(awardItemDict, itemID, itemCount)
+            
+    if randItemList2DoCount != useCount:
+        GameWorld.DebugLog("    随机物品库2执行次数: %s" % (randItemList2DoCount))
         
     # 随机物品库2
-    if awardIpyData.GetRandItemList2() and awardIpyData.GetRandTimeList2():
-        if not __AddChestsRandAwardItem(curPlayer, chestsItemID, useCount, awardItemDict, awardIpyData.GetRandItemList2(), awardIpyData.GetRandTimeList2()):
+    if awardIpyData.GetRandItemList2() and awardIpyData.GetRandTimeList2() and randItemList2DoCount:
+        if not __AddChestsRandAwardItem(curPlayer, chestsItemID, randItemList2DoCount, awardItemDict, awardIpyData.GetRandItemList2(), awardIpyData.GetRandTimeList2()):
             return
-        needSpaceMax += __GetMaxRandTime(awardIpyData.GetRandTimeList2())
+        
+    # 装备库
+    if awardIpyData.GetPieRateDrop() or awardIpyData.GetIndepRateDrop():
+        if not __AddChestsEquipItem(curPlayer, chestsItemID, useCount, awardItemDict, awardIpyData):
+            return
     
     # 产出特殊物品广播
     needNotifyItemList = awardIpyData.GetNeedNotifyItemList()
     
     needSpaceDict = {} # {packType:needSpace, ...}
     notifyItemList = []
-    jobAwardItemDict = {}
+    jobAwardItemList = []
     for itemID, itemCount in awardItemDict.items():
+        if not itemCount:
+            continue
         jobItemID = __GetChestsJobItem(chestsItemID, job, itemID, jobItemList)
         if not jobItemID:
             return
@@ -182,15 +228,19 @@
         if not itemData:
             GameWorld.ErrLog("宝箱奖励物品不存在! chestsItemID=%s,itemID=%s,jobItemID=%s" % (chestsItemID, itemID, jobItemID))
             return
-        packType = ChConfig.GetItemPackType(itemData.GetType())
+        packType = ChConfig.GetItemPackType(itemData)
         needSpace = int(math.ceil(itemCount / float(itemData.GetPackCount())))
         needSpaceDict[packType] = needSpaceDict.get(packType, 0) + needSpace
         
-        jobAwardItemDict[jobItemID] = itemCount
+        # 装备拆开给,需要同步每件装备的属性
+        if ItemCommon.GetIsEquip(itemData):
+            jobAwardItemList.extend([[jobItemID, 1]] * itemCount)
+        else:
+            jobAwardItemList.append([jobItemID, itemCount])
         if itemID in needNotifyItemList or jobItemID in needNotifyItemList:
             notifyItemList.append(jobItemID)
             
-    return needSpaceMax, needSpaceDict, jobAwardItemDict, awardIpyData.GetMoneyType(), awardIpyData.GetMoneyCount() * useCount, notifyItemList
+    return needSpaceDict, jobAwardItemList, awardIpyData.GetMoneyType(), awardIpyData.GetMoneyCount() * useCount, notifyItemList, updOpenCount
 
 def __GetMaxRandTime(randTimeList):
     if len(randTimeList) == 1 and type(randTimeList[0]) == int:
@@ -210,6 +260,7 @@
             itemID = itemInfo[0] # 有配置物品ID,需判断该物品ID是否合法可开出等,支持配置空物品ID
             itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
             if not itemData:
+                GameWorld.ErrLog("宝箱奖励物品不存在! chestsItemID=%s,itemID=%s" % (chestsItemID, itemID))
                 return False
             
             # 符印判断是否已经解锁
@@ -252,6 +303,73 @@
             
     return True
 
+def __AddChestsEquipItem(curPlayer, chestsItemID, useCount, awardItemDict, awardIpyData):
+    ## 获取宝箱装备库产出
+    
+    dropEquipInfoList = []
+    itemJobList = [curPlayer.GetJob()] if awardIpyData.GetIsDropJobSelf() else IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1) # 掉落装备职业列表
+    
+    # 饼图概率随机装备
+    pieRateDoCnt = awardIpyData.GetPieRateDoCnt() * useCount
+    pieRateDropList = awardIpyData.GetPieRateDrop()  # 饼图概率掉落信息 [(概率,0),(概率,(阶,颜色)),...]
+    for _ in xrange(pieRateDoCnt):
+        dropInfo = GameWorld.GetResultByRandomList(pieRateDropList)
+        if dropInfo:
+            dropEquipInfoList.append(dropInfo)
+    GameWorld.DebugLog("饼图装备掉落结果: pieRateDoCnt=%s, %s" % (pieRateDoCnt, dropEquipInfoList))
+    
+    # 独立概率随机装备
+    Def_NPCMaxDropRate = NPCCommon.Def_NPCMaxDropRate
+    indepRateDict = awardIpyData.GetIndepRateDrop() # 独立概率掉落信息 {(阶,颜色):概率,...}
+    for _ in xrange(useCount):
+        for dropInfo, rate in indepRateDict.iteritems():
+            dropRate = rate
+            mustDropCount = dropRate / Def_NPCMaxDropRate
+            dropRate = dropRate % Def_NPCMaxDropRate # 基础概率
+            GameWorld.DebugLog("    dropInfo=%s,rate=%s,mustDropCount=%s,dropRate=%s" % (dropInfo, rate, mustDropCount, dropRate))
+            curDropCount = mustDropCount
+            if GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):
+                curDropCount += 1
+            if not curDropCount:
+                continue
+            
+            for _ in xrange(curDropCount):
+                dropEquipInfoList.append(dropInfo)
+                
+    GameWorld.DebugLog("装备库产出: dropEquipInfoList=%s" % dropEquipInfoList)
+    
+    colorSuitRateDict = awardIpyData.GetEquipColorSuitInfo() # 装备颜色对应套装概率 {颜色:套装概率, ...}
+    colorSuitPlaceKeyInfoDict = awardIpyData.GetEquipPartKeyRateInfo() # 装备部位集合信息 {(颜色,是否套装):部位集合key, ...}
+    for classLV, color in dropEquipInfoList:
+        isSuit = 0
+        if color in colorSuitRateDict:
+            suitRate = colorSuitRateDict[color]
+            isSuit = GameWorld.CanHappen(suitRate, maxRate=Def_NPCMaxDropRate)
+        colorSuitKey = (color, isSuit)
+        if colorSuitKey not in colorSuitPlaceKeyInfoDict:
+            GameWorld.ErrLog("未配置颜色套装对应部位集合key! chestsItemID=%s,color=%s,isSuit=%s" % (chestsItemID, color, isSuit))
+            continue
+        placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey]
+        jobList = itemJobList
+        placeList = NPCCommon.GetEquipPlaceByPlaceKey(placeKey)
+        if not placeList:
+            GameWorld.ErrLog("部位集合key不存在!chestsItemID=%s,placeKey=%s" % (chestsItemID, placeKey))
+            continue
+        # 未指定,默认取当前解锁的最大境界装备阶
+        if classLV == 0:
+            classLV = ChEquip.GetPlayerMaxEquipClassLV(curPlayer)
+            GameWorld.DebugLog("    未指定装备阶,默认取玩家当前解锁的最大阶: classLV=%s" % classLV)
+            
+        randEquipIDList = NPCCommon.__GetEquipIDList(chestsItemID, classLV, color, isSuit, placeList, itemJobList, findType="ChestsItem")
+        if not randEquipIDList:
+            continue
+        randItemID = random.choice(randEquipIDList)
+        __AddAwardItem(awardItemDict, randItemID, 1)
+        GameWorld.DebugLog("开出装备: chestsItemID=%s,itemID=%s,classLV=%s,color=%s,isSuit=%s,placeKey=%s,jobList=%s,randEquipIDList=%s" 
+                           % (chestsItemID, randItemID, classLV, color, isSuit, placeKey, jobList, randEquipIDList))
+        
+    return True
+
 def __GetChestsJobItem(chestsItemID, job, itemID, jobItemList):
     ## 获取宝箱物品奖励对应的职业物品, 职业从1开始
     for jobItemIDList in jobItemList:
@@ -281,19 +399,26 @@
     # 多条产出记录的,按等级来
     lvIpyDataList = []
     for ipyData in awardIpyDataList:
-        lvIpyDataList.append([ipyData.GetAwardLV(), ipyData])
+        lvIpyDataList.append([ipyData.GetRealmLV(), ipyData.GetAwardLV(), ipyData])
     lvIpyDataList.sort() # 升序排序
     
     curLV = curPlayer.GetLV()
-    minLV = lvIpyDataList[0][0]
+    curRealmLV = curPlayer.GetOfficialRank()
+    minRealmLV, minLV = lvIpyDataList[0][0], lvIpyDataList[0][1]
     if curLV < minLV:
-        GameWorld.ErrLog("当前等级无法开启该宝箱!curLV=%s,minLV=%s,chestsItemID=%s" % (curLV, minLV, chestsItemID), curPlayer.GetPlayerID())
+        GameWorld.ErrLog("当前等级无法开启该宝箱!curLV=%s < minLV=%s,chestsItemID=%s" % (curLV, minLV, chestsItemID), curPlayer.GetPlayerID())
+        return
+    if curRealmLV < minRealmLV:
+        GameWorld.ErrLog("当前境界无法开启该宝箱!curRealmLV=%s < minRealmLV=%s,chestsItemID=%s" % (curRealmLV, minRealmLV, chestsItemID), curPlayer.GetPlayerID())
         return
     
     for i, lvIpyInfo in enumerate(lvIpyDataList[1:], 1):
-        awardLV, ipyData = lvIpyInfo
-        if curLV < awardLV:
-            awardLV, ipyData = lvIpyDataList[i - 1]
-            return ipyData
+        realmLV, awardLV, ipyData = lvIpyInfo
+        if realmLV: # 境界优先,二选一
+            if curRealmLV < realmLV:
+                return lvIpyDataList[i - 1][-1]
+        else:
+            if curLV < awardLV:
+                return lvIpyDataList[i - 1][-1]
     return awardIpyDataList[-1]
 

--
Gitblit v1.8.0