ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -52,6 +52,7 @@
import PlayerMagicWeapon
import PlayerBossReborn
import PlayerFairyCeremony
import PlayerWeekParty
import FamilyRobBoss
import IpyGameDataPY
import PyGameData
@@ -1169,6 +1170,8 @@
    # 1. 职业物品ID集合
    job = curPlayer.GetJob()
    JobItemDropSets = IpyGameDataPY.GetFuncCfg("JobItemDropSets", 1) # {物品ID集合key:[职业顺序物品ID列表], ...}
    itemDropSets = IpyGameDataPY.GetFuncCfg("JobItemDropSets", 2) # {物品ID集合key:[随机物品ID列表], ...}
    itemDropRateSets = IpyGameDataPY.GetFuncCfg("JobItemDropSets", 3) # {物品ID集合key:[随机物品ID饼图列表], ...}
    ItemKeyMaxDropCountDict = ipyDrop.GetItemKeyMaxDropCount() # {物品ID集合key:随机次数,...}
    
    #     1.1 只掉本职业的
@@ -1199,20 +1202,14 @@
    #     1.2 随机掉落一个
    ItemKeyDropRateDict = ipyDrop.GetItemKeyDropRate() # {物品ID集合key:概率, ...}, 随机掉一个,优先级低
    if ItemKeyDropRateDict:
        for jobItemKey, dropRate in ItemKeyDropRateDict.items():
            if jobItemKey not in JobItemDropSets:
                continue
            jobItemList = JobItemDropSets[jobItemKey]
            if len(jobItemList) < job:
                GameWorld.ErrLog("职业物品集合key没有配置对应职业ID: npcID=%s,jobItemKey=%s,job=%s" % (npcID, jobItemKey, job))
                continue
        for itemKey, dropRate in ItemKeyDropRateDict.items():
            # 在只掉本职业里的不处理
            if jobItemKey in ItemKeyDropRateJobDict:
            if itemKey in ItemKeyDropRateJobDict:
                continue
            mustDropCount = dropRate / Def_NPCMaxDropRate
            dropRate = dropRate % Def_NPCMaxDropRate # 基础概率
            canDropCount = mustDropCount
            doCnt = ItemKeyMaxDropCountDict.get(jobItemKey, 1) # 默认1个
            doCnt = ItemKeyMaxDropCountDict.get(itemKey, 1) # 默认1个
            doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)
            for _ in xrange(doCnt):
                if not GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):
@@ -1220,9 +1217,20 @@
                canDropCount += 1
                
            for _ in xrange(canDropCount):
                randJobItemID = random.choice(jobItemList)
                dropItemIDList.append(randJobItemID)
                #GameWorld.DebugLog("掉落随机职业指定物品ID: jobItemKey=%s,randJobItemID=%s" % (jobItemKey, randJobItemID))
                if itemKey in itemDropRateSets:
                    randItemRateList = itemDropRateSets[itemKey]
                    randItemID = GameWorld.GetResultByRandomList(randItemRateList)
                    #GameWorld.DebugLog("掉落饼图物品ID: itemKey=%s,randItemRateList=%s,randItemID=%s" % (itemKey, randItemRateList, randItemID))
                elif itemKey in itemDropSets:
                    randItemList = itemDropSets[itemKey]
                    randItemID = random.choice(randItemList)
                    #GameWorld.DebugLog("掉落随机物品ID: itemKey=%s,randItemList=%s,randItemID=%s" % (itemKey, randItemList, randItemID))
                else:
                    continue
                if not randItemID:
                    continue
                dropItemIDList.append(randItemID)
                #GameWorld.DebugLog("掉落随机指定物品ID: itemKey=%s,randItemID=%s" % (itemKey, randItemID))
                
    # 2. 指定掉落ID处理, 受全局设定影响
    itemIDDropRateDict = ipyDrop.GetItemIDDropRate() # {物品ID:概率, ...}
@@ -2060,13 +2068,7 @@
        # 通知GameServer boss状态 封魔坛在副本里单独处理
        ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', npcid)
        if ipyData and ipyData.GetMapID() != ChConfig.Def_FBMapID_SealDemon:
            mapID = GameWorld.GetMap().GetMapID()
            lineID = GameWorld.GetGameWorld().GetLineID()
            msgList = [npcid, 0, mapID, lineID]
            GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState',
                                                                '%s' % (msgList), len(str(msgList)))
            bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % npcid
            GameWorld.GetGameWorld().SetGameWorldDict(bosskey, 0)
            GameServe_GameWorldBossState(npcid, 0)
            #GameWorld.GetGameWorld().SetGameWorldDict(ChConfig.Map_NPC_WorldBossDeadTick % npcid, GameWorld.GetGameWorld().GetTick())
            #因为存在boss分流,所以用gameFB字典,但是存活状态还是用GameWorld字典
            GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_NPC_WorldBossDeadTick % npcid, GameWorld.GetGameWorld().GetTick())
@@ -2092,13 +2094,75 @@
                   curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID))
    return
def GameServer_KillGameWorldBoss(bossID, killerName, hurtValue, isNotify=True):
    isAddKillCnt = 0 # 页游逻辑,手游暂写死不增
    mapID = GameWorld.GetMap().GetMapID()
    killMsg = str([bossID, killerName, hurtValue, isAddKillCnt, isNotify, mapID])
def GameServer_KillGameWorldBoss(bossID, killPlayerName, hurtValue, isNotify=True, killerIDList=[]):
    dataMapID = GameWorld.GetGameWorld().GetMapID()
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    killMsg = str([bossID, killPlayerName, hurtValue, isNotify, realMapID, dataMapID, copyMapID, killerIDList])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'KillGameWorldBoss', killMsg, len(killMsg))
    GameWorld.DebugLog("Boss被击杀: bossID=%s,dataMapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s" % (bossID, dataMapID, realMapID, copyMapID, killerIDList))
    return
def GameServe_GameWorldBossState(bossID, isAlive):
    dataMapID = GameWorld.GetGameWorld().GetMapID()
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    stateMsg = str([bossID, isAlive, dataMapID, realMapID, copyMapID])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState', '%s' % stateMsg, len(stateMsg))
    GameWorld.DebugLog("Boss状态变更: bossID=%s,isAlive=%s,dataMapID=%s,realMapID=%s,copyMapID=%s"
                       % (bossID, isAlive, dataMapID, realMapID, copyMapID))
    if not isAlive:
        if dataMapID in ChConfig.Def_CrossZoneTableName:
            tableName = ChConfig.Def_CrossZoneTableName[dataMapID]
            realMapID = GameWorld.GetGameWorld().GetRealMapID()
            copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
            zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID)
            if not zoneIpyData:
                return
            zoneID = zoneIpyData.GetZoneID()
            GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0)
        else:
            GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID, 0)
    return
def OnPlayerKillBoss(curPlayer, npcID, mapID, isCrossServer):
    killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)
    limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)
    if limitIndex != None:
        #今日杀怪次数+1
        key = ChConfig.Def_PDict_Boss_KillCnt % limitIndex
        newCnt = curPlayer.NomalDictGetProperty(key, 0) + 1
        PlayerControl.NomalDictSetProperty(curPlayer, key, newCnt)
        BossHurtMng.NotifyAttackBossCnt(curPlayer, limitIndex)
        GameWorld.DebugLog("今日杀怪次数  playerID=%s, newCnt=%s" % (curPlayer.GetPlayerID(), newCnt))
        dataDict = {"objID":npcID, "bossID":npcID, "touchCnt":newCnt,
                    "AccID":curPlayer.GetAccID(), "PlayerID":curPlayer.GetPlayerID()}
        DataRecordPack.SendEventPack("AddKillBossCnt", dataDict, curPlayer)
    if isCrossServer:
        return
    if limitIndex == ShareDefine.Def_Boss_Func_World:
        # 世界BOSS击杀成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillWorldBoss, 1)
        # 每日活动
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_WorldBOSS)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_WorldBOSS, 1)
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)
        PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_WorldBOSS, 1)
    if mapID == ChConfig.Def_FBMapID_BossHome:
        #BOSS之家
        # BOSS之家BOSS击杀成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillBossHomeBoss, 1)
        # 每日活动
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_BOSSHome)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_BOSSHome, 1)
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)
        PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_BOSSHome, 1)
    return
#################################################
## NPC控制定义
#
@@ -2118,6 +2182,7 @@
        self.__Killer = None # 击杀者, 由各种规则得出, 一般也是物品归属的代表, 用于广播、记录等确保与归属一致
        self.__AllKillerDict = {} # 所有击杀的玩家ID对应字典, 非队伍, 一般也是归属的拥有者
        self.__FeelPlayerList = [] # 所有摸怪玩家列表,处理任务及某些逻辑用
        self.__ownerPlayerList = [] # 归属者列表
        
        self.__OwnerHurtType = 0
        self.__OwnerHurtID = 0
@@ -3500,12 +3565,7 @@
            # 通知GameServer boss刷新成功
            ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', curNPCID)
            if ipyData:
                mapID = GameWorld.GetMap().GetMapID()
                lineID = GameWorld.GetGameWorld().GetLineID()
                msgList = [curNPCID, 1, mapID, lineID]
                GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState',
                                                            '%s' % (msgList), len(str(msgList)))
                GameServe_GameWorldBossState(curNPCID, 1)
                if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                    FamilyRobBoss.FamilyOwnerBossOnReborn(curNPC)
                    
@@ -3928,7 +3988,8 @@
            if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                killerName = FamilyRobBoss.FamilyOwnerBossOnKilled(curNPC, self.__OwnerHurtID)
            #KillerJob = 0 if not self.__Killer else self.__Killer.GetJob()
            GameServer_KillGameWorldBoss(curNPC.GetNPCID(), killerName, 0)
            killerIDList = [player.GetPlayerID() for player in self.__ownerPlayerList]
            GameServer_KillGameWorldBoss(curNPC.GetNPCID(), killerName, 0, True, killerIDList)
        #===========================================================================================
        # # 暗金boss
        # if curNPC.GetIsBoss() == ChConfig.Def_NPCType_Boss_Dark:
@@ -4426,7 +4487,8 @@
                    dropPlayer = curPlayer
                self.__KilledByPlayerSetPrize(curPlayer)
                ownerPlayerList.append(curPlayer)
            self.__ownerPlayerList = ownerPlayerList
            #调用物品掉落
            self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
@@ -4627,6 +4689,13 @@
                hurtID = killerDict.keys()[0]
                if isGameBoss:
                    GameWorld.Log("    归属默认玩家, npcID=%s,playerID=%s" % (npcID, hurtID))
            elif GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_GatherSoul:
                player = FBCommon.GetCurSingleFBPlayer()
                if player:
                    hurtID = player.GetPlayerID()
                    killerDict[hurtID] = player
                    hurtType = ChConfig.Def_NPCHurtTypePlayer
                    #GameWorld.Log("    聚魂副本归属默认玩家, npcID=%s,playerID=%s" % (npcID, hurtID))
                
        return killerDict, killTeam, hurtType, hurtID
    
@@ -4861,6 +4930,7 @@
            
            self.__DoNormalTeamExp(curPlayer)
            self.__KillNPCFuncEx(curPlayer, curNPC, maxHurtID, True)
        self.__ownerPlayerList = ownerPlayerList
            
        #调用物品掉落
        self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
@@ -4889,6 +4959,7 @@
                maxLV = curPlayerLV
                dropPlayer = player
            ownerPlayerList.append(player)
        self.__ownerPlayerList = ownerPlayerList
            
        if not ownerPlayerList:
            GameWorld.Log("奖励归属仙盟,但是不存在可获得该奖励的成员!npcID=%s,hurtType=%s,hurtID=%s" 
@@ -4929,47 +5000,31 @@
        defObjType = curNPC.GetGameObjType() 
        mapFBType = GameWorld.GetMap().GetMapFBType()
        mapID = FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID())
        playerID = curPlayer.GetPlayerID()
        #playerID = curPlayer.GetPlayerID()
        
        # 如果是NPC
        if defObjType == IPY_GameWorld.gotNPC:
        if defObjType != IPY_GameWorld.gotNPC:
            return
        # 跨服服务器处理
        if GameWorld.IsCrossServer():
            #掉落归属
            if mapFBType != IPY_GameWorld.fbtNull:
                FBLogic.DoFB_DropOwner(curPlayer , curNPC)
            else:
                if curNPC.GetLV()>=curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):
                    PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_KillNPC)
                
            killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)
            limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)
            if limitIndex != None:
                #今日杀怪次数+1
                key = ChConfig.Def_PDict_Boss_KillCnt % limitIndex
                newCnt = curPlayer.NomalDictGetProperty(key, 0) + 1
                PlayerControl.NomalDictSetProperty(curPlayer, key, newCnt)
                BossHurtMng.NotifyAttackBossCnt(curPlayer, limitIndex)
                GameWorld.DebugLog("今日杀怪次数  playerID=%s, newCnt=%s" % (curPlayer.GetPlayerID(), newCnt))
                dataDict = {"objID":curNPC.GetID(), "bossID":npcID, "touchCnt":newCnt,
                            "AccID":curPlayer.GetAccID(), "PlayerID":curPlayer.GetPlayerID()}
                DataRecordPack.SendEventPack("AddKillBossCnt", dataDict, curPlayer)
                if limitIndex == 0:
                    # 世界BOSS击杀成就
                    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillWorldBoss, 1)
                    # 每日活动
                    PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_WorldBOSS)
                    PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_WorldBOSS, 1)
                    PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)
            if ChConfig.IsGameBoss(curNPC) and mapID == ChConfig.Def_FBMapID_BossHome:
                #BOSS之家
                # BOSS之家BOSS击杀成就
                PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillBossHomeBoss, 1)
                # 每日活动
                PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_BOSSHome)
                PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_BOSSHome, 1)
                PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)
            if ChConfig.IsGameBoss(curNPC):
                OnPlayerKillBoss(curPlayer, npcID, mapID, True)
            return
        #掉落归属
        if mapFBType != IPY_GameWorld.fbtNull:
            FBLogic.DoFB_DropOwner(curPlayer , curNPC)
        else:
            if curNPC.GetLV()>=curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):
                PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_KillNPC)
            
        if ChConfig.IsGameBoss(curNPC):
            OnPlayerKillBoss(curPlayer, npcID, mapID, False)
        return
        
    #---------------------------------------------------------------------
@@ -4995,7 +5050,7 @@
        #GameWorld.DebugLog("__MissionOnKillNPC isFeel=%s" % (isFeel), curPlayer.GetPlayerID())
        killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)
        limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)
        isWorldBoos = limitIndex == 0
        isWorldBoos = limitIndex == ShareDefine.Def_Boss_Func_World
        if isFeel:
            #击杀NPC触发摸怪任务事件
            EventShell.EventRespons_OnKillByFeel(curPlayer, curNPC)
@@ -5246,21 +5301,9 @@
    
    # 采集次数判断
    limitMaxTime, todayCollTime = 0, 0
    npcFuncType = curNPC.GetFunctionType()
    npcFuncCollectCntLimitDict = ReadChConfig.GetEvalChConfig('CollectNPCFuncTimeLimit')
    if npcFuncType in npcFuncCollectCntLimitDict:
        vipLV = curPlayer.GetVIPLv()
        limitMaxTime = eval(npcFuncCollectCntLimitDict[npcFuncType])
        todayBuyTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcBuyTime % npcFuncType)
        todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcCollTime % npcFuncType)
        limitMaxTime += todayBuyTime
        GameWorld.DebugLog("    vipLV=%s,maxTime=%s,todayTime=%s,todayBuyTime=%s" % (vipLV, limitMaxTime, todayCollTime, todayBuyTime))
    npcIDCollectCntLimitDict = ReadChConfig.GetEvalChConfig("CollectNPCIDTimeLimit")
    if npcID in npcIDCollectCntLimitDict:
        limitMaxTime = npcIDCollectCntLimitDict[npcID][0]
        todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)
        GameWorld.DebugLog("    maxTime=%s,todayTime=%s" % (limitMaxTime, todayCollTime))
    collLimitInfo = GetCollTimeLimitInfo(curPlayer, npcID)
    if collLimitInfo:
        limitMaxTime, todayCollTime = collLimitInfo
        
    if limitMaxTime > 0 and todayCollTime >= limitMaxTime:
        
@@ -5309,6 +5352,19 @@
    AttackCommon.AddHurtValue(curNPC, curPlayer.GetPlayerID(), ChConfig.Def_NPCHurtTypePlayer, 1)
    return
def GetCollTimeLimitInfo(curPlayer, npcID):
    ## 获取采集次数限制信息
    npcIDCollectCntLimitDict = ReadChConfig.GetEvalChConfig("CollectNPCIDTimeLimit")
    for npcIDTuple in npcIDCollectCntLimitDict.keys():
        if npcID not in npcIDTuple:
            continue
        limitMaxTime = npcIDCollectCntLimitDict[npcIDTuple][0]
        todayCollTime = 0
        for collNPCID in npcIDTuple:
            todayCollTime += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % collNPCID)
        GameWorld.DebugLog("    limitMaxTime=%s,todayCollTime=%s" % (limitMaxTime, todayCollTime))
        return limitMaxTime, todayCollTime
    return
## 设置玩家采集该NPC
#  @param curPlayer:玩家实例
@@ -5393,11 +5449,11 @@
    openCnt = clientData.OpenCnt
    isAutoBuy = clientData.IsAutoBuy
    isOnlyGold = clientData.IsOnlyGold
    npcIDCollectCntLimitDict = ReadChConfig.GetEvalChConfig("CollectNPCIDTimeLimit")
    if npcID not in npcIDCollectCntLimitDict:
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    collLimitInfo = GetCollTimeLimitInfo(curPlayer, npcID)
    if not collLimitInfo:
        GameWorld.DebugLog("该NPC不是自定义采集NPC箱子, 不可开启! npcID=%s" % npcID)
        return
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    GameWorld.DebugLog("OnOpenCollNPCBox...npcID=%s,openCnt=%s,isAutoBuy=%s" % (npcID, openCnt, isAutoBuy))
    DoGetCollectionNPCAwardLogic(curPlayer, npcID, isAutoBuy, openCnt, mapID, isOnlyGold)
    return
@@ -5427,22 +5483,14 @@
    curNPC = GameWorld.GetGameData().FindNPCDataByID(npcID)
    if not curNPC:
        return True
    # 根据NPC功能号
    npcFuncType = curNPC.GetFunctionType()
    npcFuncCollectCntLimitDict = ReadChConfig.GetEvalChConfig('CollectNPCFuncTimeLimit')
    limitMaxTime = 0 # 0表示不限制次数
    todayCollTime = 0
    if npcFuncType in npcFuncCollectCntLimitDict:
        vipLV = curPlayer.GetVIPLv()
        todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcCollTime % npcFuncType)
        limitMaxTime = eval(npcFuncCollectCntLimitDict[npcFuncType])
    
    # 根据NPCID
    npcIDCollectCntLimitDict = ReadChConfig.GetEvalChConfig("CollectNPCIDTimeLimit")
    if npcID in npcIDCollectCntLimitDict:
        limitMaxTime = npcIDCollectCntLimitDict[npcID][0]
        todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)
    collLimitInfo = GetCollTimeLimitInfo(curPlayer, npcID)
    if collLimitInfo:
        limitMaxTime, todayCollTime = collLimitInfo
        
    if limitMaxTime > 0:
        canCollectCnt = max(0, limitMaxTime - todayCollTime)
@@ -5544,20 +5592,13 @@
                               % (unCostCnt, itemGold, reduceGold), curPlayer.GetPlayerID())
        
    # 增加当日采集次数
    if limitMaxTime > 0:
    if collLimitInfo:
        updCollTime = todayCollTime + successCnt
        npcFuncType = curNPC.GetFunctionType()
        npcFuncCollectCntLimitDict = ReadChConfig.GetEvalChConfig('CollectNPCFuncTimeLimit')
        if npcFuncType in npcFuncCollectCntLimitDict:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcCollTime % npcFuncType, updCollTime)
            SyncCollNPCTime(curPlayer, [npcFuncType])
        if npcID in npcIDCollectCntLimitDict:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)
            SyncCollNPCTime(curPlayer, npcIDList=[npcID])
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)
        SyncCollNPCTime(curPlayer, npcIDList=[npcID])
        GameWorld.DebugLog("        增加当日采集次数: todayCollTime=%s,updCollTime=%s" % (todayCollTime, updCollTime))
        #采集成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, successCnt, [npcID])
    #采集成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, successCnt, [npcID])
    SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)
    #DataRecordPack.DR_CollectNPCOK(curPlayer, npcID, addMoney, addExp, addZhenQi, giveItemInfoList)
    return True
@@ -5734,24 +5775,11 @@
#  @param funcType:功能号,默认为0,即同步配表中全部
#  @return None
def SyncCollNPCTime(curPlayer, funcTypeList=[], npcIDList=[]):
    if not funcTypeList:
        npcFuncCollectCntLimitDict = ReadChConfig.GetEvalChConfig('CollectNPCFuncTimeLimit')
        funcTypeList = npcFuncCollectCntLimitDict.keys()
    if not npcIDList:
        collectNPCIDTimeLimit = ReadChConfig.GetEvalChConfig('CollectNPCIDTimeLimit')
        npcIDList = collectNPCIDTimeLimit.keys()
#    if funcTypeList:
#        collection = ChPyNetSendPack.tagMCFuncNPCCollectionCnt()
#        for fType in funcTypeList:
#            todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcCollTime % fType)
#            collection.Clear()
#            collection.FuncType = fType
#            collection.CollectionCnt = todayCollTime
#            collection.BuyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcBuyTime % fType)
#            NetPackCommon.SendFakePack(curPlayer, collection)
        for npcIDTuple in collectNPCIDTimeLimit.keys():
            npcIDList += list(npcIDTuple)
    if npcIDList:
        npcIDCollInfo = ChPyNetSendPack.tagMCNPCIDCollectionCntInfo()
        npcIDCollInfo.Clear()
@@ -5771,18 +5799,13 @@
#  @param curPlayer:玩家实例
#  @return None
def CollNPCTimeOnDay(curPlayer, funcTypeList=[]):
    npcFuncCollectCntLimitDict = ReadChConfig.GetEvalChConfig('CollectNPCFuncTimeLimit')
    funcTypeList = npcFuncCollectCntLimitDict.keys() if not funcTypeList else funcTypeList
    for funcType in funcTypeList:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcCollTime % funcType, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcBuyTime % funcType, 0)
    collectNPCIDTimeLimit = ReadChConfig.GetEvalChConfig('CollectNPCIDTimeLimit')
    for npcID, collCntInfo in collectNPCIDTimeLimit.items():
    for npcIDTuple, collCntInfo in collectNPCIDTimeLimit.items():
        isResetOnDay = collCntInfo[1]
        if not isResetOnDay:
            continue
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, 0)
        for npcID in npcIDTuple:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, 0)
    
    SyncCollNPCTime(curPlayer)
    return
@@ -5870,28 +5893,43 @@
#  @param queryNPCIDList:查询的NPCID列表
#  @param tick
#  @return {NPCID:cnt}
def GetNPCCntInfo(queryNPCIDList, tick):
def GetNPCCntInfo(queryNPCIDList, tick, copyMapID=None):
    npcCntDict = {}
    if not queryNPCIDList:
        return npcCntDict
    #if not queryNPCIDList:
    #    return npcCntDict
    
    gameNPCManager = GameWorld.GetNPCManager()
    GameWorld.DebugLog("GetNPCCntInfo...queryNPCIDList=%s" % (str(queryNPCIDList)))
    for index in xrange(gameNPCManager.GetNPCCount()):
        curNPC = gameNPCManager.GetNPCByIndex(index)
        curID = curNPC.GetID()
        if curID == 0:
            continue
        curNPCID = curNPC.GetNPCID()
        if curNPCID not in queryNPCIDList:
            continue
        if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
            continue
        npcCntDict[curNPCID] = npcCntDict.get(curNPCID, 0) + 1
    if isinstance(copyMapID, int):
        for index in xrange(gameNPCManager.GetNPCCountByGWIndex(copyMapID)):
            curNPC = gameNPCManager.GetNPCByIndexByGWIndex(copyMapID, index)
            curID = curNPC.GetID()
            if curID == 0:
                continue
            curNPCID = curNPC.GetNPCID()
            if queryNPCIDList and curNPCID not in queryNPCIDList:
                continue
            if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
                continue
            npcCntDict[curNPCID] = npcCntDict.get(curNPCID, 0) + 1
    else:
        for index in xrange(gameNPCManager.GetNPCCount()):
            curNPC = gameNPCManager.GetNPCByIndex(index)
            curID = curNPC.GetID()
            if curID == 0:
                continue
            curNPCID = curNPC.GetNPCID()
            if queryNPCIDList and curNPCID not in queryNPCIDList:
                continue
            if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
                continue
            npcCntDict[curNPCID] = npcCntDict.get(curNPCID, 0) + 1
                
    GameWorld.DebugLog("    npcCntDict=%s" % (str(npcCntDict)))
    return npcCntDict
@@ -5918,7 +5956,7 @@
    NetPackCommon.SendFakePack(curPlayer, npcInfoPack)
    return
def SendGameServerGoodItemRecord(mapID, npcID, playerName, playerID, itemID, equipInfo=[]):
def SendGameServerGoodItemRecord(mapID, npcID, playerName, playerID, itemID, equipInfo=[], serverGroupID=0):
    # @param equipInfo: [equipPlace, itemClassLV, itemColor, itemQuality, itemUserData]
#    GameWorld.DebugLog("检查物品是否发送GameServer: mapID=%s, npcID=%s, playerName=%s, itemID=%s" 
#                       % (mapID, npcID, playerName, itemID))
@@ -5949,13 +5987,9 @@
    if not needRecord:
        return
    
    dropEquipMsg = str([playerID, playerName, mapID, npcID, itemID, itemUserData, weightValue])
    dropEquipMsg = str([playerID, playerName, mapID, npcID, itemID, itemUserData, weightValue, serverGroupID])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'BossDropGoodItem', dropEquipMsg, len(dropEquipMsg))
    GameWorld.DebugLog("发送GameServer记录拾取掉落好物品: %s" % dropEquipMsg, playerID)
    msgList = [playerName, playerID, mapID, npcID, itemID, itemUserData]
    PlayerControl.WorldNotify(0, 'DropRecord' , msgList)
    return
#// A5 52 购买功能NPC采集次数 #tagCMBuyCollectionCnt