| #!/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 ChConfig  | 
| import ChItem  | 
|   | 
| 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  | 
|           | 
|     isBind = int(chestsIpyData.GetIsBind()) # ½±ÀøÎïÆ·ÊÇ·ñ°ó¶¨  | 
|     costItemID = chestsIpyData.GetCostItemID()  | 
|     costItemCountTotal = chestsIpyData.GetCostItemCount() * useCnt  | 
|     costGoldTotal = chestsIpyData.GetCostGold() * useCnt  | 
|       | 
|     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"   | 
|                        % (needSpaceDict, jobAwardItemList, moneyType, moneyCount, notifyItemList, updOpenCount))  | 
|       | 
|     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:  | 
|         curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isBind)  | 
|         if not curItem:  | 
|             GameWorld.ErrLog("±¦Ïä´´½¨½±ÀøÎïÆ·Òì³£!chestsItemID=%s,useCnt=%s,itemID=%s,itemCount=%s,isBind=%s"   | 
|                              % (chestsItemID, useCnt, itemID, itemCount, isBind), curPlayer.GetPlayerID())  | 
|             continue  | 
|           | 
|         if showType:  | 
|             syncItemList.append(ItemCommon.GetJsonItem(curItem)) # ±ØÐëÔÚ¸øÎïÆ·Ö®Ç°ÏÈget  | 
|               | 
|         userData = curItem.GetUserData()  | 
|         isOK = ItemControler.DoLogic_PutItemInPack(curPlayer, curItem, event=[ChConfig.ItemGive_Chests, False, {"UseItemID":chestsItemID}])  | 
|         if isOK and itemID in notifyItemList:  | 
|             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 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 not exData:  | 
|             GameWorld.ErrLog("Ñ¡ÔñµÄÎïÆ·´íÎó, ÐèÒªÖ¸¶¨Ò»¸öÑ¡ÔñÎïÆ·ID!chestsItemID=%s,selectItemID=%s" % (chestsItemID, exData))  | 
|             return  | 
|         selectItemID = exData  | 
|           | 
|         isSelectOK = False  | 
|         for cfgItemID, itemCount in awardIpyData.GetSelectItemDict().items():  | 
|             # Ö§³Ö°´Ö°ÒµÑ¡Ôñ£¬Ç°¶ËÎÞÂÛ·¢Ö°Òµ¶ÔÓ¦ÎïÆ·ID»òÕßÅäÖõÄÎïÆ·ID¾ù¿É»ñµÃ  | 
|             jobItemID = __GetChestsJobItem(chestsItemID, job, cfgItemID, jobItemList)  | 
|             if not jobItemID:  | 
|                 return  | 
|             if selectItemID == cfgItemID or selectItemID == jobItemID:  | 
|                 __AddAwardItem(awardItemDict, jobItemID, itemCount * useCount)  | 
|                 isSelectOK = True  | 
|                 break  | 
|               | 
|         if not isSelectOK:  | 
|             GameWorld.ErrLog("Ñ¡ÔñµÄÎïÆ·´íÎó, ¸Ã±¦ÏäûÓиÃÎïÆ·!chestsItemID=%s,selectItemID=%s" % (chestsItemID, selectItemID))  | 
|             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  | 
|       | 
|     # ²ú³öÌØÊâÎïÆ·¹ã²¥  | 
|     needNotifyItemList = awardIpyData.GetNeedNotifyItemList()  | 
|       | 
|     needSpaceDict = {} # {packType:needSpace, ...}  | 
|     notifyItemList = []  | 
|     jobAwardItemList = []  | 
|     for itemID, itemCount in awardItemDict.items():  | 
|         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.GetType())  | 
|         needSpace = int(math.ceil(itemCount / float(itemData.GetPackCount())))  | 
|         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:  | 
|                 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 __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.GetAwardLV(), ipyData])  | 
|     lvIpyDataList.sort() # ÉýÐòÅÅÐò  | 
|       | 
|     curLV = curPlayer.GetLV()  | 
|     minLV = lvIpyDataList[0][0]  | 
|     if curLV < minLV:  | 
|         GameWorld.ErrLog("µ±Ç°µÈ¼¶ÎÞ·¨¿ªÆô¸Ã±¦Ïä!curLV=%s,minLV=%s,chestsItemID=%s" % (curLV, minLV, 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  | 
|     return awardIpyDataList[-1]  | 
|   |