hxp
2019-05-14 92422444e4113c2b525a74b5b3cc29ec0c9e309d
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -50,6 +50,7 @@
import PlayerBossReborn
import PlayerFairyCeremony
import PlayerNewFairyCeremony
import GameLogic_CrossGrassland
import PlayerWeekParty
import PlayerActLogin
import FamilyRobBoss
@@ -94,8 +95,6 @@
        
    #初始化处理间隔
    curNPC.SetIsNeedProcess(False)
    #设定致命一击伤害百分比
    curNPC.SetSuperHit(ChConfig.Def_SuperHitPercent)
    #初始化这个NPC的时钟
    curNPC.SetTickTypeCount(ChConfig.TYPE_NPC_Tick_Count)
    return
@@ -1223,7 +1222,7 @@
                    itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
                    if not itemData:
                        continue
                    itemJob = itemData.GetJobLimit() / 100
                    itemJob = itemData.GetJobLimit()
                    if itemJob and itemJob != curPlayer.GetJob():
                        # 非本职业可用,不掉落
                        GameWorld.DebugLog("全服击杀次数必掉,非本职业可用,不掉落! itemID=%s" % itemID)
@@ -1237,7 +1236,7 @@
                        itemData = GameWorld.GetGameData().GetItemByTypeID(rItemID)
                        if not itemData:
                            continue
                        itemJob = itemData.GetJobLimit() / 100
                        itemJob = itemData.GetJobLimit()
                        if itemJob and itemJob != curPlayer.GetJob():
                            # 非本职业可用,不掉落
                            GameWorld.DebugLog("全服击杀次数必掉随机,非本职业可用,不掉落! rItemID=%s" % rItemID)
@@ -1276,7 +1275,7 @@
                    if itemData.GetItemColor() != color:
                        continue
                    suiteID = itemData.GetSuiteID()
                    itemJob = itemData.GetJobLimit() / 100
                    itemJob = itemData.GetJobLimit()
                    itemPlace = itemData.GetEquipPlace()
                    itemID = itemData.GetItemTypeID()
                    if itemPlace not in filterItemIDDict:
@@ -1402,7 +1401,7 @@
            if not itemData:
                GameWorld.ErrLog("掉落物品ID不存在, dropItemID=%s" % dropItemID)
                continue
            itemJob = itemData.GetJobLimit() / 100
            itemJob = itemData.GetJobLimit()
            if isJobLimit and itemJob and itemJob != curPlayer.GetJob():
                # 非本职业可用,不掉落
                #GameWorld.DebugLog("非本职业可用,不掉落! dropItemID=%s" % dropItemID)
@@ -1941,6 +1940,67 @@
        
    return
#// B4 0C 召唤私有专属木桩怪 #tagCMSummonPriWoodPile
#
#struct    tagCMSummonPriWoodPile
#{
#    tagHead        Head;
#    DWORD        NPCID;
#    BYTE        Count;    //默认1个,最多5个
#};
def OnSummonPriWoodPile(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    npcID = clientData.NPCID
    count = clientData.Count
    SummonPriWoodPile(curPlayer, npcID, count)
    return
def SummonPriWoodPile(curPlayer, npcID, count):
    ''' 召唤私有专属木桩怪
    '''
    maxCount = 5
    nowCount = 0
    # 只允许存在一个私有木桩
    indexList = range(curPlayer.GetSummonCount())
    for index in indexList[::-1]:
        summonNPC = curPlayer.GetSummonNPCAt(index)
        if not summonNPC:
            continue
        npcType = summonNPC.GetType()
        if npcType not in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
            continue
        if nowCount >= maxCount or summonNPC.GetNPCID() != npcID:
            SetDeadEx(summonNPC)
        else:
            nowCount += 1
    summonCount = min(count, maxCount - nowCount)
    #GameWorld.DebugLog("召唤: count=%s,maxCount=%s,nowCount=%s,summonCount=%s"
    #                   % (count, maxCount, nowCount, summonCount))
    if summonCount <= 0:
        return
    for _ in xrange(summonCount):
        summonNPC = curPlayer.SummonNewNPC()
        #设置召唤兽基础信息
        summonNPC.SetNPCTypeID(npcID)
        #初始化
        InitNPC(summonNPC)
        #玩家召唤兽列表添加召唤兽,召唤兽添加主人
        summonNPC.SetOwner(curPlayer)
        summonNPC.SetDict(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID, curPlayer.GetPlayerID())
        #将召唤兽召唤出来
        #玩家周围随机出生点
        #技能召唤坐标 ChConfig.Def_SummonAppearDist
        summonPos = GameMap.GetEmptyPlaceInArea(curPlayer.GetPosX(), curPlayer.GetPosY(), 3)
        summonNPC.Reborn(summonPos.GetPosX(), summonPos.GetPosY())
    return
## 设置npc死亡及自身处理(请不要将游戏逻辑加在此函数中)
#  @param curNPC:npc实例
#  @return 
@@ -1995,31 +2055,34 @@
    return
def GameServer_KillGameWorldBoss(bossID, killPlayerName, hurtValue, isNotify=True, killerIDList=[]):
    dataMapID = GameWorld.GetGameWorld().GetMapID()
    mapID = GameWorld.GetGameWorld().GetMapID()
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    killMsg = str([bossID, killPlayerName, hurtValue, isNotify, realMapID, dataMapID, copyMapID, killerIDList])
    killMsg = str([bossID, killPlayerName, hurtValue, isNotify, mapID, realMapID, 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))
    GameWorld.DebugLog("Boss被击杀: bossID=%s,mapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s" % (bossID, mapID, realMapID, copyMapID, killerIDList))
    return
def GameServe_GameWorldBossState(bossID, isAlive):
    dataMapID = GameWorld.GetGameWorld().GetMapID()
    mapID = GameWorld.GetGameWorld().GetMapID()
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    stateMsg = str([bossID, isAlive, dataMapID, realMapID, copyMapID])
    stateMsg = str([bossID, isAlive, mapID, 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))
    GameWorld.DebugLog("Boss状态变更: bossID=%s,isAlive=%s,mapID=%s,realMapID=%s,copyMapID=%s"
                       % (bossID, isAlive, mapID, realMapID, copyMapID))
    if not isAlive:
        if dataMapID in ChConfig.Def_CrossZoneMapTableName:
            tableName = ChConfig.Def_CrossZoneMapTableName[dataMapID]
        if mapID in ChConfig.Def_CrossZoneMapTableName:
            tableName = ChConfig.Def_CrossZoneMapTableName[mapID]
            realMapID = GameWorld.GetGameWorld().GetRealMapID()
            copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
            zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID)
            zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, mapID, copyMapID)
            if not zoneIpyData:
                return
            zoneID = zoneIpyData.GetZoneID()
            GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0)
        elif mapID in ChConfig.Def_CrossDynamicLineMap:
            zoneID = FBCommon.GetCrossDynamicLineMapZoneID()
            GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0)
        else:
            GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID, 0)
@@ -3553,14 +3616,13 @@
    def DoHPPerLogic(self, dropType, ownerID):
        curNPC = self.__Instance
        curNPCID = curNPC.GetNPCID()
        hpPerLogicNPCIDList = ReadChConfig.GetEvalChConfig('HPPerLogicNPCIDList')
        if curNPCID not in hpPerLogicNPCIDList:
        hpPerLogicNPCIDDict = IpyGameDataPY.GetFuncEvalCfg('BossHPInformation', 1, {})
        hpPerLogicList = GameWorld.GetDictValueByKey(hpPerLogicNPCIDDict, curNPCID)
        if not hpPerLogicList:
            return
        hpPerLogicDict = ReadChConfig.GetEvalChConfig('HPPerLogic_%s' % curNPCID)
        hpPerList = sorted(hpPerLogicDict.keys(), reverse=True)
        hpPerList, sysMark = hpPerLogicList
        hpPerList = sorted(hpPerList, reverse=True)
        nowHPPer = GameObj.GetHP(curNPC) * 100 / GameObj.GetMaxHP(curNPC) # 当前百分比
        hpPerLogicMark = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_HPPerLogicMark)
        logicHPPerList = hpPerList[hpPerLogicMark:]
@@ -3573,16 +3635,12 @@
            #GameWorld.DebugLog("DoHPPerLogic npcID=%s,hpPerLogicDict=%s,nowHPPer=%s,hpPerLogicMark=%s,logicHPPerList=%s" 
            #                   % (curNPCID, str(hpPerLogicDict), nowHPPer, hpPerLogicMark, str(logicHPPerList)))
            
            isNotify, dropItemTemplate, addPrestigeFormat = hpPerLogicDict[hpPer]
            if isNotify:
                PlayerControl.WorldNotify(0, "FB_liubo_0", [GameWorld.GetMap().GetMapID(), curNPCID, hpPer])
            PlayerControl.WorldNotify(0, sysMark, [curNPCID, hpPer])
            
#            if dropItemTemplate > 0:
#                self.__DropItemByTemplate(dropItemTemplate, dropType, ownerID)
#                PlayerControl.WorldNotify(0, "GeRen_admin_481766", [GameWorld.GetMap().GetMapID(), curNPCID, curNPCID])
            if addPrestigeFormat != '':
                self.__GiveNearbyPlayerPrestige(addPrestigeFormat, ChConfig.Def_Matrix_Six)
            
            hpPerLogicMark += 1
            #GameWorld.DebugLog("DoHPPerLogic update hpPerLogicMark=%s" % (hpPerLogicMark))
@@ -3707,7 +3765,6 @@
        ############################################
        #初始化状态
        curNPC.SetSpeed(curNPC.GetOrgSpeed())
        curNPC.SetSuperHit(ChConfig.Def_SuperHitPercent)
        curNPC.SetAtkInterval(curNPC.GetBaseAtkInterval())
#        #先清空异常
@@ -3893,11 +3950,11 @@
        #杀死NPC, 触发任务
        self.__EventKillNpc()
            
        #mapID = GameWorld.GetMap().GetMapID()
        mapID = GameWorld.GetMap().GetMapID()
        killerName = "" if not self.__Killer else self.__Killer.GetPlayerName()
        # 记录boss击杀信息的NPC
        bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID)
        if bossIpyData:
        if bossIpyData and mapID not in [ChConfig.Def_FBMapID_ZhuXianBoss, ChConfig.Def_FBMapID_SealDemon]:
            if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                killerName = FamilyRobBoss.FamilyOwnerBossOnKilled(curNPC, self.__OwnerHurtID)
            #KillerJob = 0 if not self.__Killer else self.__Killer.GetJob()
@@ -4101,10 +4158,10 @@
        mapID = GameWorld.GetMap().GetMapID()
        mapID = FBCommon.GetRecordMapID(mapID)
        isGameBoss = ChConfig.IsGameBoss(curNPC)
        if mapID in [ChConfig.Def_FBMapID_MunekadoTrial, ChConfig.Def_FBMapID_DemonKing]:
            return
        if isGameBoss:
            GameWorld.Log("NPC开始掉落: npcID=%s,dropPlayerID=%s" % (npcID, dropPlayer.GetPlayerID()), dropPlayer.GetPlayerID())
        if mapID == ChConfig.Def_FBMapID_MunekadoTrial:
            return
        ipyDrop = GetNPCDropIpyData(npcID)
        if not ipyDrop:
            if isGameBoss:
@@ -5086,6 +5143,354 @@
            return
        return curItem
    
    ##----------------------------------------- 归属 -----------------------------------------------
    def RefreshDropOwner(self, tick, refreshInterval=3000, isDead=False):
        ## 刷新boss掉落归属
        # @return: 可攻击的掉落归属目标玩家
        curNPC = self.__Instance
        tagObj = None # 即将攻击的目标, 归属最大伤血取最大伤血玩家或队伍队员,其他取最大仇恨
        ownerType, ownerID = 0, 0
        dropOwnerType = GetDropOwnerType(curNPC)
        if isDead:
            GameWorld.Log("Boss死亡: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s"
                          % (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType))
        if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:
            maxHurtObj = self.RefreshHurtList(tick, refreshInterval)
            if maxHurtObj:
                ownerType, ownerID = maxHurtObj.GetValueType(), maxHurtObj.GetValueID()
                if ownerType == ChConfig.Def_NPCHurtTypeTeam:
                    tagObj = self.__GetMaxHurtTeamPlayer(ownerID, isDead)
                elif ownerType == ChConfig.Def_NPCHurtTypePlayer:
                    tagObj = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
        elif dropOwnerType == ChConfig.DropOwnerType_Family:
            ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(self, curNPC, tick, refreshInterval)
            if ownerInfo:
                tagObj, ownerFamilyID = ownerInfo
                ownerType, ownerID = ChConfig.Def_NPCHurtTypeFamily, ownerFamilyID
        elif dropOwnerType == ChConfig.DropOwnerType_Contend:
            tagObj = self.__RefreshContendOwner()
            if tagObj:
                ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, tagObj.GetPlayerID()
        if isDead:
            GameWorld.Log("ownerType=%s, ownerID=%s, tagObjID=%s" % (ownerType, ownerID, 0 if not tagObj else tagObj.GetPlayerID()))
        # 没有攻击目标,则刷新仇恨,支持主动怪
        if not tagObj:
            angryObjType, maxAngryObj = None, None
            self.RefreshAngryList(tick, refreshInterval, isUpdAngry=True)
            maxAngry = self.GetMaxAngryTag()
            if maxAngry:
                angryID = maxAngry.GetObjID()
                angryObjType = maxAngry.GetObjType()
                #GameWorld.DebugLog("最大仇恨目标: ID=%s, Type=%s" % (angryID, angryObjType))
                maxAngryObj = GameWorld.GetObj(angryID, angryObjType)
            tagObj = maxAngryObj
            if angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj and not ownerType:
                if dropOwnerType == ChConfig.DropOwnerType_Contend:
                    ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID()
                elif maxAngryObj.GetTeamID():
                    ownerType, ownerID = ChConfig.Def_NPCHurtTypeTeam, maxAngryObj.GetTeamID()
                else:
                    ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID()
            if isDead:
                GameWorld.Log("angryObj, ownerType=%s, ownerID=%s" % (ownerType, ownerID))
        self.UpdateDropOwner(tick, ownerType, ownerID, isDead)
        return tagObj
    def __RefreshContendOwner(self):
        ## 刷新boss争夺归属者,归属移除时不做刷新新归属,默认由后面的仇恨刷新
        curNPC = self.__Instance
        ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID)
        ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)
        if not ownerID or ownerType != ChConfig.Def_NPCHurtTypePlayer:
            return
        owner = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
        if not owner:
            return
        if not owner.GetVisible():
            GameWorld.DebugLog("竞争归属玩家不可见,移除归属!playerID=%s" % ownerID)
            return
        if owner.GetHP() <= 0 or owner.GetPlayerAction() == IPY_GameWorld.paDie:
            GameWorld.DebugLog("竞争归属玩家死亡,移除归属!playerID=%s" % ownerID)
            return
        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        if not self.GetIsInRefreshPoint(owner.GetPosX(), owner.GetPosY(), refreshPoint):
            GameWorld.DebugLog("竞争归属玩家不在boss范围里,移除归属!playerID=%s" % ownerID)
            return
        #GameWorld.DebugLog("竞争归属玩家归属正常!playerID=%s" % ownerID)
        return owner
    def __GetMaxHurtTeamPlayer(self, teamID, isDead):
        ## 获取最大伤血队伍中攻击的目标队员
        curNPC = self.__Instance
        curTeam = GameWorld.GetTeamManager().FindTeam(teamID)
        if curTeam:
            refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
            if isDead:
                GameWorld.Log("队伍成员数: teamID=%s,memberCount=%s" % (teamID, curTeam.GetMemberCount()))
            for i in xrange(curTeam.GetMemberCount()):
                curTeamPlayer = curTeam.GetMember(i)
                if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                    if isDead:
                        GameWorld.Log("    i=%s, 队员为空!" % i)
                    continue
                if curTeamPlayer.GetHP() <= 0:
                    if isDead:
                        GameWorld.Log("    i=%s, 队员血量为0!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))
                    continue
                if not curTeamPlayer.GetVisible():
                    if isDead:
                        GameWorld.Log("    i=%s, 队员不可见!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID()))
                    continue
                if isDead:
                    GameWorld.Log("    i=%s, 队员坐标(%s, %s)! memPlayerID=%s" % (i, curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), curTeamPlayer.GetPlayerID()))
                if self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):
                    return curTeamPlayer
        else:
            GameWorld.ErrLog("找不到该队伍: teamID=%s" % teamID)
        return
    def UpdateDropOwner(self, tick, ownerType=0, ownerID=0, isDead=False):
        curNPC = self.__Instance
        npcID = curNPC.GetNPCID()
        dropOwnerType = GetDropOwnerType(curNPC)
        if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry, ChConfig.DropOwnerType_Family, ChConfig.DropOwnerType_Contend]:
            #GameWorld.DebugLog("不需要展示掉落归属的NPC! npcID=%s,dropOwnerType=%s" % (npcID, dropOwnerType))
            return
        lastDropOwnerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID)
        lastDropOwnerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)
        key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)
        if lastDropOwnerID and (lastDropOwnerType != ownerType or lastDropOwnerID != ownerID):
            GameWorld.Log("归属变更, 清除旧归属! key=%s,ownerType=%s,ownerID=%s,lastDropOwnerType=%s,lastDropOwnerID=%s"
                          % (key, ownerType, ownerID, lastDropOwnerType, lastDropOwnerID))
            self.__DelDropOwnerBuff(dropOwnerType, lastDropOwnerType, lastDropOwnerID, tick)
        killerDict, curTeam, hurtType, hurtID = {}, None, 0, 0
        # 更新归属
        curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerID, ownerID)
        curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerType, ownerType)
        if isDead:
            GameWorld.Log("Boss归属: key=%s,ownerType=%s,ownerID=%s" % (key, ownerType, ownerID))
        # 刷新归属
        if ownerType == ChConfig.Def_NPCHurtTypePlayer:
            curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
            if curPlayer:
                playerID = curPlayer.GetPlayerID()
                hurtType, hurtID = ChConfig.Def_NPCHurtTypePlayer, playerID
                killerDict[playerID] = curPlayer
                self.__AddDropOwnerPlayerBuff(curPlayer, tick)
                if dropOwnerType == ChConfig.DropOwnerType_Contend:
                    curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, curNPC.GetID())
        elif ownerType == ChConfig.Def_NPCHurtTypeTeam:
            curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)
            if not curTeam:
                return
            # 因为有击杀次数限制,所以不是所有的队员都可以获得归属,所以这里设置为特殊指定玩家掉落
            hurtType, hurtID = ChConfig.Def_NPCHurtTypeSpecial, 0
            if isDead:
                GameWorld.Log("队伍成员数: %s" % (curTeam.GetMemberCount()))
            refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
            for i in xrange(curTeam.GetMemberCount()):
                curTeamPlayer = curTeam.GetMember(i)
                if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                    if isDead:
                        GameWorld.Log("    i=%s, 成员不存在!" % (i))
                    continue
                if curTeamPlayer.GetCopyMapID() == GameWorld.GetGameWorld().GetCopyMapID() \
                    and self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \
                    and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False) and curTeamPlayer.GetVisible():
                    self.__AddDropOwnerPlayerBuff(curTeamPlayer, tick)
                    killerDict[curTeamPlayer.GetPlayerID()] = curTeamPlayer
                    if isDead:
                        GameWorld.Log("    i=%s, 成员有归属权! memPlayerID=%s,背包剩余空格=%s"
                                      % (i, curTeamPlayer.GetPlayerID(), ItemCommon.GetItemPackSpace(curTeamPlayer, IPY_GameWorld.rptItem)))
                # 不同线、或者距离超出boss范围的队员不加归属buff
                else:
                    isOk = BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
                    if isOk:
                        GameWorld.DebugLog("删除归属队员buff: teamID=%s,playerID=%s" % (ownerID, curTeamPlayer.GetPlayerID()))
                    if isDead:
                        GameWorld.Log("    i=%s, 成员无归属权! memPlayerID=%s,copyMapID=%s,pos(%s,%s),CheckKillNPCByCnt=%s"
                                      % (i, curTeamPlayer.GetPlayerID(), curTeamPlayer.GetCopyMapID(),
                                         curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(),
                                         AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False)))
        elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
            hurtType, hurtID = ChConfig.Def_NPCHurtTypeFamily, ownerID
            refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
            copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
            for index in xrange(copyPlayerMgr.GetPlayerCount()):
                player = copyPlayerMgr.GetPlayerByIndex(index)
                if not player:
                    continue
                # 归属仙盟 且 在boss区域内
                if player.GetFamilyID() == ownerID and self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint) and player.GetVisible():
                    self.__AddDropOwnerPlayerBuff(player, tick)
                else:
                    isOk = BuffSkill.DelBuffBySkillID(player, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
                    if isOk:
                        GameWorld.DebugLog("删除非归属仙盟成员buff: teamID=%s,playerID=%s" % (ownerID, player.GetPlayerID()))
        if isDead:
            #key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)
            teamID = curTeam.GetTeamID() if curTeam else 0
            if killerDict:
                PyGameData.g_npcKillerInfo[key] = killerDict, curTeam, hurtType, hurtID
            elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
                PyGameData.g_npcKillerInfo[key] = {}, None, hurtType, hurtID
            GameWorld.Log("Boss被击杀: npcID=%s,key=%s,playerIDList=%s,teamID=%s,hurtType=%s,hurtID=%s"
                          % (npcID, key, killerDict.keys(), teamID, hurtType, hurtID))
        return
    def __AddDropOwnerPlayerBuff(self, curPlayer, tick):
        curNPC = self.__Instance
        findBuff = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff)[0]
        if not findBuff:
            SkillCommon.AddBuffBySkillType_NoRefurbish(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
            GameWorld.DebugLog("添加归属buff: playerID=%s" % curPlayer.GetPlayerID())
        return
    def __DelDropOwnerBuff(self, dropOwnerType, ownerType, ownerID, tick):
        curNPC = self.__Instance
        if ownerType == ChConfig.Def_NPCHurtTypePlayer:
            curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
            if not curPlayer:
                return
            GameWorld.DebugLog("删除归属玩家buff: playerID=%s" % (ownerID))
            BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
            if dropOwnerType == ChConfig.DropOwnerType_Contend:
                curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, 0)
        elif ownerType == ChConfig.Def_NPCHurtTypeTeam:
            curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)
            if not curTeam:
                return
            GameWorld.DebugLog("删除归属队伍buff: teamID=%s" % (ownerID))
            for i in xrange(curTeam.GetMemberCount()):
                curTeamPlayer = curTeam.GetMember(i)
                if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                    continue
                BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
        return
    def DelayDropOwnerBuffDisappearTime(self):
        ''' 延迟掉落归属buff消失时间 '''
        curNPC = self.__Instance
        ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID)
        ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)
        if ownerType == ChConfig.Def_NPCHurtTypePlayer:
            curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
            if not curPlayer:
                return
            self.__SetDropOwnerBuffDisappearTime(curPlayer)
        elif ownerType == ChConfig.Def_NPCHurtTypeTeam:
            curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)
            if not curTeam:
                return
            for i in xrange(curTeam.GetMemberCount()):
                curTeamPlayer = curTeam.GetMember(i)
                if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
                    continue
                self.__SetDropOwnerBuffDisappearTime(curTeamPlayer)
        elif ownerType == ChConfig.Def_NPCHurtTypeFamily:
            copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
            for index in xrange(copyPlayerMgr.GetPlayerCount()):
                player = copyPlayerMgr.GetPlayerByIndex(index)
                if not player:
                    continue
                self.__SetDropOwnerBuffDisappearTime(player)
        return
    def __SetDropOwnerBuffDisappearTime(self, curPlayer):
        ''' 设置掉落归属buff消失时间 '''
        curNPC = self.__Instance
        findSkill = GameWorld.GetGameData().GetSkillBySkillID(ChConfig.Def_SkillID_DropOwnerBuff)
        if not findSkill:
            return
        buffType = SkillCommon.GetBuffType(findSkill)
        buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)
        if buffTuple == ():
            return
        RemainTime = 10000 # 延迟10秒消失
        tick = GameWorld.GetGameWorld().GetTick()
        buffStateManager = buffTuple[0]
        for index in xrange(buffStateManager.GetBuffCount()):
            curBuff = buffStateManager.GetBuff(index)
            buffSkill = curBuff.GetSkill()
            if buffSkill.GetSkillTypeID() != ChConfig.Def_SkillID_DropOwnerBuff:
                continue
            if curNPC.GetID() != curBuff.GetOwnerID():
                #GameWorld.DebugLog("非buff归属着,不设置消失时间!", curPlayer.GetPlayerID())
                break
            curBuff.SetCalcStartTick(tick)
            curBuff.SetRemainTime(RemainTime)
            # 通知buff刷新
            buffStateManager.Sync_RefreshBuff(index, curBuff.GetRemainTime())
            #GameWorld.DebugLog("掉落归属buff消失时间: RemainTime=%s" % (RemainTime), curPlayer.GetPlayerID())
            break
        return
    ##--------------------------------------------- -----------------------------------------------
def OnPlayerKillNPCPlayer(curPlayer, defender, tick):
    ## 玩家击杀了NPC相关的玩家
    contendNPCObjID = defender.GetDictByKey(ChConfig.Def_PlayerKey_ContendNPCObjID)
    if contendNPCObjID:
        curNPC = GameWorld.FindNPCByID(contendNPCObjID)
        if not curNPC:
            return
        dropOwnerType = GetDropOwnerType(curNPC)
        if dropOwnerType != ChConfig.DropOwnerType_Contend:
            return
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("玩家击杀竞争归属者! defPlayerID=%s,contendNPCObjID=%s,npcID=%s"
                           % (defender.GetPlayerID(), contendNPCObjID, curNPC.GetNPCID()), playerID)
        npcControl = NPCControl(curNPC)
        npcControl.UpdateDropOwner(tick, ChConfig.Def_NPCHurtTypePlayer, playerID, False)
    return
#---------------------------------------------------------------------
def SendVirtualItemDrop(player, itemID, posX, posY, userDataStr):
    #通知客户端假物品掉落
@@ -5138,21 +5543,6 @@
    return max(value / pow(10, nlen), 1)
Def_CollNPCCfg_Len = 10
(
Def_CollNPCCfg_CanTogether, # 是否允许同时采集
Def_CollNPCCfg_SysMsgMark, # 不可同时采集提示
Def_CollNPCCfg_CostItemInfo, # 采集消耗物品信息
Def_CollNPCCfg_PrepareTime, # 采集时间毫秒
Def_CollNPCCfg_ExpFormat, # 获得经验公式
Def_CollNPCCfg_MoneyFormat, # 获得金币公式
Def_CollNPCCfg_ZhenQi, # 获得的真气/魔魂
Def_CollNPCCfg_GiveItemModeID, # 获得的物品信息模板编号
Def_CollNPCCfg_NotCostItemNotify, # 消耗品不足提示
Def_CollNPCCfg_LimitSysMsgMark, #采集上限提示
) = range(Def_CollNPCCfg_Len)
def CheckCanCollectByNPCID(curPlayer, npcID, collectNPCIpyData):
    # 根据NPCID判断是否可以采集
    
@@ -5190,7 +5580,11 @@
    npcID = curNPC.GetNPCID()
    collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)
    if not collectNPCIpyData:
        GameWorld.DebugLog("非特定采集NPC...")
        #GameWorld.DebugLog("非特定采集NPC...")
        return False
    if collectNPCIpyData.GetIsMissionCollectNPC():
        #GameWorld.DebugLog("任务采集物暂不处理")
        return False
    
    if not CheckCanCollectByNPCID(curPlayer, npcID, collectNPCIpyData):
@@ -5293,6 +5687,10 @@
        GameWorld.DebugLog("    非特定采集NPC...npcID=%s" % npcID)
        return
    
    if collectNPCIpyData.GetIsMissionCollectNPC():
        #GameWorld.DebugLog("任务采集物暂不处理")
        return
    PlayerState.DoCollectingLostHP(curPlayer, collectNPCIpyData, tick, True)
    
    if GameWorld.IsCrossServer():
@@ -5318,33 +5716,106 @@
        DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData)
    return
#// A2 34 自定义场景中获取采集奖励 #tagCMGetCustomSceneCollectAward
#
#struct    tagCMGetCustomSceneCollectAward
#{
#    tagHead        Head;
#    DWORD        NPCID;    //采集的NPCID
#};
def OnGetCustomSceneCollectAward(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    npcID = clientData.NPCID
    if not curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        GameWorld.DebugLog("非自定义场景中,无法获取定义采集奖励!")
        return
    collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)
    if collectNPCIpyData:
        DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData)
    return
def DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData, collectCnt=1):
    GameWorld.DebugLog("给采集奖励: npcID=%s,collectCnt=%s" % (npcID, collectCnt))
    if collectCnt <= 0:
        return
    if collectNPCIpyData.GetIsMissionCollectNPC():
        #GameWorld.DebugLog("任务采集物暂不处理")
        return
    
    isMaxTime = False # 是否达到了采集最大次数
    limitMaxTime = collectNPCIpyData.GetMaxCollectCount()
    if limitMaxTime > 0:
        todayCollTime = GetTodayCollectCount(curPlayer, npcID)
        canCollectCnt = max(0, limitMaxTime - todayCollTime)
        collectCnt = min(collectCnt, canCollectCnt)
        if collectCnt <= 0:
            GameWorld.DebugLog("    该NPC已达到最大采集次数: todayCollTime=%s,limitMaxTime=%s" % (todayCollTime, limitMaxTime))
            GameWorld.DebugLog("    该NPC已达到最大采集次数: npcID=%s,todayCollTime=%s,limitMaxTime=%s" % (npcID, todayCollTime, limitMaxTime))
            return
        
        updCollTime = todayCollTime + collectCnt
        curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)
        updCollTime = curCollTime + collectCnt
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)
        SyncCollNPCTime(curPlayer, [npcID])
        GameWorld.DebugLog("        增加当日采集次数: todayCollTime=%s,updCollTime=%s" % (todayCollTime, updCollTime))
    giveItemList = collectNPCIpyData.GetCollectAward()
    if giveItemList:
        itemID, itemCount, isAuctionItem = giveItemList
        ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])
        GameWorld.DebugLog("    增加采集次数: npcID=%s,todayCollTime=%s,curCollTime=%s,updCollTime=%s" % (npcID, todayCollTime, curCollTime, updCollTime))
        isMaxTime = todayCollTime + collectCnt >= limitMaxTime
    awardItemList = []
    collectAwardCfg = collectNPCIpyData.GetCollectAward()
    collectAppointAwardCfg = collectNPCIpyData.GetCollectAppointAward()
    if collectAppointAwardCfg:
        collTotalTime = min(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID) + 1, ChConfig.Def_UpperLimit_DWord)
        if collTotalTime in collectAppointAwardCfg:
            awardItemList.append(collectAppointAwardCfg[collTotalTime])
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID, collTotalTime)
        GameWorld.DebugLog("    采集次数定制奖励: collTotalTime=%s,awardItemList=%s" % (collTotalTime, awardItemList))
    if not awardItemList:
        alchemyDiffLV = collectNPCIpyData.GetAlchemyDiffLV()
        giveItemWeightList = []
        if alchemyDiffLV:
            curAlchemyLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
            for itemInfo in collectAwardCfg:
                itemID = itemInfo[1][0]
                itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
                if not itemData:
                    continue
                if ItemCommon.GetItemClassLV(itemData) > curAlchemyLV + alchemyDiffLV:
                    continue
                giveItemWeightList.append(itemInfo)
        else:
            giveItemWeightList = collectAwardCfg
        GameWorld.DebugLog("    常规采集物品权重列表: alchemyDiffLV=%s,collectAwardCfg=%s,giveItemWeightList=%s" % (alchemyDiffLV, collectAwardCfg, giveItemWeightList))
        giveItemInfo = GameWorld.GetResultByWeightList(giveItemWeightList)
        if giveItemInfo:
            awardItemList.append(giveItemInfo)
    GameWorld.DebugLog("    最终采集奖励: awardItemList=%s" % awardItemList)
    if awardItemList:
        for itemID, itemCount, isAuctionItem in awardItemList:
            ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])
        if collectNPCIpyData.GetNotifyCollectResult():
            awardPack = ChPyNetSendPack.tagMCCollectAwardItemInfo()
            awardPack.CollectNPCID = npcID
            for itemID, itemCount, isAuctionItem in awardItemList:
                awardItem = ChPyNetSendPack.tagMCCollectAwardItem()
                awardItem.ItemID = itemID
                awardItem.Count = itemCount
                awardItem.IsAuctionItem = isAuctionItem
                awardPack.AwardItemList.append(awardItem)
            awardPack.Count = len(awardPack.AwardItemList)
            NetPackCommon.SendFakePack(curPlayer, awardPack)
    else:
        GameWorld.ErrLog("采集物品没有奖励!npcID=%s" % (npcID))
        
    #采集成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, collectCnt, [npcID])
    #SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)
    if isMaxTime:
        GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
    return
## 采集结果同步
@@ -5391,11 +5862,20 @@
def CollNPCTimeOnDay(curPlayer):
    ## 采集NPCOnDay处理
    DoResetCollectNPCTimeByType(curPlayer, [1])
    return
def DoResetCollectNPCTimeByType(curPlayer, resetTypeList=[]):
    '''重置采集物采集次数
            重置类型: 0-不重置,1-每日5点,12-灵草园重置,14-仙草园重置
    '''
    resetNPCIDList = []
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    for index in xrange(ipyDataMgr.GetCollectNPCCount()):
        ipyData = ipyDataMgr.GetCollectNPCByIndex(index)
        npcID = ipyData.GetNPCID()
        if resetTypeList and ipyData.GetCollectResetType() not in resetTypeList:
            continue
        if not ipyData.GetMaxCollectCount():
            continue
        if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID):
@@ -5404,6 +5884,7 @@
        resetNPCIDList.append(npcID)
        
    if resetNPCIDList:
        #GameWorld.DebugLog("重置采集次数: resetTypeList=%s,resetNPCIDList=%s" % (resetTypeList, resetNPCIDList), curPlayer.GetPlayerID())
        SyncCollNPCTime(curPlayer, resetNPCIDList)
    return
@@ -5696,3 +6177,45 @@
    sendPack.Value = speed
    curNPC.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())
    return
def UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount=0):
    ## 更新玩家攻击NPC次数
    GameWorld.DebugLog("更新玩家攻击NPC次数: npcID=%s,attackCount=%s,maxCount=%s" % (npcID, attackCount, maxCount))
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCAttackCount % npcID, attackCount)
    if GameWorld.IsCrossServer():
        serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)
        msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "NPCID":npcID, "AttackCount":attackCount, "MaxCount":maxCount}
        GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_NPCAttackCount, msgInfo, [serverGroupID])
    else:
        SyncNPCAttackCount(curPlayer, [npcID])
        if attackCount and attackCount >= maxCount:
            GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
    return
def CrossServerMsg_NPCAttackCount(curPlayer, msgData):
    ## 收到跨服服务器同步的攻击NPC次数
    npcID = msgData["NPCID"]
    attackCount = msgData["AttackCount"]
    maxCount = msgData["MaxCount"]
    UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount)
    return
def SyncNPCAttackCount(curPlayer, npcIDList):
    ## 同步NPC攻击次数
    if not npcIDList:
        return
    clientPack = ChPyNetSendPack.tagMCNPCAttackCountInfo()
    for npcID in npcIDList:
        attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID)
        atkCountObj = ChPyNetSendPack.tagMCNPCAttackCount()
        atkCountObj.NPCID = npcID
        atkCountObj.AttackCount = attackCount
        clientPack.NPCAttackCountList.append(atkCountObj)
    clientPack.Count = len(clientPack.NPCAttackCountList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return