ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -40,22 +40,12 @@
import DataRecordPack
import NetPackCommon
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 +53,13 @@
import PlayerGoldInvest
import PlayerWeekParty
import NPCRealmRefresh
import NPCHurtManager
import PlayerActLogin
import PlayerActTask
import PlayerZhanling
import FamilyRobBoss
#import PlayerZhanling
import IpyGameDataPY
import PlayerGubao
import PlayerState
import TurnAttack
import PyGameData
import PlayerTeam
import NPCHurtMgr
import PlayerVip
import GameObj
import ChNPC
@@ -129,12 +113,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 +126,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 +140,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 +164,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 +616,7 @@
#===============================================================================
def GetDefaultMaxAngryNPCIDList():
    return GameLogic_FamilyInvade.GetDefaultMaxAngryNPCIDList()
    return []
#---------------------------------------------------------------------
##NPC进入战斗状态
@@ -946,115 +791,6 @@
        
    return
#// B4 0F 回收私有专属木桩怪 #tagCMRecyclePriWoodPile
#
#struct    tagCMRecyclePriWoodPile
#{
#    tagHead        Head;
#    DWORD        ObjID;
#};
def OnRecyclePriWoodPile(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    objID = clientData.ObjID
    curNPC = GameWorld.FindNPCByID(objID)
    if not curNPC:
        return
    if curNPC.GetType() not in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
        return
    summonPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID)
    if curPlayer.GetPlayerID() != summonPlayerID:
        #GameWorld.DebugLog("非玩家私有木桩...")
        return
    SetDeadEx(curNPC)
    return
#// B4 0C 召唤私有专属木桩怪 #tagCMSummonPriWoodPile
#
#struct    tagCMSummonPriWoodPile
#{
#    tagHead        Head;
#    DWORD        NPCID;
#    BYTE        Count;    //默认1个,最多5个
#    DWORD        HP;    //默认0取最大值,其中一个血量数值大于0则用指定血量
#    DWORD        HPEx;    //默认0取最大值,其中一个血量数值大于0则用指定血量
#};
def OnSummonPriWoodPile(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    npcID = clientData.NPCID
    count = clientData.Count
    hp = clientData.HP
    hpEx = clientData.HPEx
    SummonPriWoodPile(curPlayer, npcID, count, hp, hpEx)
    return
def SummonPriWoodPile(curPlayer, npcID, count, hp=0, hpEx=0):
    ''' 召唤私有专属木桩怪
    '''
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    if mapID:
        if not FBLogic.OnCanSummonPriWoodPile(curPlayer, mapID, lineID, npcID, count):
            GameWorld.ErrLog("无法召唤木桩怪!mapID=%s,lineID=%s,npcID=%s,count=%s" % (mapID, lineID, npcID, count))
            return
    if count != 1:
        hp, hpEx = 0, 0 # 指定血量的暂仅适用于单只的
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_playerPriWoodPileNPCDict:
        PyGameData.g_playerPriWoodPileNPCDict[playerID] = []
    playerPriWoodNPCList = PyGameData.g_playerPriWoodPileNPCDict[playerID]
    maxCount = 3
    nowCount = len(playerPriWoodNPCList)
    summonCount = min(count, maxCount - nowCount)
    GameWorld.DebugLog("召唤木桩: npcID=%s,count=%s,maxCount=%s,nowCount=%s,summonCount=%s,hp=%s,hpEx=%s"
                       % (npcID, count, maxCount, nowCount, summonCount, hp, hpEx))
    if summonCount <= 0:
        return
    npcManager = GameWorld.GetNPCManager()
    for _ in xrange(summonCount):
        #summonNPC = curPlayer.SummonNewNPC()
        summonNPC = npcManager.AddPlayerSummonNPC()
        #设置召唤兽基础信息
        summonNPC.SetNPCTypeID(npcID)
        summonNPC.SetSightLevel(curPlayer.GetSightLevel())
        #初始化
        InitNPC(summonNPC)
        #玩家召唤兽列表添加召唤兽,召唤兽添加主人
        #summonNPC.SetOwner(curPlayer)
        summonNPC.SetDict(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID, playerID)
        #将召唤兽召唤出来
        #玩家周围随机出生点
        #技能召唤坐标 ChConfig.Def_SummonAppearDist
        summonPos = GameMap.GetEmptyPlaceInArea(curPlayer.GetPosX(), curPlayer.GetPosY(), 3)
        summonNPC.Reborn(summonPos.GetPosX(), summonPos.GetPosY(), False)
        NPCControl(summonNPC).ResetNPC_Init(isReborn=True)
        if hp or hpEx:
            hpTotal = hpEx * ShareDefine.Def_PerPointValue + hp
            GameObj.SetHP(summonNPC, hpTotal)
            GameObj.SetMaxHP(summonNPC, hpTotal)
        summonNPC.NotifyAppear() # 最终统一通知NPC出现
        playerPriWoodNPCList.append(summonNPC)
    return
def ClearPriWoodPile(curPlayer):
    ## 清除私有木桩
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_playerPriWoodPileNPCDict:
        return
    playerPriWoodNPCList = PyGameData.g_playerPriWoodPileNPCDict.pop(playerID)
    for summonNPC in playerPriWoodNPCList:
        if not summonNPC:
            continue
        SetDeadEx(summonNPC)
    return
## 设置npc死亡及自身处理(请不要将游戏逻辑加在此函数中)
#  @param curNPC:npc实例
#  @return 
@@ -1086,15 +822,13 @@
    # 暗金boss
    if ChConfig.IsGameBoss(curNPC): 
        # 通知GameServer boss状态 封魔坛在副本里单独处理
        ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', npcid)
        if ipyData and ipyData.GetMapID() not in [ChConfig.Def_FBMapID_SealDemon, ChConfig.Def_FBMapID_ZhuXianBoss]:
            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())
            if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
                FamilyRobBoss.ClearFamilyOwnerBossHurt(curNPC)
        #ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', npcid)
        #if ipyData and ipyData.GetMapID() not in [ChConfig.Def_FBMapID_SealDemon, ChConfig.Def_FBMapID_ZhuXianBoss]:
        #    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())
        ChNPC.OnNPCSetDead(curNPC)
        
        if npcid == IpyGameDataPY.GetFuncCfg("CrossYaomoBoss", 1):
@@ -1102,10 +836,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 +854,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=[]):
@@ -1174,86 +903,6 @@
    return
def OnPlayerKillBoss(curPlayer, npcID, mapID, isCrossServer):
    npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)
    if not npcData:
        return
    killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)
    limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)
    if limitIndex != None:
        totalKey = ChConfig.Def_PDict_Boss_KillCntTotal % limitIndex
        totalCnt = min(curPlayer.NomalDictGetProperty(totalKey, 0) + 1, ChConfig.Def_UpperLimit_DWord)
        PlayerControl.NomalDictSetProperty(curPlayer, totalKey, totalCnt)
        #今日杀怪次数+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("更新击杀Boss次数: index=%s, todayCnt=%s, totalCnt=%s" % (limitIndex, newCnt, totalCnt), curPlayer.GetPlayerID())
        dataDict = {"objID":npcID, "bossID":npcID, "touchCnt":newCnt, "totalCnt":totalCnt,
                    "AccID":curPlayer.GetAccID(), "PlayerID":curPlayer.GetPlayerID()}
        DataRecordPack.SendEventPack("AddKillBossCnt", dataDict, curPlayer)
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_KillBoss, 1, [limitIndex])
        PlayerState.SetBossStateExit(curPlayer)
    if isCrossServer:
        return
    if limitIndex == ShareDefine.Def_Boss_Func_World:
        # 世界BOSS击杀成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillWorldBoss, 1)
        PlayerGubao.AddGubaoItemEffValue(curPlayer, PlayerGubao.GubaoEffType_KillWorldBoss, 1)
        # 每日活动
        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)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_WorldBoss, 1)
        PlayerZhanling.AddZhanlingValue(curPlayer, PlayerZhanling.ZhanlingType_Huanjingge, 1)
        PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_WorldBoss, 1)
    elif limitIndex == ShareDefine.Def_Boss_Func_Home:
        #BOSS之家
        # BOSS之家BOSS击杀成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillBossHomeBoss, 1)
        PlayerGubao.AddGubaoItemEffValue(curPlayer, PlayerGubao.GubaoEffType_KillBossHome, 1)
        # 每日活动
        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)
    if mapID == ChConfig.Def_FBMapID_CrossPenglai:
        #跨服蓬莱仙境
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_CrossPenglai)
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillCrossPenglaiBoss, 1)
        PlayerGubao.AddGubaoItemEffValue(curPlayer, PlayerGubao.GubaoEffType_KillCrossPenglaiBoss, 1)
        PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_CrossPenglaiBoss, 1)
    elif mapID == ChConfig.Def_FBMapID_CrossDemonLand:
        #跨服魔化之地
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_CrossDemonLand)
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillCrossDemonLandBoss, 1)
        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)
    if ipyData:
        GY_Query_BossFirstKill.SetPlayerFirstKillBoss(curPlayer, npcID)
    #Boss投资
    PlayerGoldInvest.OnKillBoss(curPlayer, npcID)
    return
    
#################################################
@@ -2074,8 +1723,6 @@
        #清除所有身上buff
        self.ClearAllBuff(isClearAuraBuff)
        curNPC = self.__Instance
        NPCHurtManager.ClearPlayerHurtList(curNPC)
        NPCHurtMgr.ClearPlayerHurtList(curNPC)
        return True
    
    #---------------------------------------------------------------------
@@ -2424,9 +2071,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 +2089,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 +2223,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 +2243,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 +2292,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 +2305,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 +2407,6 @@
        npcID = curNPC.GetNPCID()
        #######################特殊NPC的处理
        
        #boss伤血排行榜击杀逻辑
        #BossHurtMng.BossOnKilled(curNPC)
        #掉落需要用到摸怪,所以在处理掉落奖励之前设置
        self.__SetFeelNPCPlayerList()
        
@@ -2800,27 +2416,17 @@
        #杀死NPC, 触发任务
        self.__EventKillNpc()
            
        mapID = GameWorld.GetMap().GetMapID()
        killerName = "" if not self.__Killer else self.__Killer.GetPlayerName()
        # 记录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)
        #mapID = GameWorld.GetMap().GetMapID()
        #killerName = "" if not self.__Killer else self.__Killer.GetPlayerName()
        ## 记录boss击杀信息的NPC
        #bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID)
        #if bossIpyData and mapID not in [ChConfig.Def_FBMapID_ZhuXianBoss, ChConfig.Def_FBMapID_SealDemon]:
        #    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 +2436,7 @@
        curNPC = self.__Instance
        self.__FeelPlayerList = []
        
        npcHurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
        npcHurtList = [] #NPCHurtManager.GetPlayerHurtList(curNPC)
        if not npcHurtList:
            npcHurtList = curNPC.GetPlayerHurtList()
        #npcHurtList.Sort()  #这里不排序,只要有伤害就算
@@ -3090,12 +2696,6 @@
            return
        
        curNPC = self.__Instance
        # VIP杀怪加攻
        PlayerVip.DoAddVIPKillLVExp(lastHurtPlayer, GetNPCLV(curNPC))
        # SPֵ
        #PlayerControl.AddZhenQiByKillNPC(lastHurtPlayer, curNPC.GetSP())
        return
    
    #---------------------------------------------------------------------
@@ -3209,13 +2809,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
    
@@ -3538,10 +3131,7 @@
            FBLogic.DoFB_DropOwner(curPlayer , curNPC)
        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)
        
        if ChConfig.IsGameBoss(curNPC):
@@ -3567,17 +3157,12 @@
        #不是普通NPC    
        elif npcObjType != IPY_GameWorld.gnotNormal:
            return
        npcID = curNPC.GetNPCID()
        #GameWorld.DebugLog("__MissionOnKillNPC isFeel=%s" % (isFeel), curPlayer.GetPlayerID())
        #击杀特定NPC成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, 1, [npcID])
        return
        
    def __GetIsLog(self):
        ## 测试查错日志,临时用
        ## 相关bug: 仙界秘境无经验、boss无掉落
        return ChConfig.IsGameBoss(self.__Instance)
        #return GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_BZZD or ChConfig.IsGameBoss(self.__Instance)
    #---------------------------------------------------------------------
    ## 普通组队给经验
@@ -3720,19 +3305,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 +3436,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 +3758,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():
@@ -4283,130 +3860,8 @@
        DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData, crossCollectOK=True)
    return
#// A2 34 自定义场景中获取采集奖励 #tagCMGetCustomSceneCollectAward
#
#struct    tagCMGetCustomSceneCollectAward
#{
#    tagHead        Head;
#    DWORD        NPCID;    //采集的NPCID
#};
def OnGetCustomSceneCollectAward(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    playerID = curPlayer.GetPlayerID()
    npcID = clientData.NPCID
    if not curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        GameWorld.ErrLog("非自定义场景中,无法获取定义采集奖励!", playerID)
        return
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    GameWorld.Log("前端场景采集: mapID=%s,lineID=%s,npcID=%s" % (mapID, lineID, npcID), playerID)
    if not mapID:
        GameWorld.ErrLog("无自定义场景地图ID,不允许采集!", playerID)
        return
    if not FBLogic.OnCustomSceneCollectOK(curPlayer, mapID, lineID, npcID):
        GameWorld.ErrLog("自定义场景地图不允许采集! mapID=%s,lineID=%s,npcID=%s" % (mapID, lineID, npcID), playerID)
        return
    collectNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CollectNPC", npcID)
    if collectNPCIpyData:
        DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData)
    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
## 采集结果同步
#  @param None
#  @param None
def SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, syncItemInfoList, collectNPCID=0):
    return #暂不同步
    return
def SyncCollNPCTime(curPlayer, npcIDList=None):
    ## 同步采集NPC功能号采集次数
@@ -4662,16 +4117,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 +4148,6 @@
        return
    # 增加购买次数
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, hasBuyCnt + 1)
    BossHurtMng.NotifyAttackBossCnt(curPlayer, killBossMark)
    
    CrossPlayerData.SendMergePlayerDataNow(curPlayer)
    return
@@ -4746,26 +4196,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 +4237,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