ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -42,20 +42,12 @@
import FBCommon
import PlayerActivity
import PlayerSuccess
import BossHurtMng
import PlayerPrestigeSys
import GY_Query_BossFirstKill
import GameLogic_FamilyInvade
import GameLogic_GatherSoul
import FormulaControl
import PlayerBossReborn
import PlayerFairyCeremony
import PlayerCrossYaomoBoss
import PlayerActCollectWords
import PlayerNewFairyCeremony
import GameLogic_CrossGrassland
import PlayerActGarbageSorting
import PlayerActBossTrial
import PlayerTongTianLing
import CrossPlayerData
import PlayerFeastWish
@@ -63,19 +55,14 @@
import PlayerGoldInvest
import PlayerWeekParty
import NPCRealmRefresh
import NPCHurtManager
import PlayerActLogin
import PlayerActTask
import PlayerZhanling
import FamilyRobBoss
import IpyGameDataPY
import PlayerGubao
import PlayerState
import TurnAttack
import PyGameData
import PlayerTeam
import NPCHurtMgr
import PlayerVip
import GameObj
import ChNPC
@@ -129,12 +116,12 @@
            return realmNPCIpyData.GetLV()
    return curNPC.GetLV()
def GetNPCDataEx(npcID):
    ## 获取NPC扩展数据表,可热更
    npcDataEx = IpyGameDataPY.GetIpyGameDataNotLog("NPCEx", npcID)
def GetNPCDataPy(npcID):
    ## 获取NPC数据表,py自定义的表,可热更
    npcDataEx = IpyGameDataPY.GetIpyGameDataNotLog("NPC", npcID)
    if not npcDataEx:
        if False: # 不可能成立的条件,只为了 . 出代码提示
            npcDataEx = IpyGameDataPY.IPY_NPCEx()
            npcDataEx = IpyGameDataPY.IPY_NPC()
        return npcDataEx
    return npcDataEx
@@ -142,11 +129,9 @@
def SetRealmLV(curNPC, realmLV): return curNPC.SetMAtkMin(realmLV)      # NPC表中此字段含义改成境界等级
def GetIsLVSuppress(curNPC): return curNPC.GetWindDef() # 风防代表是否等级压制
def GetFightPowerLackAtkLimit(curNPC): # 战力不足限制攻击,默认不限制
    npcDataEx = GetNPCDataEx(curNPC.GetNPCID())
    return npcDataEx.GetFightPowerLackAtkLimit() if npcDataEx else 0
def GetSuppressFightPower(curNPC):
    npcDataEx = GetNPCDataEx(curNPC.GetNPCID())
    return npcDataEx.GetSuppressFightPower() if npcDataEx else curNPC.GetThunderDef() # 雷防代表压制战力
    return 0
def GetSuppressFightPower(curNPC): # 压制战力
    return 0
def SetSuppressFightPower(curNPC, value): return curNPC.SetThunderDef(min(value, ShareDefine.Def_UpperLimit_DWord))
def GetCommendFightPower(curNPC): return curNPC.GetFireDef() # 火防代表推荐战力
def GetDropOwnerType(curNPC): return curNPC.GetThunderAtk() # 雷攻代表掉落归属类型
@@ -158,122 +143,6 @@
def GetNPCSeries(curNPC): return curNPC.GetPoisionDef() # 毒防字段代表NPC系,按二进制位区分
def DoNPCAttrStrengthen(curNPC, isReborn, isDyn=False):
    '''NPC属性增强, NPC属性成长由两个因素决定
    1.NPC成长等级,成长等级决定成长属性,与成长表结合使用
            可设置地图NPC等级动态成长,但是已经刷新出来的NPC等级不变,动态等级变更后刷新的NPC等级才会使用最新等级
    2.玩家人数因素,决定NPC属性的额外成长系数,可单独使用,或者和1一起使用
            可设置马上刷新NPC属性
            除血量外,其他属性会根据动态因素直接变更
            血量会根据血量百分比动态变更至相应的百分比
    '''
    npcID = curNPC.GetNPCID()
    strengthenIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCStrengthen", npcID)
    if not strengthenIpyData:
        #GameWorld.DebugLog("该NPC属性不成长!npcID=%s" % npcID)
        return
    strengthenLV = 0
    strengthenPlayerCnt = 0
    gameFB = GameWorld.GetGameFB()
    if strengthenIpyData.GetIsStrengthenByPlayerCount():
        if FamilyRobBoss.IsHorsePetRobBoss(npcID):
            strengthenPlayerCnt = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_HorsePetRobBossPlayerCount)
        else:
            strengthenPlayerCnt = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt)
            if not strengthenPlayerCnt:
                GameWorld.ErrLog("NPC配置了按玩家人数成长类型,但是无法获取到对应的玩家人数!npcID=%s" % (npcID))
                return
    lvStrengthenType = strengthenIpyData.GetLVStrengthenType()
    # 根据世界等级
    if lvStrengthenType == 3:
        strengthenLV = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
    # 根据最大等级
    elif lvStrengthenType == 2:
        strengthenLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)
    # 根据平均等级
    elif lvStrengthenType == 1:
        strengthenLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenAverageLV)
    # 根据按成长等级的上下限随机
    elif lvStrengthenType == 4:
        randMinLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMinLV)
        randMaxLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)
        strengthenLV = random.randint(randMinLV, randMaxLV)
    # 根据境界难度
    elif lvStrengthenType == 5:
        realmLV = PlayerControl.GetDifficultyRealmLV(curNPC.GetSightLevel())
        realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
        if realmNPCIpyData:
            strengthenLV = realmNPCIpyData.GetLV()
        else:
            lvStrengthenType = 0
    # 木桩怪最大、平均成长等级处理,直接取归属玩家等级
    if lvStrengthenType in [1, 2] and curNPC.GetType() in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
        owner = None
        summonPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID)
        if summonPlayerID:
            owner = GameWorld.GetObj(summonPlayerID, IPY_GameWorld.gotPlayer)
        if owner:
            strengthenLV = owner.GetLV()
    if strengthenIpyData.GetCmpNPCBaseLV():
        strengthenLV = max(strengthenLV, curNPC.GetLV())
    if lvStrengthenType in [1, 2] and not strengthenLV:
        GameWorld.ErrLog("NPC配置了成长等级类型,但是无法获取到对应的成长等级值!npcID=%s,lvStrengthenType=%s" % (npcID, lvStrengthenType))
        return
    # 副本特殊指定
    npcFBAttrDict = FBLogic.GetFBNPCStrengthenAttr(curNPC, isReborn)
    if "LV" in npcFBAttrDict:
        strengthenLV = npcFBAttrDict["LV"]
    attrDict = {} #GetNPCStrengthenAttrDict(npcID, strengthenLV, strengthenPlayerCnt, strengthenIpyData)
    attrDict.update(npcFBAttrDict) # 如果副本有指定属性,则以副本为主
    if not attrDict:
        return
    # 成长等级只在重生的时候设置一次
    if isReborn and curNPC.GetCurLV() != strengthenLV:
        curNPC.SetCurLV(strengthenLV, False) # 重生的不通知等级变更,属性成长刷新后由NPC出现包通知
    befMaxHP = GameObj.GetMaxHP(curNPC)
    befHP = GameObj.GetHP(curNPC)
    #GameWorld.DebugLog("NPC属性成长刷新,isReborn=%s,npcID=%s,LV=%s,curLV=%s,befMaxHP=%s,befHP=%s,attrDict=%s"
    #                   % (isReborn, npcID, curNPC.GetLV(), curNPC.GetCurLV(), befMaxHP, befHP, attrDict))
    for attrKey, strengthenValue in attrDict.items():
        if not hasattr(curNPC, "Set%s" % attrKey):
            if attrKey == "FightPower":
                SetSuppressFightPower(curNPC, strengthenValue)
            continue
        if attrKey == "MaxHP":
            GameObj.SetMaxHP(curNPC, strengthenValue)
        else:
            strengthenValue = min(strengthenValue, ChConfig.Def_UpperLimit_DWord)
            getattr(curNPC, "Set%s" % attrKey)(strengthenValue)
        #GameWorld.DebugLog("    %s=%s" % (attrKey, strengthenValue))
    aftMaxHP = GameObj.GetMaxHP(curNPC)
    if befMaxHP != aftMaxHP:
        if isReborn:
            GameObj.SetHP(curNPC, aftMaxHP)
        elif isDyn:
            # 动态刷新属性的,血量按百分比继承
            aftHP = int(aftMaxHP * befHP / befMaxHP)
            GameObj.SetHP(curNPC, aftHP)
            curNPC.Notify_HP()
            curNPC.Notify_MaxHP()
            #GameWorld.DebugLog("    aftHP=%s,aftMaxHP=%s" % (aftHP, aftMaxHP))
    # 机器人复活初始化给技能
    if isReborn and curNPC.GetType() == ChConfig.ntRobot:
        __OnFBRobotReborn(curNPC, strengthenLV)
    return
def __OnFBRobotReborn(curNPC, npcLV):
@@ -298,27 +167,6 @@
    for skillID in skillIDList:
        skillManager.LearnSkillByID(skillID)
    FBLogic.OnRandomRobotJob(curNPC, lineRobotJobDict)
    return
def __DoGiveVSPlayerNPCSkill(curNPC, job, npcLV):
    skillManager = curNPC.GetSkillManager()
    jobSkillDict = IpyGameDataPY.GetFuncEvalCfg("XMZZRobotSkill", 1)
    if job not in jobSkillDict:
        return
    skillInfoDict = jobSkillDict[job]
    #{1:{(100, 101, 102, 103):1, 50000:100, 50100:200, 50400:300}, 2:{(200, 201, 202, 203):1, 55000:100, 55100:200, 55200:300}}
    skillIDList = []
    for skillInfo, needLV in skillInfoDict.items():
        if npcLV < needLV:
            continue
        if isinstance(skillInfo, int):
            skillIDList.append(skillInfo)
        else:
            skillIDList += list(skillInfo)
    GameWorld.DebugLog("给NPC技能: job=%s,npcLV=%s, %s" % (job, npcLV, skillIDList))
    for skillID in skillIDList:
        skillManager.LearnSkillByID(skillID)
    return
def GiveKillNPCDropPrize(curPlayer, mapID, npcCountDict, exp_rate=None, mailTypeKey=None, isMail=False, 
@@ -771,7 +619,7 @@
#===============================================================================
def GetDefaultMaxAngryNPCIDList():
    return GameLogic_FamilyInvade.GetDefaultMaxAngryNPCIDList()
    return []
#---------------------------------------------------------------------
##NPC进入战斗状态
@@ -1092,9 +940,7 @@
            #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())
            if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                FamilyRobBoss.ClearFamilyOwnerBossHurt(curNPC)
        ChNPC.OnNPCSetDead(curNPC)
        
        if npcid == IpyGameDataPY.GetFuncCfg("CrossYaomoBoss", 1):
@@ -1102,10 +948,6 @@
            
    # 清除队伍成员伤血列表
    AttackCommon.ClearTeamPlayerHurtValue(curNPC)
    # 清除自定义伤血列表
    #BossHurtMng.ClearHurtValueList(curNPC)
    NPCHurtManager.DeletePlayerHurtList(curNPC)
    NPCHurtMgr.DeletePlayerHurtList(curNPC)
    if curNPC.GetType() == ChConfig.ntRobot:
        lineID = GameWorld.GetGameWorld().GetLineID()
        lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})
@@ -1124,19 +966,18 @@
            
    # C++设置npc死亡
    notifyClient = True
    tfMgr = TurnAttack.GetTurnFightMgr()
    turnFight = tfMgr.getNPCTurnFight(objID)
    if turnFight:
        notifyClient = False # 回合制战斗的由py自己通知
        # //04 07 NPC消失#tagNPCDisappear 此处通知消失,与回合制死亡区分
        clientPack = ChNetSendPack.tagNPCDisappear()
        clientPack.NPCID = [objID]
        clientPack.Count = len(clientPack.NPCID)
        turnFight.addBatPack(clientPack)
    #tfMgr = TurnAttack.GetTurnFightMgr()
    #turnFight = tfMgr.getNPCTurnFight(objID)
    #if turnFight:
    #    notifyClient = False # 回合制战斗的由py自己通知
    #    # //04 07 NPC消失#tagNPCDisappear 此处通知消失,与回合制死亡区分
    #    clientPack = ChNetSendPack.tagNPCDisappear()
    #    clientPack.NPCID = [objID]
    #    clientPack.Count = len(clientPack.NPCID)
    #    turnFight.addBatPack(clientPack)
    curNPC.SetDead(curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason),
                   curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerType),
                   curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID), notifyClient)
    tfMgr.delNPCGUID(objID)
    return
def GameServer_KillGameWorldBoss(bossID, killPlayerName, hurtValue, isNotify=True, killerIDList=[]):
@@ -1187,7 +1028,6 @@
        key = ChConfig.Def_PDict_Boss_KillCnt % limitIndex
        newCnt = curPlayer.NomalDictGetProperty(key, 0) + 1
        PlayerControl.NomalDictSetProperty(curPlayer, key, newCnt)
        BossHurtMng.NotifyAttackBossCnt(curPlayer, limitIndex)
        GameWorld.DebugLog("更新击杀Boss次数: index=%s, todayCnt=%s, totalCnt=%s" % (limitIndex, newCnt, totalCnt), curPlayer.GetPlayerID())
        
        dataDict = {"objID":npcID, "bossID":npcID, "touchCnt":newCnt, "totalCnt":totalCnt,
@@ -1206,8 +1046,6 @@
        # 每日活动
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_WorldBOSS)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_WorldBOSS, 1)
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)
        PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)
        PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_WorldBOSS, 1)
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_WorldBoss, 1)
        PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_WorldBOSS, 1)
@@ -1223,8 +1061,6 @@
        # 每日活动
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_BOSSHome)
        PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_BOSSHome, 1)
        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)
        PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)
        PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_BOSSHome, 1)
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_BossHome, 1)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_BossHome, 1)
@@ -1242,11 +1078,7 @@
        PlayerGubao.AddGubaoItemEffValue(curPlayer, PlayerGubao.GubaoEffType_KillCrossDemonLandBoss, 1)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_CrossDemonLandBoss, 1)
    if mapID in [ChConfig.Def_FBMapID_CrossPenglai, ChConfig.Def_FBMapID_CrossDemonLand]:
        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_CrossBoss)
        PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_CrossBoss, 1)
    if npcData.GetIsBoss() == ChConfig.Def_NPCType_Boss_Dark:
        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_KillBoss)
        
    # 个人首杀记录
    ipyData = IpyGameDataPY.GetIpyGameDataNotLog("BOSSFirstKill", npcID)
@@ -2074,8 +1906,6 @@
        #清除所有身上buff
        self.ClearAllBuff(isClearAuraBuff)
        curNPC = self.__Instance
        NPCHurtManager.ClearPlayerHurtList(curNPC)
        NPCHurtMgr.ClearPlayerHurtList(curNPC)
        return True
    
    #---------------------------------------------------------------------
@@ -2424,9 +2254,7 @@
            ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', curNPCID)
            if ipyData:
                GameServe_GameWorldBossState(curNPCID, 1)
                if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                    FamilyRobBoss.FamilyOwnerBossOnReborn(curNPC)
        # 检查是否有光环, 在重生时处理,不然可能导致有些无战斗逻辑的怪物无法套上光环buff
        skillManager = curNPC.GetSkillManager()
        for index in xrange(skillManager.GetSkillCount()):
@@ -2444,13 +2272,13 @@
    
    def __notifyAppear(self):
        ## //04 06 NPC出现#tagNPCAppear,可能也有 04 08 玩家召唤NPC出现#tagPlayerSummonNPCAppear,卡牌先简化,只使用0406
        curNPC = self.__Instance
        objID = curNPC.GetID()
        turnFight = TurnAttack.GetTurnFightMgr().getNPCTurnFight(objID)
        if not turnFight:
            # 非回合制怪保留原通知
            curNPC.NotifyAppear()
            return
        #curNPC = self.__Instance
        #objID = curNPC.GetID()
        #turnFight = TurnAttack.GetTurnFightMgr().getNPCTurnFight(objID)
        #if not turnFight:
        #    # 非回合制怪保留原通知
        #    curNPC.NotifyAppear()
        #    return
        
        # 回合制怪不通知,统一由 // B4 24 回合战斗初始化 #tagSCTurnFightInit
        return
@@ -2578,18 +2406,18 @@
        heroAttrDict = {}
        if lineupPlayerID:
            heroAttrDict.update({
                                 ShareDefine.Def_Effect_Atk:500000000,
                                 ShareDefine.Def_Effect_Def:50000000,
                                 ShareDefine.Def_Effect_MaxHP:3000000000,
                                 ChConfig.AttrID_Atk:500000000,
                                 ChConfig.AttrID_Def:50000000,
                                 ChConfig.AttrID_MaxHP:3000000000,
                                 })
        else:
            npcDataEx = GetNPCDataEx(curNPC.GetNPCID())
            npcDataEx = GetNPCDataPy(curNPC.GetNPCID())
            if not npcDataEx:
                return
            heroAttrDict.update({
                                 ShareDefine.Def_Effect_Atk:npcDataEx.GetAtk(),
                                 ShareDefine.Def_Effect_Def:npcDataEx.GetDef(),
                                 ShareDefine.Def_Effect_MaxHP:npcDataEx.GetMaxHP(),
                                 ChConfig.AttrID_Atk:npcDataEx.GetAtk(),
                                 ChConfig.AttrID_Def:npcDataEx.GetDef(),
                                 ChConfig.AttrID_MaxHP:npcDataEx.GetMaxHP(),
                                 })
            
        GameWorld.DebugLog("heroAttrDict: ID:%s,NPCID:%s,%s" % (curNPC.GetID(), curNPC.GetNPCID(), heroAttrDict))
@@ -2598,10 +2426,10 @@
        curNPC.ResetNPCBattleState()
        
        # 设置属性
        curNPC.SetMinAtk(heroAttrDict.get(ShareDefine.Def_Effect_Atk, 1))
        curNPC.SetMaxAtk(heroAttrDict.get(ShareDefine.Def_Effect_Atk, 1))
        curNPC.SetDef(heroAttrDict.get(ShareDefine.Def_Effect_Def, 1))
        GameObj.SetMaxHP(curNPC, heroAttrDict.get(ShareDefine.Def_Effect_MaxHP, 1))
        curNPC.SetMinAtk(heroAttrDict.get(ChConfig.AttrID_Atk, 1))
        curNPC.SetMaxAtk(heroAttrDict.get(ChConfig.AttrID_Atk, 1))
        curNPC.SetDef(heroAttrDict.get(ChConfig.AttrID_Def, 1))
        GameObj.SetMaxHP(curNPC, heroAttrDict.get(ChConfig.AttrID_MaxHP, 1))
        return
    
    ## 刷新NPC属性
@@ -2647,29 +2475,6 @@
            
        return
    
    def SetHelpBattleRobotRebornAttr(self, fightPower):
        '''助战机器人只设置血量属性
                        血量算法,(助战玩家=助战机器人):每个副本配置伤害*(助战玩家战力/副本规定战力)*系数值  系数值暂定为50
        '''
        curNPC = self.__Instance
        mapID = FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID())
        funcLineID = FBCommon.GetFBPropertyMark()
        ipyData = IpyGameDataPY.GetIpyGameData("FBHelpBattle", mapID, funcLineID)
        if not ipyData:
            return
        SetSuppressFightPower(curNPC, fightPower)
        fbFightPower = ipyData.GetFightPowerMin()
        baseHurt = ipyData.GetRobotBaseHurt()
        hpCoefficient = ipyData.GetRobotHPCoefficient()
        maxHP = int(eval(IpyGameDataPY.GetFuncCompileCfg("HelpBattleRobot", 2)))
        GameWorld.DebugLog("设置助战机器人属性: objID=%s,fightPower=%s,maxHP=%s" % (curNPC.GetID(), fightPower, maxHP))
        GameObj.SetMaxHP(curNPC, maxHP)
        GameObj.SetHP(curNPC, maxHP)
        curNPC.Notify_HP()
        curNPC.Notify_MaxHP()
        return
    # NPC移动速度特殊处理,只处理百分比不能处理固定值 
    # 因为 ChConfig.TYPE_Calc_AttrSpeed 非服务端移动速度,偷懒处理法
    def RefreshNPCSpeed(self, allAttrList):
@@ -2683,9 +2488,6 @@
            speed = int(curNPC.GetSpeed() * (ShareDefine.Def_MaxRateValue) / max(100.0, float(ShareDefine.Def_MaxRateValue + speedPer)))
            curNPC.SetSpeed(speed)
            curNPC.SetDict(ChConfig.Def_NPC_Dict_SpeedPer, speedPer)
        if GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_GatherSoul:
            #目前只在聚魂副本里通知
            NPCSpeedChangeNotify(curNPC, curNPC.GetSpeed())
        return
    
    
@@ -2788,9 +2590,6 @@
        npcID = curNPC.GetNPCID()
        #######################特殊NPC的处理
        
        #boss伤血排行榜击杀逻辑
        #BossHurtMng.BossOnKilled(curNPC)
        #掉落需要用到摸怪,所以在处理掉落奖励之前设置
        self.__SetFeelNPCPlayerList()
        
@@ -2805,22 +2604,12 @@
        # 记录boss击杀信息的NPC
        bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID)
        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()
            killerIDList = [player.GetPlayerID() for player in self.__ownerPlayerList]
            GameServer_KillGameWorldBoss(curNPC.GetNPCID(), killerName, 0, True, killerIDList)
            
        if npcID == IpyGameDataPY.GetFuncCfg("BossRebornServerBoss", 3):
            PlayerControl.WorldNotify(0, "BossRebornBossKilled", [curNPC.GetNPCID()])
            
        #===========================================================================================
        # # 暗金boss
        # if curNPC.GetIsBoss() == ChConfig.Def_NPCType_Boss_Dark:
        #    #PlayerControl.WorldNotify(0, "Old_andyshao_861048", [curNPC.GetNPCID()])
        #    if mapID == ChConfig.Def_MapID_DouHunTan:
        #        NPCCustomRefresh.DoRefreshNeutralBoss(npcID)
        #清空NPC的仇恨
        curNPC.GetNPCAngry().Clear()
        return
@@ -2830,7 +2619,7 @@
        curNPC = self.__Instance
        self.__FeelPlayerList = []
        
        npcHurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
        npcHurtList = [] #NPCHurtManager.GetPlayerHurtList(curNPC)
        if not npcHurtList:
            npcHurtList = curNPC.GetPlayerHurtList()
        #npcHurtList.Sort()  #这里不排序,只要有伤害就算
@@ -3090,12 +2879,6 @@
            return
        
        curNPC = self.__Instance
        # VIP杀怪加攻
        PlayerVip.DoAddVIPKillLVExp(lastHurtPlayer, GetNPCLV(curNPC))
        # SPֵ
        #PlayerControl.AddZhenQiByKillNPC(lastHurtPlayer, curNPC.GetSP())
        return
    
    #---------------------------------------------------------------------
@@ -3209,13 +2992,6 @@
                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
    
@@ -3539,7 +3315,6 @@
        else:
            if GetNPCLV(curNPC) >= curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):
                PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_KillNPC)
                PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_KillNPC)
                PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_KillNPC)
            PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_KillSpecificNPC, 1, [npcID])
        #PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_KillNPC, 1)
@@ -3577,7 +3352,6 @@
        ## 测试查错日志,临时用
        ## 相关bug: 仙界秘境无经验、boss无掉落
        return ChConfig.IsGameBoss(self.__Instance)
        #return GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_BZZD or ChConfig.IsGameBoss(self.__Instance)
    #---------------------------------------------------------------------
    ## 普通组队给经验
@@ -3720,19 +3494,14 @@
            GameWorld.Log("检查Boss死亡: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s" 
                          % (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType))
        #if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:
        maxHurtInfo = NPCHurtManager.RefreshHurtList(curNPC, tick, refreshInterval, isDead, checkCanDead)
        if not maxHurtInfo:
            maxHurtInfo = NPCHurtMgr.RefreshHurtList(curNPC, tick, refreshInterval, isDead)
        if maxHurtInfo:
            tagObj, ownerType, ownerID = maxHurtInfo
        #maxHurtInfo = NPCHurtManager.RefreshHurtList(curNPC, tick, refreshInterval, isDead, checkCanDead)
        #
        #if maxHurtInfo:
        #    tagObj, ownerType, ownerID = maxHurtInfo
            
        elif dropOwnerType == ChConfig.DropOwnerType_Family:
            ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(self, curNPC, tick, refreshInterval)
            if ownerInfo:
                tagObj, ownerFamilyID = ownerInfo
                ownerType, ownerID = ChConfig.Def_NPCHurtTypeFamily, ownerFamilyID
            pass
        elif dropOwnerType == ChConfig.DropOwnerType_Contend:
            tagObj = self.__RefreshContendOwner()
            if tagObj:
@@ -3856,7 +3625,7 @@
        if isDead:
            GameWorld.Log("Boss归属: key=%s,ownerType=%s,ownerID=%s" % (key, ownerType, ownerID))
            
        hurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
        hurtList = [] #NPCHurtManager.GetPlayerHurtList(curNPC)
        # 刷新归属
        if ownerType == ChConfig.Def_NPCHurtTypePlayer:
            curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
@@ -4178,9 +3947,6 @@
    
    # 采集耗时
    prepareTime = collectNPCIpyData.GetPrepareTime() * 1000
    collTimeReduceRate = PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_CollTimeReduceRate)
    if collTimeReduceRate:
        prepareTime = max(1000, int(prepareTime * (ShareDefine.Def_MaxRateValue - collTimeReduceRate) / float(ShareDefine.Def_MaxRateValue)))
    prepareType = IPY_GameWorld.pstCollecting if curNPC.GetType() == IPY_GameWorld.ntCollection else IPY_GameWorld.pstMissionCollecting
    PlayerControl.Sync_PrepareBegin(curPlayer, prepareTime, prepareType, prepareID=curNPC.GetID())
    if collectNPCIpyData.GetLostHPPer():
@@ -4314,93 +4080,7 @@
    return
def DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData, collectCnt=1, crossCollectOK=False, isSweep=False):
    GameWorld.DebugLog("给采集奖励: npcID=%s,collectCnt=%s,crossCollectOK=%s" % (npcID, collectCnt, crossCollectOK))
    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已达到最大采集次数: npcID=%s,todayCollTime=%s,limitMaxTime=%s" % (npcID, todayCollTime, limitMaxTime))
            return
        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("    增加采集次数: 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:
        #缥缈草园的采集定制由缥缈寻访次数决定
        if collectNPCIpyData.GetCollectResetType() in [12, 14]:
            fairyDomainVisitCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FairyDomainVisitCnt)
            grasslandCollectAppointCfg = collectAppointAwardCfg.get(fairyDomainVisitCnt, {})
            curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)
            if curCollTime in grasslandCollectAppointCfg:
                awardItemList.append(grasslandCollectAppointCfg[curCollTime])
            GameWorld.DebugLog("    草园采集定制奖励: fairyDomainVisitCnt=%s,curCollTime=%s,awardItemList=%s" % (fairyDomainVisitCnt, curCollTime, awardItemList))
        else:
            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 = ItemCommon.GetWeightItemListByAlchemyDiffLV(curPlayer, collectAwardCfg, alchemyDiffLV)
        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)
    jsonItemList = []
    if awardItemList:
        for itemID, itemCount, isAuctionItem in awardItemList:
            if ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem]):
                jsonItemList.append(ItemCommon.GetJsonItem([itemID, itemCount, isAuctionItem]))
        if not isSweep:
            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)
            GameLogic_CrossGrassland.RecordGrasslandAward(curPlayer, awardItemList)
    else:
        GameWorld.ErrLog("采集物品没有奖励!npcID=%s" % (npcID))
    #采集成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, collectCnt, [npcID])
    if crossCollectOK:
        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_CrossCollect)
    #SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)
    if not isSweep:
        GameLogic_CrossGrassland.DecCustomSceneNPCCount(curPlayer, npcID)
        if isMaxTime:
            GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
    return jsonItemList
    return
## 采集结果同步
#  @param None
@@ -4662,16 +4342,12 @@
    buyTimesVIPPriID = IpyGameDataPY.GetFuncEvalCfg("KillBossCntLimit1", 1, {}).get(killBossMark)
    if not buyTimesVIPPriID:
        return
    canBuyCnt = PlayerVip.GetPrivilegeValue(curPlayer, buyTimesVIPPriID)
    canBuyCnt = 0
    canBuyCnt += PlayerGoldInvest.GetAddBossBuyCnt(curPlayer, killBossMark)
    hasBuyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, 0)
    playerID = curPlayer.GetPlayerID()
    if hasBuyCnt >= canBuyCnt:
        GameWorld.DebugLog('购买BOSS可击杀次数, 已达到今日最大可购买次数,hasBuyCnt=%s, canBuyCnt=%s'%(hasBuyCnt, canBuyCnt), playerID)
        return
    canKillCnt, dayTimesLimit = BossHurtMng.GetCanKillBossCnt(curPlayer, killBossMark)
    if canKillCnt >= dayTimesLimit:
        GameWorld.DebugLog('购买BOSS可击杀次数, 剩余次数已满!,canKillCnt=%s'%(canKillCnt), playerID)
        return
    
    costGold = IpyGameDataPY.GetFuncEvalCfg("KillBossCntLimit1", 2, {}).get(killBossMark)
@@ -4697,7 +4373,6 @@
        return
    # 增加购买次数
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, hasBuyCnt + 1)
    BossHurtMng.NotifyAttackBossCnt(curPlayer, killBossMark)
    
    CrossPlayerData.SendMergePlayerDataNow(curPlayer)
    return
@@ -4746,26 +4421,10 @@
    GameWorld.DebugLog("通知GameServer地图Boss分流信息: mapID=%s,lineID=%s,shuntPlayerDict=%s" % (mapID, lineID, shuntPlayerDict), lineID)
    return
def NPCSpeedChangeNotify(curNPC, speed):
    ##通知NPC速度
    GameObj.NotifyObjInfoRefresh(curNPC, IPY_GameWorld.CDBPlayerRefresh_Speed, speed)
    return
def UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount=0):
    ## 更新玩家攻击NPC次数
    if not npcID:
        return
    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):
@@ -4803,64 +4462,6 @@
#  @param curNPC 被攻击NPC
#  @return None
def __OnAttackedDropItem(atkObj, curNPC):
    attackPlayer, npcObjType = AttackCommon.GetAttackPlayer(atkObj)
    if npcObjType:
        return
    if not attackPlayer:
        return
    npcID = curNPC.GetNPCID()
    ipyData = IpyGameDataPY.GetIpyGameDataNotLog("TreasureNPC", npcID)
    if not ipyData:
        return
    attackCountDropWeightInfo = ipyData.GetAttackCountDropWeightInfo()
    attackDropWeightList = ipyData.GetAttackDropWeightList()
    attackDropWeightListEx = ipyData.GetAttackDropWeightListEx()
    dropCountEx = ipyData.GetDropCountEx()
    alchemyDiffLV = ipyData.GetAlchemyDiffLV()
    mainItemWeightList = []
    if attackCountDropWeightInfo:
        maxCount = max(attackCountDropWeightInfo)
        attackCount = attackPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID) + 1
        if attackCount <= maxCount:
            if attackCount in attackCountDropWeightInfo:
                mainItemWeightList = attackCountDropWeightInfo[attackCount]
            UpdateNPCAttackCount(attackPlayer, npcID, attackCount, maxCount)
    if mainItemWeightList:
        mainItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, mainItemWeightList, alchemyDiffLV)
    elif attackDropWeightList:
        mainItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightList, alchemyDiffLV)
    mainItemInfo = GameWorld.GetResultByWeightList(mainItemWeightList)
    if not mainItemInfo:
        notDropNotify = ipyData.GetNotDropNotify()
        if notDropNotify:
            PlayerControl.NotifyCode(attackPlayer, notDropNotify)
        return
    dropItemList = []
    if mainItemInfo:
        dropItemList.append(mainItemInfo)
    if attackDropWeightListEx and dropCountEx:
        weightListEx = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightListEx, alchemyDiffLV)
        for _ in xrange(dropCountEx):
            itemInfo = GameWorld.GetResultByWeightList(weightListEx)
            if itemInfo:
                dropItemList.append(itemInfo)
    if not dropItemList:
        return
    mapID = PlayerControl.GetCustomMapID(attackPlayer)
    if mapID:
        DoGiveItemByVirtualDrop(attackPlayer, dropItemList, npcID)
        GameLogic_CrossGrassland.RecordGrasslandAward(attackPlayer, dropItemList)
    else:
        dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY()
        ChItem.DoMapDropItem(attackPlayer, dropItemList, npcID, dropPosX, dropPosY, isOnlySelfSee=False)
    return