From 84ede803777ff10b5cbe93b1ec0168af08f55d5e Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 13 一月 2021 18:11:26 +0800
Subject: [PATCH] 8677 【BT】【后端】跨服冲榜活动; 新增跨服活动时间管理模块、跨服榜单;跨服邮件;跨服广播优化;相关GM命令、后台工具;

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipStar.py |  334 +++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 234 insertions(+), 100 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipStar.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipStar.py
index 43e26d5..d664808 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipStar.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/Operate_EquipStar.py
@@ -22,16 +22,20 @@
 import PlayerControl
 import IPY_GameWorld
 import DataRecordPack
+import PlayerAuctionHouse
 import IpyGameDataPY
+import PlayerSuccess
 import GameWorld
 import EventShell
 import ChConfig
 import ChEquip
+
+import math
 #-------------------------------------------------------------------------------------------
 
 
-#===============================================================================
 #// A5 C5 装备部位升星 #tagCMEquipPartStarUp
+#
 #struct    tagCMEquipPartStarUp
 #{
 #    tagHead        Head;
@@ -39,13 +43,8 @@
 #    BYTE    CostEquipCnt;    // 装备个数
 #    WORD    CostEquipIndex[CostEquipCnt];    // 装备索引
 #    DWORD    CostEquipID[CostEquipCnt];    // 装备物品ID
+#    BYTE    AutoBuy;        // 自动购买 0-不自动购买,1-自动购买并升星,2-自动购买预览(未满概率时预览消耗时使用)
 #};
-#===============================================================================
-## 部位升星
-#  @param playerIndex: 玩家
-#  @param clientData: 封包
-#  @param tick: 当前时间
-#  @return None
 def OnEquipPartStarUp(playerIndex, clientData, tick):    
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
     playerID = curPlayer.GetPlayerID()
@@ -66,9 +65,9 @@
         return
     
     # 当前装备等级是否到达最高等级
-    curPack = curPlayer.GetItemManager().GetPack(packType)
-    curEquip = curPack.GetAt(equipPackIndex)
-    if not curEquip or curEquip.IsEmpty():
+    equipPack = curPlayer.GetItemManager().GetPack(packType)
+    curEquip = equipPack.GetAt(equipPackIndex)
+    if not ItemCommon.CheckItemCanUse(curEquip):
         GameWorld.DebugLog("OnEquipPartStarUp() equip is empty")
         return
     
@@ -77,101 +76,94 @@
     if curPartStar >= maxStar:
         GameWorld.Log("OnEquipPartStarUp:curPartStar(%s) >= maxStar(%s)" % (curPartStar, maxStar), playerID)
         return
-
-    # 升星处理
-    result = DoLogic_EquipStarUp(curPlayer, classLV, equipPlace, curPartStar, equipPackIndex, clientData)
-    if result == ChConfig.Def_ComposeState_None:
-        return
-    updPartStar = ChEquip.GetEquipPartStar(curPlayer, equipPackIndex)
-    GameWorld.DebugLog("   装备升星 equipPackIndex=%s result=%s,curPartStar=%s,updPartStar=%s" % (equipPackIndex, result, curPartStar, updPartStar), playerID)
-    if result == ChConfig.Def_ComposeState_Sucess:
-        # 星级变更时处理
-        #刷新属性
-        ChEquip.RefreshPlayerEquipAttribute(curPlayer, classLV)
-        playControl = PlayerControl.PlayerControl(curPlayer)
-        playControl.RefreshPlayerAttrState()
-  
-        if updPartStar in IpyGameDataPY.GetFuncEvalCfg('EquipPartStarNotify'):
-            itemID = curEquip.GetItemTypeID()
-            userData = curEquip.GetUserData()
-            guid = ItemCommon.CacheNotifyEquipDetailInfo(curPlayer, curEquip)
-            msgParamList = [curPlayer.GetPlayerName(), itemID, userData, guid, updPartStar]
-            PlayerControl.WorldNotify(0, "StarLevelUp", msgParamList)
-        EventShell.EventRespons_EquipStarUp(curPlayer)
-    return
-     
-
-## 开始装备升星
-#  @param index 为装备位
-#  @return 
-def DoLogic_EquipStarUp(curPlayer, classLV, equipPlace, curPartStar, equipPackIndex, clientData):
-    result = ChConfig.Def_ComposeState_None
-    nextStar = curPartStar + 1
-    ipyData = IpyGameDataPY.GetIpyGameData("EquipStarUp", classLV, equipPlace, nextStar)
-    if not ipyData:
-        return result
     
-    costEquipCnt = ipyData.GetCostEquipCnt()
-    if clientData.CostEquipCnt < costEquipCnt:
-        GameWorld.DebugLog(' 开始装备升星,装备材料不足 %s' % costEquipCnt)
-        return result
-    costEquipPlaceList = ipyData.GetCostEquipPlace()
-    costEquipColorList = ipyData.GetCostEquipColor()
-    isJobLimit = ipyData.GetIsJobLimit()
-    suitTotalRate = ipyData.GetSuitTotalRate()
     itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
-    delEquipIndexList = []
-    totalEquipStars = ChEquip.GetTotalEquipStars(curPlayer)
+    costEquipIndexList = clientData.CostEquipIndex
+    costEquipIDList = clientData.CostEquipID
+    autoBuy = clientData.AutoBuy
     
-    if not costEquipCnt:
-        curRate = 100
-    else:
-        curRate = 0 #成功概率
+    checkCostResult = __CheckCostInfo(curPlayer, classLV, equipPlace, curPartStar, costEquipIndexList, costEquipIDList, itemPack, autoBuy)
+    if not checkCostResult:
+        return
+    curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney = checkCostResult
+    
+    if autoBuy:
+        isAutoBuyPreview = autoBuy == 2
+        # 概率未满 且 自动购买, 则需要执行拍卖行购买装备
+        if curRate < 100:
+            playerGoldPaper = curPlayer.GetGoldPaper()
+            queryData = [classLV, equipPlace, curPartStar, equipPackIndex, isAutoBuyPreview, curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney, playerGoldPaper]
+            PlayerAuctionHouse.QueryGameServer_AuctionHouse(playerID, "EquipStarAutoBuy", queryData)
+            return
         
-        for i, index in enumerate(clientData.CostEquipIndex):
-            costEquip = itemPack.GetAt(index)
-            if not costEquip or costEquip.IsEmpty():
-                return result
-            equipID = costEquip.GetItemTypeID()
-            if equipID != clientData.CostEquipID[i]:
-                GameWorld.ErrLog('   装备升星 客户端发的物品索引与实际物品ID不对应  index=%s,eatItemID=%s,wantEatItemID=%s' % (index, equipID, clientData.CostEquipID[i]))
-                return result
-            itemColor = costEquip.GetItemColor()
-            equipPlace = costEquip.GetEquipPlace()
-            if itemColor not in costEquipColorList:
-                return result
-            if equipPlace not in costEquipPlaceList:
-                return result
-            if isJobLimit and not ItemCommon.CheckJob(curPlayer, costEquip):
-                return result
-            delEquipIndexList.append(index)
-            isSuite = 1 if costEquip.GetSuiteID() else 0
-            
-            ipyData = IpyGameDataPY.GetIpyGameData('EquipStarUpRate', ItemCommon.GetItemClassLV(costEquip), 
-                                                   itemColor, equipPlace, isSuite
-                                                   )
-            if not ipyData:
+        if lackItemCostMoney:
+            if isAutoBuyPreview:
+                # 满概率时自动购买必要材料的,暂不处理,前端自己判断就行
                 return
-            curRate += ipyData.GetRate()
+            
+            if not PlayerControl.HaveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Paper, lackItemCostMoney):
+                GameWorld.DebugLog("自动购买必要物品货币不足,无法升星! %s" % lackItemCostMoney, playerID)
+                return
+            
+    elif lackItemCostMoney:
+        GameWorld.DebugLog("缺少必要物品,不自动购买,无法升星! %s" % lackItemCostMoney, playerID)
+        return
+    
+    # 升星处理
+    buyEquipCostMoney = 0
+    __DoEquipStarUp(curPlayer, classLV, equipPlace, curPartStar, equipPackIndex, curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney, buyEquipCostMoney)
+    return
+
+def GameServer_EquipStarAutoBuy(curPlayer, result):
+    ## GameServer自动购买拍品结果返回
+    classLV, equipPlace, curPartStar, equipPackIndex, curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney, buyEquipCostMoney = result
+    __DoEquipStarUp(curPlayer, classLV, equipPlace, curPartStar, equipPackIndex, curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney, buyEquipCostMoney)
+    return
+
+def __DoEquipStarUp(curPlayer, classLV, equipPlace, curPartStar, equipPackIndex, curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney, buyEquipCostMoney):
+    ## 执行装备部位升星
+    
+    playerID = curPlayer.GetPlayerID()
+    #自动购买货币
+    costMoneyTotal = lackItemCostMoney + buyEquipCostMoney
+    if not PlayerControl.HaveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Paper, costMoneyTotal):
+        return
+    
+    nextStar = curPartStar + 1
+    totalEquipStars = ChEquip.GetTotalEquipStars(curPlayer)
     if totalEquipStars < IpyGameDataPY.GetFuncCfg('EquipStarCustomized'):
         curRate = 100
-    if curRate <= 0:
-        GameWorld.Log('装备升星异常 概率为0!!equipPackIndex=%s'%equipPackIndex)
-        return result
     isOK = GameWorld.CanHappen(curRate, 100)
-    #判断普通物品材料 成功才扣
-    costItemDict = ipyData.GetCostItemDict()
-    if isOK and costItemDict:
-        delItemDict = {}
-        for itemID, itemCnt in costItemDict.items():
-            hasEnough, indexList, findItemIsBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(itemID, itemPack, itemCnt)
-            if not hasEnough:
-                return result
-            delItemDict[tuple(indexList)] = itemCnt
-        for itemIndexList, delCnt in delItemDict.items():
-            ItemCommon.ReduceItem(curPlayer, itemPack, itemIndexList, delCnt, True, ChConfig.ItemDel_EquipStarUp)
-    #扣装备
-    ItemCommon.ReduceItem(curPlayer, itemPack, delEquipIndexList, len(delEquipIndexList), True, ChConfig.ItemDel_EquipStarUp)
+    GameWorld.DebugLog("装备升星最终总概率: %s, isOK=%s, lackItemCostMoney=%s,buyEquipCostMoney=%s" 
+                       % (curRate, isOK, lackItemCostMoney, buyEquipCostMoney), playerID)
+    
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    #扣材料物品,因为可能还需要先到GameServer,再回MapServer扣除物品,故中间过程物品位置可能发生变化,所以这里不能直接通过index去扣物品,需要重新精确定位
+    for delItemID, delCount in delItemInfoDict.items():
+        if not delCount:
+            continue
+        hasEnough, indexList, findItemIsBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(delItemID, itemPack, delCount)
+        GameWorld.DebugLog("    扣除道具: delItemID=%s,delCount=%s,indexList=%s" % (delItemID, delCount, indexList))
+        ItemCommon.ReduceItem(curPlayer, itemPack, indexList, delCount, True, ChConfig.ItemDel_EquipStarUp)
+        
+    delItemByGUIDDict = {}
+    for index, itemGUID in delEquipGUIDDict.items():
+        delCnt = 1
+        curEquip = itemPack.GetAt(index)
+        if not ItemCommon.CheckItemCanUse(curEquip) or curEquip.GetGUID() != itemGUID:
+            delItemByGUIDDict[itemGUID] = delCnt
+            continue
+        GameWorld.DebugLog("    扣除装备: index=%s, %s" % (index, itemGUID))
+        ItemCommon.DelItem(curPlayer, curEquip, delCnt, recordName=ChConfig.ItemDel_EquipStarUp)
+    if delItemByGUIDDict:
+        GameWorld.DebugLog("    扣除装备位置错误,通过GUID补扣! %s" % delItemByGUIDDict)
+        ItemCommon.DelItemByGUID(curPlayer, itemPack, delItemByGUIDDict, recordName=ChConfig.ItemDel_EquipStarUp)
+        
+    drDict = {"PlayerID":playerID, "AccID":curPlayer.GetAccID(), "classLV":classLV, "equipPlace":equipPlace, "IsSuccess":isOK,
+              "curRate":curRate, "nextStar":nextStar, 'totalEquipStars':totalEquipStars,
+              "lackItemCostMoney":lackItemCostMoney, "buyEquipCostMoney":buyEquipCostMoney}
+    if not PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Paper, costMoneyTotal, ChConfig.Def_Cost_EquipStar, drDict):
+        return
     
     if isOK:
         ChEquip.SetEquipPartStar(curPlayer, equipPackIndex, nextStar)
@@ -180,8 +172,150 @@
     else:
         result = ChConfig.Def_ComposeState_Fail
     curPlayer.Sync_MakeItemAnswer(ShareDefine.Def_mitEquipStarUp, result)
-    drDict = {"PlayerID":curPlayer.GetPlayerID(), "AccID":curPlayer.GetAccID(), "classLV":classLV, "equipPlace":equipPlace, "IsSuccess":isOK,
-              "curRate":curRate, "nextStar":nextStar, 'totalEquipStars':totalEquipStars}
     DataRecordPack.SendEventPack("EquipStarUp", drDict, curPlayer)
-    return result
+    
+    if not isOK:
+        return
+        
+    EventShell.EventRespons_EquipStarUp(curPlayer)
+    updPartStar = ChEquip.GetEquipPartStar(curPlayer, equipPackIndex)
+    GameWorld.DebugLog("    装备升星 equipPackIndex=%s result=%s,curPartStar=%s,updPartStar=%s" % (equipPackIndex, result, curPartStar, updPartStar), playerID)
+    
+    # 成就
+    EquipStarSuccess(curPlayer, classLV)
+    
+    # 星级变更时处理
+    # 刷新属性
+    ChEquip.RefreshPlayerEquipAttribute(curPlayer, classLV)
+    playControl = PlayerControl.PlayerControl(curPlayer)
+    playControl.RefreshPlayerAttrState()
+    
+    if updPartStar in IpyGameDataPY.GetFuncEvalCfg('EquipPartStarNotify'):
+        equipPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
+        curEquip = equipPack.GetAt(equipPackIndex)
+        if ItemCommon.CheckItemCanUse(curEquip):
+            itemID = curEquip.GetItemTypeID()
+            userData = curEquip.GetUserData()
+            guid = ItemCommon.CacheNotifyEquipDetailInfo(curPlayer, curEquip)
+            msgParamList = [curPlayer.GetPlayerName(), itemID, userData, guid, updPartStar]
+            PlayerControl.WorldNotify(0, "StarLevelUp", msgParamList)
+            
+    return
+
+def __CheckCostInfo(curPlayer, classLV, equipPlace, curPartStar, costEquipIndexList, costEquipIDList, itemPack, isAutoBuy):
+    nextStar = curPartStar + 1
+    ipyData = IpyGameDataPY.GetIpyGameData("EquipStarUp", classLV, equipPlace, nextStar)
+    if not ipyData:
+        return
+    
+    costEquipCnt = ipyData.GetCostEquipCnt() # 是否消耗装备
+    costEquipPlaceList = ipyData.GetCostEquipPlace()
+    costEquipColorList = ipyData.GetCostEquipColor()
+    isJobLimit = ipyData.GetIsJobLimit()
+    delEquipGUIDDict = {}
+    totalEquipStars = ChEquip.GetTotalEquipStars(curPlayer)
+    
+    if not costEquipCnt:
+        curRate = 100 # 不用消耗装备的默认满概率
+    else:
+        curRate = 0 #成功概率
+        diffClassChangeRatePerInfo = IpyGameDataPY.GetFuncEvalCfg("EquipStarRate", 1)
+        unSuitRateRange = IpyGameDataPY.GetFuncEvalCfg("EquipStarRate", 2)
+        suitRateRange = IpyGameDataPY.GetFuncEvalCfg("EquipStarRate", 3)
+        if len(diffClassChangeRatePerInfo) != 2 or len(unSuitRateRange) != 2 or len(suitRateRange) != 2:
+            GameWorld.ErrLog('升星不同阶概率配置错误!')
+            return
+        
+        for i, index in enumerate(costEquipIndexList):
+            costEquip = itemPack.GetAt(index)
+            if not costEquip or costEquip.IsEmpty():
+                return
+            equipID = costEquip.GetItemTypeID()
+            if equipID != costEquipIDList[i]:
+                GameWorld.ErrLog('   装备升星 客户端发的物品索引与实际物品ID不对应  index=%s,eatItemID=%s,wantEatItemID=%s' % (index, equipID, costEquipIDList[i]))
+                return
+            costEquipColor = costEquip.GetItemColor()
+            costEquipPlace = costEquip.GetEquipPlace()
+            if costEquipColor not in costEquipColorList:
+                return
+            if costEquipPlace not in costEquipPlaceList:
+                return
+            if isJobLimit and not ItemCommon.CheckJob(curPlayer, costEquip):
+                return
+            
+            if costEquip.GetSuiteID():
+                baseRate = ipyData.GetSuitRate()
+                minRate, maxRate = suitRateRange
+            else:
+                baseRate = ipyData.GetUnSuitRate()
+                minRate, maxRate = unSuitRateRange
+                
+            GameWorld.DebugLog("equipID=%s,baseRate=%s,minRate=%s,maxRate=%s" % (equipID, baseRate, minRate, maxRate))
+            addRate = baseRate
+            costClassLV = ItemCommon.GetItemClassLV(costEquip)
+            
+            #吞高阶
+            if costClassLV > classLV:
+                diffClassChangeRatePer = diffClassChangeRatePerInfo[0] * (costClassLV - classLV)
+                addRate = int(math.ceil(round(baseRate * (100 + diffClassChangeRatePer) / 100.0, 2)))
+                GameWorld.DebugLog("    吞高阶 costClassLV=%s,classLV=%s,diffClassChangeRatePer=%s,addRate=%s" % (costClassLV, classLV, diffClassChangeRatePer, addRate))
+            #吞低阶
+            elif costClassLV < classLV:
+                diffClassChangeRatePer = diffClassChangeRatePerInfo[1] * (classLV - costClassLV)
+                addRate = int(math.ceil(round(baseRate * (100 - diffClassChangeRatePer) / 100.0, 2)))
+                GameWorld.DebugLog("    吞低阶 costClassLV=%s,classLV=%s,diffClassChangeRatePer=%s,addRate=%s" % (costClassLV, classLV, diffClassChangeRatePer, addRate))
+            addRate = max(minRate, min(addRate, maxRate))
+            curRate += addRate
+            GameWorld.DebugLog("    本件装备增加概率=%s,当前总概率=%s" % (addRate, curRate))
+            delEquipGUIDDict[index] = costEquip.GetGUID()
+            
+    delItemInfoDict = {}
+    lackItemCostMoney = 0
+    costItemDict = ipyData.GetCostItemDict()
+    if costItemDict:
+        for itemID, itemCnt in costItemDict.items():
+            hasEnough, indexList, findItemIsBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(itemID, itemPack, itemCnt)
+            if not hasEnough:
+                if not isAutoBuy:
+                    GameWorld.DebugLog("    缺少必要物品,不自动购买!itemID=%s,lackCnt=%s" % (itemID, lackCnt))
+                    return
+                itemGoldPaper = ItemCommon.GetShopItemPrice(itemID, IPY_GameWorld.TYPE_Price_Gold_Paper)
+                if not itemGoldPaper:
+                    GameWorld.DebugLog("    找不到物品自动购买消耗货币!itemID=%s,lackCnt=%s" % (itemID, lackCnt))
+                    return
+                lackItemCostMoney += itemGoldPaper * lackCnt
+                delCount = itemCnt - lackCnt
+                GameWorld.DebugLog("    缺少必要物品: itemID=%s,lackMoney(%s)*Count(%s)=%s" % (itemID, itemGoldPaper, lackCnt, itemGoldPaper * lackCnt))
+            else:
+                delCount = itemCnt
+            delItemInfoDict[itemID] = delCount
+            
+    if totalEquipStars < IpyGameDataPY.GetFuncCfg('EquipStarCustomized'):
+        curRate = 100
+    #if curRate <= 0:
+    #    GameWorld.ErrLog('装备升星异常 概率为0!!classLV=%s, equipPlace=%s' % (classLV, equipPlace))
+    #    return
+    if curRate >= IpyGameDataPY.GetFuncCfg("EquipStarRate", 4): # 优化高概率体验
+        curRate = 100
+        
+    return curRate, delEquipGUIDDict, delItemInfoDict, lackItemCostMoney
+
+
+def EquipStarSuccess(curPlayer, classLV):
+    ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition('EquipPlaceIndexMap', {'ClassLV':classLV}, True)
+    if not ipyDataList:
+        return
+    
+    starCountDict = {}
+    for ipyData in ipyDataList:
+        index = ipyData.GetGridIndex()
+        equipStar = ChEquip.GetEquipPartStar(curPlayer, index)
+        if not equipStar:
+            continue
+        conditionKey = (classLV, equipStar)
+        starCountDict[conditionKey] = starCountDict.get(conditionKey, 0) + 1
+        
+    #GameWorld.DebugLog("升星成就数据: classLV=%s,starCountDict=%s" % (classLV, starCountDict))
+    PlayerSuccess.UpdateSuccessProgressByConditions(curPlayer, ShareDefine.SuccType_EquipStar, starCountDict)
+    return
 

--
Gitblit v1.8.0