| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package Player.PlayerActCollectWords  | 
| #  | 
| # @todo:¼¯×ֻ  | 
| # @author hxp  | 
| # @date 2020-12-08  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ¼¯×ֻ  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2020-12-08 19:00"""  | 
| #-------------------------------------------------------------------------------  | 
| import GameWorld  | 
| import PyGameData  | 
| import ShareDefine  | 
| import PlayerControl  | 
| import ChConfig  | 
| import IpyGameDataPY  | 
| import ChPyNetSendPack  | 
| import NetPackCommon  | 
| import ItemCommon  | 
| import ItemControler  | 
| import IPY_GameWorld  | 
|   | 
|   | 
| def GetActInfo(actNum):  | 
|     if ShareDefine.OperationActionName_CollectWords not in PyGameData.g_operationActionDict:  | 
|         return {}  | 
|     actNumDict = PyGameData.g_operationActionDict[ShareDefine.OperationActionName_CollectWords]  | 
|     if actNum not in actNumDict:  | 
|         return {}  | 
|     return actNumDict[actNum]  | 
|   | 
| def OnPlayerLogin(curPlayer):  | 
|     ## Íæ¼ÒµÇ¼  | 
|       | 
|     for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_CollectWords, {}).values():  | 
|         actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)  | 
|         isReset = __CheckPlayerCollectWordsAction(curPlayer, actNum)  | 
|         if not isReset:  | 
|             # »î¶¯ÖÐͬ²½»î¶¯ÐÅÏ¢  | 
|             if actInfo.get(ShareDefine.ActKey_State):  | 
|                 SyncCollectWordsActionInfo(curPlayer, actNum)  | 
|                 SyncCollectWordsPlayerInfo(curPlayer, actNum)  | 
|                   | 
|     return  | 
|   | 
| def RefreshActCollectWordsInfo(actNum):  | 
|     ## ÊÕµ½GameServerͬ²½µÄ»î¶¯ÐÅÏ¢£¬Ë¢Ð»ÐÅÏ¢  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for index in xrange(playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(index)  | 
|         if curPlayer.GetID() == 0:  | 
|             continue  | 
|         __CheckPlayerCollectWordsAction(curPlayer, actNum)  | 
|           | 
|     return  | 
|   | 
| def __CheckPlayerCollectWordsAction(curPlayer, actNum):  | 
|     ## ¼ì²éÍæ»î¶¯Êý¾ÝÐÅÏ¢  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     actInfo = GetActInfo(actNum)  | 
|     actID = actInfo.get(ShareDefine.ActKey_ID, 0)  | 
|     state = actInfo.get(ShareDefine.ActKey_State, 0)  | 
|       | 
|     playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollectWordsID % actNum) # Íæ¼ÒÉíÉϵĻID  | 
|       | 
|     # »î¶¯ID ÏàͬµÄ»°²»´¦Àí  | 
|     if actID == playerActID:  | 
|         GameWorld.DebugLog("¼¯×ֻID²»±ä£¬²»´¦Àí£¡actNum=%s,actID=%s" % (actNum, actID), curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     templateID = 0  | 
|     cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)  | 
|     if cfgID:  | 
|         actIpyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)  | 
|         templateID = 0 if not actIpyData else actIpyData.GetTemplateID()  | 
|         exchangeList = IpyGameDataPY.GetIpyGameDataList("CollectWordsExchange", templateID)  | 
|         if not exchangeList:  | 
|             GameWorld.ErrLog("¼¯×Ö¶Ò»»ÕÒ²»µ½¶Ò»»Ä£°åÅäÖÃ!actNum=%s,cfgID=%s,templateID=%s" % (actNum, cfgID, templateID), playerID)  | 
|         else:  | 
|             for exchangeIpyData in exchangeList:  | 
|                 exchangeNum = exchangeIpyData.GetExchangeNum()  | 
|                 PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollectWordsExchangeCount % (actNum, exchangeNum), 0)  | 
|                   | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollectWordsID % actNum, actID)  | 
|     GameWorld.DebugLog("¼¯×Ö»î¶¯ÖØÖÃ! actNum=%s,cfgID=%s,templateID=%s,actID=%s" % (actNum, cfgID, templateID, actID), playerID)  | 
|       | 
|     if state:  | 
|         SyncCollectWordsActionInfo(curPlayer, actNum)  | 
|         SyncCollectWordsPlayerInfo(curPlayer, actNum)  | 
|           | 
|     return True  | 
|   | 
| def OnKillNPCDrop(curPlayer, curNPC):  | 
|     ## »÷ɱNPCµô×ÖÂß¼  | 
|       | 
|     if curNPC.GetType() in [ChConfig.ntPriWoodPilePVP]:  | 
|         return  | 
|       | 
|     for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_CollectWords, {}).values():  | 
|         actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)  | 
|         randList = __GetDropWordsItemRateList(curPlayer, curNPC, actInfo)  | 
|         if not randList:  | 
|             continue  | 
|         dropItemID = GameWorld.GetResultByRandomList(randList)  | 
|         if not dropItemID:  | 
|             continue  | 
|         GameWorld.DebugLog("    ¼¯×ֻµôÂäÎïÆ·! actNum=%s,npcID=%s,dropItemID=%s" % (actNum, curNPC.GetNPCID(), dropItemID))  | 
|           | 
|         itemCount = 1 # Ä¬ÈÏ1¸ö  | 
|         isAuctionItem = 0 # ·ÇÅÄÆ·  | 
|         ItemControler.GivePlayerItem(curPlayer, dropItemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])  | 
|           | 
|     return  | 
|   | 
| def __GetDropWordsItemRateList(curPlayer, npcData, actInfo):  | 
|     ## »ñÈ¡µô×Ö±ýͼÁÐ±í  | 
|       | 
|     if not actInfo.get(ShareDefine.ActKey_State):  | 
|         return  | 
|       | 
|     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)  | 
|     if not ipyData:  | 
|         return  | 
|       | 
|     isBoss = ChConfig.IsGameBoss(npcData)  | 
|     playerLV = curPlayer.GetLV()  | 
|     npcLV = npcData.GetLV()  | 
|     limitLV = ipyData.GetLVLimit()  | 
|     if not isBoss and limitLV and limitLV > playerLV:  | 
|         #GameWorld.DebugLog("    ¼¯×Ö»î¶¯Íæ¼ÒµÈ¼¶²»×㣬ÎÞ·¨µôÂä! actName=%s,cfgID=%s,limitLV=%s" % (actName, cfgID, limitLV))  | 
|         return  | 
|       | 
|     dropDiffLVLimit = ipyData.GetDropDiffLVLimit()  | 
|     if not isBoss and dropDiffLVLimit and (playerLV - npcLV) > dropDiffLVLimit:  | 
|         #GameWorld.DebugLog("    ¼¯×Ö»î¶¯Íæ¼ÒµÈ¼¶ÓëNPCµÈ¼¶²îÖµ¹ý´ó£¬ÎÞ·¨µôÂä! actName=%s,cfgID=%s,playerLV(%s) - npcLV(%s) > %s"   | 
|         #                   % (actName, cfgID, playerLV, npcLV, dropDiffLVLimit))  | 
|         return  | 
|       | 
|     lastDayOnlyExchange = ipyData.GetLastDayOnlyExchange()  | 
|     if lastDayOnlyExchange:  | 
|         _, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)  | 
|         curDate = GameWorld.GetCurrentTime()  | 
|         curDateStr = "%d-%s-%s" % (curDate.year, curDate.month, curDate.day)  | 
|         if curDateStr == endDateStr:  | 
|             #GameWorld.DebugLog("    ¼¯×ֻ×îºóÒ»Ìì²»µôÂä! actName=%s,cfgID=%s, %s" % (actName, cfgID, curDateStr))  | 
|             return  | 
|           | 
|     if not isBoss:  | 
|         return ipyData.GetDropItemRateList()  | 
|       | 
|     bossDropRateListInfo = ipyData.GetDropItemRateListBoss()  | 
|     npcID = npcData.GetNPCID()  | 
|     killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)  | 
|     limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)  | 
|     return bossDropRateListInfo.get(limitIndex, [])  | 
|   | 
| def OnGetDropWordsItemDict(curPlayer, npcData, killCount):  | 
|     ## »ñÈ¡ÍÑ»úµôÂäÎïÆ·  | 
|       | 
|     dropItemCountDict = {}  | 
|     for actInfo in PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_CollectWords, {}).values():  | 
|         actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)  | 
|           | 
|         dropRateList = __GetDropWordsItemRateList(curPlayer, npcData, actInfo)  | 
|         if not dropRateList:  | 
|             continue  | 
|           | 
|         preRate = 0  | 
|         maxRate = dropRateList[-1][0]  | 
|         for rateInfo in dropRateList:  | 
|             rate, dropItemID = rateInfo  | 
|             curRate = rate - preRate  | 
|             if not curRate:  | 
|                 break  | 
|             preRate = rate  | 
|             if not dropItemID:  | 
|                 continue  | 
|             totalRate = curRate * killCount # ×ܸÅÂÊ  | 
|             dropCount = totalRate / maxRate # ¿ÉµôÂäÊý  | 
|             rateEx = totalRate % maxRate # Ê£Óà¸ÅÂÊ  | 
|             if GameWorld.CanHappen(rateEx, maxRate):  | 
|                 dropCount += 1  | 
|             if not dropCount:  | 
|                 continue  | 
|               | 
|             dropItemCountDict[dropItemID] = dropItemCountDict.get(dropItemID, 0) + dropCount  | 
|             GameWorld.DebugLog("    ÍÑ»ú¼¯×ֻµô×Ö: actNum=%s,dropItemID=%s,dropCount=%s" % (actNum, dropItemID, dropCount))  | 
|               | 
|     return dropItemCountDict  | 
|   | 
| #// AA 09 ¼¯×ֻ¶Ò»» #tagCMActCollectWordsExchange  | 
| #  | 
| #struct    tagCMActCollectWordsExchange  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        ActNum;    //»î¶¯±àºÅ£¬1 »ò 2£¬Ï໥¶ÀÁ¢µÄ»î¶¯£¬¿Éͬʱ¿ªÆô  | 
| #    BYTE        ExchangeNum;    //¶Ò»»±àºÅ  | 
| #};  | 
| def OnActCollectWordsExchange(index, clientData, tick):  | 
|     actNum = clientData.ActNum  | 
|     exchangeNum = clientData.ExchangeNum  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|       | 
|     GameWorld.DebugLog("¼¯×ֻ¶Ò»»£¡actNum=%s,exchangeNum=%s" % (actNum, exchangeNum))  | 
|       | 
|     actInfo = GetActInfo(actNum)  | 
|       | 
|     if not actInfo.get(ShareDefine.ActKey_State):  | 
|         GameWorld.DebugLog("·Ç¼¯×ֻÖУ¬ÎÞ·¨¶Ò»»£¡actNum=%s" % actNum)  | 
|         return  | 
|       | 
|     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)  | 
|     if not ipyData:  | 
|         return  | 
|       | 
|     templateID = ipyData.GetTemplateID()  | 
|     if not templateID:  | 
|         return  | 
|       | 
|     exchangeList = IpyGameDataPY.GetIpyGameDataList("CollectWordsExchange", templateID)  | 
|     if not exchangeList:  | 
|         return  | 
|       | 
|     findIpyData = None  | 
|     for exchangeIpyData in exchangeList:  | 
|         if exchangeNum == exchangeIpyData.GetExchangeNum():  | 
|             findIpyData = exchangeIpyData  | 
|             break  | 
|           | 
|     if not findIpyData:  | 
|         GameWorld.ErrLog("ÕÒ²»µ½¼¯×ֻ¶Ò»»ÅäÖÃÊý¾Ý£¡actNum=%s,cfgID=%s,templateID=%s,exchangeNum=%s"   | 
|                          % (actNum, cfgID, templateID, exchangeNum))  | 
|         return  | 
|       | 
|     exchangeCountMax = findIpyData.GetExchangeCountMax()  | 
|     curExchangeCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollectWordsExchangeCount % (actNum, exchangeNum))  | 
|     if exchangeCountMax and curExchangeCount >= exchangeCountMax:  | 
|         GameWorld.DebugLog("³¬¹ý×î´ó¼¯×Ö¶Ò»»´ÎÊý£¡templateID=%s,exchangeNum=%s,curExchangeCount=%s > %s"   | 
|                            % (templateID, exchangeNum, curExchangeCount, exchangeCountMax))  | 
|         return  | 
|       | 
|     exchangeItemInfo = __GetExchangeItemInfo(findIpyData.GetExchangeItemInfo(), actInfo.get(ShareDefine.ActKey_WorldLV, 0))  | 
|     if len(exchangeItemInfo) != 3:  | 
|         return  | 
|     exchangeItemID = exchangeItemInfo[0]  | 
|     exchangeCount = exchangeItemInfo[1]  | 
|     exchangeIsBind = exchangeItemInfo[2]  | 
|       | 
|     if not ItemControler.CheckPackSpaceEnough(curPlayer, [[exchangeItemID, exchangeCount, exchangeIsBind]]):  | 
|         return  | 
|       | 
|     delItemList = []  | 
|     needItemList = findIpyData.GetNeedItemList()  | 
|     for needItemID, needCount, _ in needItemList:  | 
|         costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, needItemID, needCount)  | 
|         if bindCnt + unBindCnt < needCount:  | 
|             GameWorld.DebugLog("¼¯×Ö¶Ò»»ËùÐèÎïÆ·²»×㣡exchangeItemID=%s,needItemID=%s,needCount=%s > %s"   | 
|                                % (exchangeItemID, needItemID, needCount, bindCnt + unBindCnt))  | 
|             return  | 
|         delItemList.append([costItemIndexList, bindCnt, unBindCnt, needCount])  | 
|           | 
|     if exchangeCountMax:  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollectWordsExchangeCount % (actNum, exchangeNum), curExchangeCount + 1)  | 
|         SyncCollectWordsPlayerInfo(curPlayer, actNum, exchangeNum)  | 
|           | 
|     eventName = "CollectWordsExchange"  | 
|     for costItemIndexList, bindCnt, unBindCnt, needCount in delItemList:  | 
|         ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, needCount, eventName)  | 
|           | 
|     ItemControler.GivePlayerItem(curPlayer, exchangeItemID, exchangeCount, exchangeIsBind, [IPY_GameWorld.rptItem], event=[eventName, False, {}])  | 
|       | 
|     if findIpyData.GetNeedNotify():  | 
|         PlayerControl.WorldNotify(0, "CollectWordsExchange", [curPlayer.GetPlayerName(), exchangeItemID])  | 
|           | 
|     return  | 
|   | 
| def __GetExchangeItemInfo(cfgExchangeItemInfo, worldLV):  | 
|     if isinstance(cfgExchangeItemInfo, dict):  | 
|         return GameWorld.GetDictValueByRangeKey(cfgExchangeItemInfo, worldLV, [])  | 
|     return cfgExchangeItemInfo  | 
|   | 
| def SyncCollectWordsActionInfo(curPlayer, actNum):  | 
|     ## Í¬²½»î¶¯ÐÅÏ¢  | 
|       | 
|     actInfo = GetActInfo(actNum)  | 
|       | 
|     if not actInfo.get(ShareDefine.ActKey_State):  | 
|         return  | 
|       | 
|     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)  | 
|     if not ipyData:  | 
|         return  | 
|       | 
|     templateID = ipyData.GetTemplateID()  | 
|     if not templateID:  | 
|         return  | 
|       | 
|     startDateStr, endDateStr = GameWorld.GetOperationActionDateStr(ipyData)  | 
|     clientPack = ChPyNetSendPack.tagMCActCollectWordsInfo()  | 
|     clientPack.ActNum = actNum  | 
|     clientPack.StartDate = startDateStr  | 
|     clientPack.EndtDate = endDateStr  | 
|     clientPack.LimitLV = ipyData.GetLVLimit()  | 
|     clientPack.LastDayOnlyExchange = ipyData.GetLastDayOnlyExchange()  | 
|     clientPack.ExchangeItemList = []  | 
|       | 
|     exchangeList = IpyGameDataPY.GetIpyGameDataList("CollectWordsExchange", templateID)  | 
|     if exchangeList:  | 
|         for exchangeIpyData in exchangeList:  | 
|             itemID, itemCount, isBind = __GetExchangeItemInfo(exchangeIpyData.GetExchangeItemInfo(), actInfo.get(ShareDefine.ActKey_WorldLV, 0))  | 
|             needItemList = exchangeIpyData.GetNeedItemList()  | 
|               | 
|             exchangeItem = ChPyNetSendPack.tagMCActCollectWordsExchangeItem()  | 
|             exchangeItem.ExchangeNum = exchangeIpyData.GetExchangeNum()  | 
|             exchangeItem.ExchangeCountMax = exchangeIpyData.GetExchangeCountMax()  | 
|             exchangeItem.ItemID = itemID  | 
|             exchangeItem.ItemCount = itemCount  | 
|             exchangeItem.IsBind = isBind  | 
|             exchangeItem.NeedItemList = []  | 
|             for needItemID, needCount, needIsBind in needItemList:  | 
|                 needItem = ChPyNetSendPack.tagMCActCollectWordsNeedItem()  | 
|                 needItem.ItemID = needItemID  | 
|                 needItem.ItemCount = needCount  | 
|                 needItem.IsBind = needIsBind  | 
|                 exchangeItem.NeedItemList.append(needItem)  | 
|             exchangeItem.NeedItemCount = len(exchangeItem.NeedItemList)  | 
|               | 
|             clientPack.ExchangeItemList.append(exchangeItem)  | 
|               | 
|     clientPack.ExchangeCount = len(clientPack.ExchangeItemList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   | 
| def SyncCollectWordsPlayerInfo(curPlayer, actNum, exchangeNum=0):  | 
|     ## Í¬²½»î¶¯Íæ¼ÒÊý¾Ý  | 
|       | 
|     actInfo = GetActInfo(actNum)  | 
|     if not actInfo:  | 
|         return  | 
|       | 
|     if not actInfo.get(ShareDefine.ActKey_State):  | 
|         return  | 
|       | 
|     cfgID = actInfo.get(ShareDefine.ActKey_CfgID)  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("ActCollectWords", cfgID)  | 
|     if not ipyData:  | 
|         return  | 
|       | 
|     templateID = ipyData.GetTemplateID()  | 
|     if not templateID:  | 
|         return  | 
|       | 
|     exchangeList = IpyGameDataPY.GetIpyGameDataList("CollectWordsExchange", templateID)  | 
|     if not exchangeList:  | 
|         return  | 
|       | 
|     clientPack = ChPyNetSendPack.tagMCActCollectWordsPlayerInfo()  | 
|     clientPack.ActNum = actNum  | 
|     clientPack.ExchangeInfoList = []  | 
|     for exchangeIpyData in exchangeList:  | 
|         ipyExchangeNum = exchangeIpyData.GetExchangeNum()  | 
|         if exchangeNum and exchangeNum != ipyExchangeNum:  | 
|             continue  | 
|           | 
|         exchangeInfo = ChPyNetSendPack.tagMCActCollectWordsExchangeInfo()  | 
|         exchangeInfo.ExchangeNum = ipyExchangeNum  | 
|         exchangeInfo.ExchangeCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollectWordsExchangeCount % (actNum, ipyExchangeNum))   | 
|         clientPack.ExchangeInfoList.append(exchangeInfo)  | 
|           | 
|         if exchangeNum:  | 
|             break  | 
|           | 
|     clientPack.ExchangeCount = len(clientPack.ExchangeInfoList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   | 
|   |