#!/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:  
 | 
        openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1  
 | 
        endDateStr = GameWorld.GetOperationActionDateStr(ipyData.GetEndDate(), openServerDay)  
 | 
        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  
 | 
      
 | 
    openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1  
 | 
    clientPack = ChPyNetSendPack.tagMCActCollectWordsInfo()  
 | 
    clientPack.ActNum = actNum  
 | 
    clientPack.StartDate = GameWorld.GetOperationActionDateStr(ipyData.GetStartDate(), openServerDay)  
 | 
    clientPack.EndtDate = GameWorld.GetOperationActionDateStr(ipyData.GetEndDate(), openServerDay)  
 | 
    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  
 | 
  
 | 
  
 |