#!/usr/bin/python # -*- coding: GBK -*- #------------------------------------------------------------------------------- # ##@package UseItem.Item_Chests # # @todo:±¦Ïä # @author hxp # @date 2018-02-05 # @version 1.0 # # ÏêϸÃèÊö: Ipy±¦Ïä±íÎïÆ· # #------------------------------------------------------------------------------- #"""Version = 2018-02-05 15:00""" #------------------------------------------------------------------------------- #µ¼Èë import GameWorld import ItemCommon import PlayerControl import IpyGameDataPY import IPY_GameWorld import ItemControler import PlayerRune import NPCCommon import ChConfig import ChEquip import ChItem import random import math #--------------------------------------------------------------------- def BatchUseItem(curPlayer, curRoleItem, tick, useCnt, exData): ##ÅúÁ¿Ê¹ÓÃÎïÆ· chestsItemID = curRoleItem.GetItemTypeID() chestsIpyData = IpyGameDataPY.GetIpyGameDataNotLog("Chests", chestsItemID) if not chestsIpyData: return showType = chestsIpyData.GetShowType() # ¹æ¶¨ÓпªÏä±íÏÖµÄĬÈÏÖ»ÄÜ¿ªÆô1¸ö #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 if costItemID: costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID) if bindCnt + unBindCnt < costItemCountTotal: GameWorld.DebugLog("ËùÐèÏûºÄµÀ¾ß²»×㣬ÎÞ·¨´ò¿ª±¦Ïä!chestsItemID=%s,costItemID=%s,costItemCountTotal=%s,bindCnt=%s,unBindCnt=%s" % (chestsItemID, costItemID, costItemCountTotal, bindCnt, unBindCnt)) return GameWorld.DebugLog("UseChests: chestsItemID=%s,useCnt=%s,isBind=%s,costItemID=%s*%s,costGoldTotal=%s" % (chestsItemID, useCnt, isBind, costItemID, costItemCountTotal, costGoldTotal)) # ²ú³öÔ¤´¦Àí awardInfo = GetChestsAwardInfo(curPlayer, chestsItemID, useCnt, exData) if not awardInfo: return 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, needSpace - packSpace]) return # ¿Û³ýÏûºÄ if costItemID: ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, costItemCountTotal, "Chests") if costGoldTotal: infoDict = {ChConfig.Def_Cost_Reason_SonKey:chestsItemID} PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGoldTotal, ChConfig.Def_Cost_UseItem, infoDict) # ¸üпªÆô´ÎÊý 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 jobAwardItemList: canSell = (not auctionItemCanSell) if itemID in aucionItemDiffSellIDList else auctionItemCanSell isAuctionItem = 1 if canSell and IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", itemID) else 0 userDataList = [] giveOKCount = ItemControler.DoGiveItemLoop(curPlayer, itemID, itemCount, isAuctionItem, event=[ChConfig.ItemGive_Chests, False, {"UseItemID":chestsItemID}], jsonItemList=syncItemList, userDataList=userDataList) if giveOKCount < itemCount: GameWorld.ErrLog("±¦Ï䏸ÎïÆ·Òì³£!chestsItemID=%s,useCnt=%s,itemID=%s,itemCount=%s,isBind=%s,giveOKCount=%s" % (chestsItemID, useCnt, itemID, itemCount, isBind, giveOKCount), curPlayer.GetPlayerID()) continue if itemID in notifyItemList: userData = userDataList[0] if userDataList else "" PlayerControl.WorldNotify(0, "ChooseMessage", [curPlayer.GetPlayerName(), chestsItemID, itemID, isBind, itemCount, userData]) # »õ±Ò if moneyType: addDataDict = {ChConfig.Def_Give_Reason_SonKey:chestsItemID} if not PlayerControl.GiveMoney(curPlayer, moneyType, moneyCount, ChConfig.Def_GiveMoney_UseItem, addDataDict, False): moneyType, moneyCount = 0, 0 # ֪ͨ if showType and syncItemList: ChItem.SendUseItemGetItemResult(curPlayer, chestsItemID, useCnt, syncItemList, moneyType, moneyCount) return True, useCnt def GetChestsAwardInfo(curPlayer, chestsItemID, useCount, exData=0): '''»ñÈ¡±¦Ï俪Æô½±Àø @return: None - »ñÈ¡±¦Ïä½±ÀøÊ§°Ü @return: needSpaceDict, jobAwardItemList [[itemID, itemCount], ...] ''' awardIpyData = __GetChestsAwardIpyDataByLV(curPlayer, chestsItemID) if not awardIpyData: return awardItemDict = {} job = curPlayer.GetJob() jobItemList = awardIpyData.GetJobItemList() # Ñ¡ÔñÎïÆ· if awardIpyData.GetSelectItemDict(): if isinstance(exData, int): selectDict = {exData:useCount} # ¼æÈݾɵĵ¥Ñ¡Ä£Ê½ elif isinstance(exData, dict): selectDict = exData else: GameWorld.ErrLog("Ñ¡ÔñµÄÎïÆ·´íÎó, ÐèÒªÖ¸¶¨Ñ¡ÔñÎïÆ·ID!chestsItemID=%s,exData=%s" % (chestsItemID, exData)) return GameWorld.DebugLog(" ×ÔÑ¡ÏîÐÅÏ¢: %s" % selectDict) selectCountTotal = 0 for cfgItemID, itemCount in awardIpyData.GetSelectItemDict().items(): # Ö§³Ö°´Ö°ÒµÑ¡Ôñ£¬Ç°¶ËÎÞÂÛ·¢Ö°Òµ¶ÔÓ¦ÎïÆ·ID»òÕßÅäÖõÄÎïÆ·ID¾ù¿É»ñµÃ jobItemID = __GetChestsJobItem(chestsItemID, job, cfgItemID, jobItemList) if not jobItemID: return if cfgItemID in selectDict: selectCount = selectDict.pop(cfgItemID) elif jobItemID in selectDict: selectCount = selectDict.pop(jobItemID) else: continue selectCountTotal += selectCount GameWorld.DebugLog(" ¿ÉÑ¡×ÔÑ¡Ïî: cfgItemID=%s,jobItemID=%s,selectCount=%s" % (cfgItemID, jobItemID, selectCount)) __AddAwardItem(awardItemDict, jobItemID, itemCount * selectCount) if not selectDict: break if selectCountTotal != useCount: GameWorld.ErrLog("Ñ¡ÔñµÄÎïÆ·´íÎó!chestsItemID=%s,selectCountTotal=%s != %s" % (chestsItemID, selectCountTotal, useCount)) return # ¹Ì¶¨²ú³öÎïÆ· if awardIpyData.GetFixedItemDict(): for itemID, itemCount in awardIpyData.GetFixedItemDict().items(): __AddAwardItem(awardItemDict, itemID, itemCount * useCount) # Ëæ»úÎïÆ·¿â1 if awardIpyData.GetRandItemList1() and awardIpyData.GetRandTimeList1(): if not __AddChestsRandAwardItem(curPlayer, chestsItemID, useCount, awardItemDict, awardIpyData.GetRandItemList1(), awardIpyData.GetRandTimeList1()): return # ¸ù¾Ý±¦Ï俪Æô´ÎÊýÌØÊâ²ú³ö 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() and randItemList2DoCount: if not __AddChestsRandAwardItem(curPlayer, chestsItemID, randItemList2DoCount, awardItemDict, awardIpyData.GetRandItemList2(), awardIpyData.GetRandTimeList2()): return # ×°±¸¿â if awardIpyData.GetPieRateDrop() or awardIpyData.GetIndepRateDrop(): if not __AddChestsEquipItem(curPlayer, chestsItemID, useCount, awardItemDict, awardIpyData): return # ²ú³öÌØÊâÎïÆ·¹ã²¥ needNotifyItemList = awardIpyData.GetNeedNotifyItemList() needSpaceDict = {} # {packType:needSpace, ...} notifyItemList = [] jobAwardItemList = [] for itemID, itemCount in awardItemDict.items(): if not itemCount: continue jobItemID = __GetChestsJobItem(chestsItemID, job, itemID, jobItemList) if not jobItemID: return itemData = GameWorld.GetGameData().GetItemByTypeID(jobItemID) if not itemData: GameWorld.ErrLog("±¦Ïä½±ÀøÎïÆ·²»´æÔÚ! chestsItemID=%s,itemID=%s,jobItemID=%s" % (chestsItemID, itemID, jobItemID)) return packType = ChConfig.GetItemPackType(itemData) needSpace = ItemControler.GetItemNeedPackCount(packType, itemData, itemCount) needSpaceDict[packType] = needSpaceDict.get(packType, 0) + needSpace # ×°±¸²ð¿ª¸ø£¬ÐèҪͬ²½Ã¿¼þ×°±¸µÄÊôÐÔ 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 needSpaceDict, jobAwardItemList, awardIpyData.GetMoneyType(), awardIpyData.GetMoneyCount() * useCount, notifyItemList, updOpenCount def __GetMaxRandTime(randTimeList): if len(randTimeList) == 1 and type(randTimeList[0]) == int: return randTimeList[0] return randTimeList[-1][1] def __AddChestsRandAwardItem(curPlayer, chestsItemID, useCount, awardItemDict, randItemList, randTimeList): # ¹ýÂËδ½âËøµÄÎïÆ· resetRandItemList = [] # ÖØÉè¿É²ú³öµÄÎïÆ·±ýͼ¸ÅÂÊÁбí for i, rateItemInfo in enumerate(randItemList): if type(rateItemInfo) not in [list, tuple] or len(rateItemInfo) != 2: GameWorld.ErrLog("±¦ÏäËæ»úÎïÆ·¿â±ýͼ¸ñʽ´íÎó!chestsItemID=%s,randItemList=%s" % (chestsItemID, randItemList)) return False rate, itemInfo = rateItemInfo if itemInfo and itemInfo[0]: itemID = itemInfo[0] # ÓÐÅäÖÃÎïÆ·ID£¬ÐèÅжϸÃÎïÆ·IDÊÇ·ñºÏ·¨¿É¿ª³öµÈ£¬Ö§³ÖÅäÖÿÕÎïÆ·ID itemData = GameWorld.GetGameData().GetItemByTypeID(itemID) if not itemData: GameWorld.ErrLog("±¦Ïä½±ÀøÎïÆ·²»´æÔÚ! chestsItemID=%s,itemID=%s" % (chestsItemID, itemID)) return False # ·ûÓ¡ÅжÏÊÇ·ñÒѾ­½âËø if itemData.GetType() == ChConfig.Def_ItemType_Rune: if not PlayerRune.GetIsOpenByRuneID(curPlayer, itemID): GameWorld.DebugLog("´Ë·ûӡδ½âËøÎÞ·¨¿ª³ö! chestsItemID=%s,itemID=%s" % (chestsItemID, itemID)) continue curRate = rate if i == 0 else (rate - randItemList[i - 1][0]) preRate = 0 if not resetRandItemList else resetRandItemList[-1][0] resetRandItemList.append([preRate + curRate, itemInfo]) # ÖØÉè±ýͼ¸ÅÂÊÁбí for _ in xrange(useCount): if len(randTimeList) == 1 and type(randTimeList[0]) == int: randTimes = randTimeList[0] else: randTimes = GameWorld.GetResultByRandomList(randTimeList) if randTimes == None: GameWorld.ErrLog("±¦ÏäËæ»ú´ÎÊýÅäÖôíÎó!chestsItemID=%s" % chestsItemID) return False if not randTimes: continue for _ in xrange(randTimes): randItemInfo = GameWorld.GetResultByRandomList(resetRandItemList) if not randItemInfo: #GameWorld.DebugLog("±¦ÏäËæ»ú¿âËæ»ú³öÎïÆ·0£¬randItemInfo=%s" % randItemInfo) continue if len(randItemInfo) != 2: GameWorld.ErrLog("±¦ÏäËæ»ú¿âÅäÖôíÎó!chestsItemID=%s" % chestsItemID) return False itemID, itemCount = randItemInfo if not itemID: #GameWorld.DebugLog("±¦ÏäËæ»ú¿âËæ»ú³öÎïÆ·itemID=0£¬randItemInfo=%s" % randItemInfo) continue __AddAwardItem(awardItemDict, itemID, itemCount) 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: if type(jobItemIDList) not in [list, tuple]: GameWorld.ErrLog("±¦ÏäÖ°ÒµÎïÆ·×é¸ñʽ´íÎó!chestsItemID=%s,jobItemList=%s" % (chestsItemID, jobItemList)) return 0 if itemID in jobItemIDList: if job <= 0 or job > len(jobItemIDList): GameWorld.ErrLog("±¦ÏäÖ°ÒµÎïÆ·ÅäÖôíÎó,ûÓиÃÖ°Òµ¶ÔÓ¦ÎïÆ·ID!chestsItemID=%s,job=%s,itemID=%s" % (chestsItemID, job, itemID)) return 0 return jobItemIDList[job - 1] return itemID def __AddAwardItem(awardItemDict, itemID, itemCount): awardItemDict[itemID] = awardItemDict.get(itemID, 0) + itemCount return def __GetChestsAwardIpyDataByLV(curPlayer, chestsItemID): ## »ñÈ¡±¦Ï俪Æô½±Àø awardIpyDataList = IpyGameDataPY.GetIpyGameDataList("ChestsAward", chestsItemID) if not awardIpyDataList: return if len(awardIpyDataList) == 1: return awardIpyDataList[0] # ¶àÌõ²ú³ö¼Ç¼µÄ£¬°´µÈ¼¶À´ lvIpyDataList = [] for ipyData in awardIpyDataList: lvIpyDataList.append([ipyData.GetRealmLV(), ipyData.GetAwardLV(), ipyData]) lvIpyDataList.sort() # ÉýÐòÅÅÐò curLV = curPlayer.GetLV() 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()) 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): 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]