hxp
2019-11-21 3fa43daecc099f2701baec224a791ca09766cdf4
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -44,6 +44,7 @@
import PlayerActivity
import PlayerSuccess
import BossHurtMng
import GY_Query_BossFirstKill
import GameLogic_FamilyInvade
import GameLogic_GatherSoul
import FormulaControl
@@ -606,7 +607,7 @@
                              dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee)
    return
def DoGiveItemByVirtualDrop(curPlayer, giveItemList, npcID, dropPosX=0, dropPosY=0, isDropDisperse=True, mailTypeKey="ItemNoPickUp"):
def DoGiveItemByVirtualDrop(curPlayer, giveItemList, npcID, dropPosX=0, dropPosY=0, isDropDisperse=True, mailTypeKey="ItemNoPickUp", extraVirtualItemList=[]):
    ## 给物品并且做假掉落表现,直接先堆叠给物品,再拆开做虚假掉落表现
    
    mapID = PlayerControl.GetCustomMapID(curPlayer)
@@ -640,6 +641,21 @@
            virtualItemDropList.append([itemID, dropItemDataStr])
        
    # 先通知掉落,再给物品,因为前端表现弹框需要这个顺序需求
    if extraVirtualItemList: #只显示假掉落
        for itemInfo in extraVirtualItemList:
            itemID, itemCount, isAuctionItem = itemInfo
            curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isAuctionItem, curPlayer=curPlayer)
            if not curItem:
                continue
            dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem)
            # 散开掉落
            if isDropDisperse:
                for _ in xrange(itemCount):
                    virtualItemDropList.append([itemID, dropItemDataStr])
            else:
                virtualItemDropList.append([itemID, dropItemDataStr])
            curItem.Clear()
    gameMap = GameWorld.GetMap()
    index = 0
    for posX, posY in ChConfig.Def_DropItemAreaMatrix:
@@ -778,7 +794,6 @@
            dropEquipInfoList.append([classLV, color, dropCount])
        GameWorld.DebugLog("    装备掉落结果: killCount=%s,[阶,颜色,件数]=%s" % (killCount, dropEquipInfoList), playerID)
        
    placeKeyListDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1)
    colorSuitRateDict = ipyDrop.GetEquipColorSuitInfo() # 装备颜色对应套装概率 {颜色:套装概率, ...}
    colorSuitPlaceKeyInfoDict = ipyDrop.GetEquipPartKeyRateInfo() # 装备部位集合信息 {(颜色,是否套装):部位集合key, ...}
    dropEquipIDDict = {}
@@ -798,10 +813,10 @@
                GameWorld.ErrLog("未配置颜色是否套装对应部位集合key! npcID=%s,color=%s,isSuit=%s" % (npcID, color, isSuit))
                continue
            placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey]
            if placeKey not in placeKeyListDict:
            placeList = GetEquipPlaceByPlaceKey(placeKey)
            if not placeList:
                GameWorld.ErrLog("部位集合key不存在!npcID=%s,placeKey=%s" % (npcID, placeKey))
                continue
            placeList = placeKeyListDict[placeKey]
            randEquipIDList = __GetEquipIDList(npcID, classLV, color, isSuit, placeList, itemJobList)
            if not randEquipIDList:
                continue
@@ -825,8 +840,8 @@
        doCnt *= killCount
        
        totalRate = dropRate * doCnt
        dropCount = totalRate / maxRate # 可掉落件数
        rateEx = totalRate % maxRate # 剩余概率
        dropCount = totalRate / Def_NPCMaxDropRate # 可掉落件数
        rateEx = totalRate % Def_NPCMaxDropRate # 剩余概率
        if GameWorld.CanHappen(rateEx, Def_NPCMaxDropRate):
            dropCount += 1
        dropIDList += [itemID] * dropCount
@@ -1008,7 +1023,6 @@
        gradeColorSuitRateDict = fbGradeColorSuitRateDict[npcID]
        curGrade = curGrade if curGrade else GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)
        
    placeKeyListDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1)
    colorDropCntDict = {} # 装备颜色已经掉落数 {颜色:数量, ...}
    colorMaxDropCntDict = ipyDrop.GetEquipColorMaxDropCount() # {颜色:上限数量,...}
    colorSuitRateDict = ipyDrop.GetEquipColorSuitInfo() # 装备颜色对应套装概率 {颜色:套装概率, ...}
@@ -1045,25 +1059,31 @@
                continue
            placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey]
            # 掉落优选部位处理
            if color == optColor and isSuit == optIsSuit and placeKey in placeKeyListDict and optPlace == None:
                optPlace = __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, placeKeyListDict[placeKey])
            if color == optColor and isSuit == optIsSuit and optPlace == None:
                allEquipPlaceList = GetAllEquipPlaceByPlaceKey(placeKey)
                #GameWorld.DebugLog("    所有可优选部位: %s" % allEquipPlaceList)
                if allEquipPlaceList:
                    optPlace = __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, allEquipPlaceList)
            jobList = itemJobList
        if placeKey not in placeKeyListDict:
            GameWorld.ErrLog("部位集合key不存在!npcID=%s,placeKey=%s" % (npcID, placeKey))
            continue
        if optPlace > 0:
            GameWorld.DebugLog("    最终优选部位: %s" % optPlace)
            placeList = [optPlace]
            jobList = [dropPlayer.GetJob()]
            optPlace = 0 # 只有一次性的,置为0
        else:
            placeList = placeKeyListDict[placeKey]
            placeList = GetEquipPlaceByPlaceKey(placeKey)
            if not placeList:
                GameWorld.ErrLog("部位集合key不存在!npcID=%s,placeKey=%s" % (npcID, placeKey))
                continue
        randEquipIDList = __GetEquipIDList(npcID, classLV, color, isSuit, placeList, jobList)
        if not randEquipIDList:
            continue
        if color in colorMaxDropCntDict:
            colorDropCntDict[color] = dropCount + 1
        randItemID = random.choice(randEquipIDList)
        if isSuit and len(jobList) > 1:
            randItemID = __GetRandDropSuitEquipID(dropPlayer, randEquipIDList)
        else:
            randItemID = random.choice(randEquipIDList)
        dropIDList.append(randItemID)
        GameWorld.DebugLog("掉落装备: npcID=%s,itemID=%s,classLV=%s,color=%s,isSuit=%s,placeKey=%s,jobList=%s,randEquipIDList=%s" 
                           % (npcID, randItemID, classLV, color, isSuit, placeKey, jobList, randEquipIDList), playerID)
@@ -1126,6 +1146,47 @@
    elif ChConfig.IsGameBoss(npcData):
        GameWorld.ErrLog("Boss没有掉落物品,NPCID=%s" % (npcID), dropPlayer.GetPlayerID())
    return dropIDList, auctionIDList, dropMoneyCnt, moneyValue
def __GetRandDropSuitEquipID(curPlayer, randEquipIDList):
    ## 获取随机掉落的套装ID,为了玩家掉落体验, 当非本职业套装时可至多重新随机X次
    randItemID = 0
    suitRandCountEx = IpyGameDataPY.GetFuncCfg("EquipSuitDrop", 1) + 1
    for _ in xrange(suitRandCountEx):
        randItemID = random.choice(randEquipIDList)
        itemData = GameWorld.GetGameData().GetItemByTypeID(randItemID)
        if not itemData:
            continue
        if ItemCommon.CheckJob(curPlayer, itemData):
            break
    return randItemID
def GetAllEquipPlaceByPlaceKey(placeKey):
    placeKeyRateListDict = IpyGameDataPY.GetFuncEvalCfg("EquipDropPartSets", 2, {}) # {集合数字key1:[[概率1,部位1],...],...}
    if placeKey in placeKeyRateListDict:
        return [rateInfo[1] for rateInfo in placeKeyRateListDict[placeKey]]
    placeKeyListDict = IpyGameDataPY.GetFuncEvalCfg("EquipDropPartSets", 1, {}) # {集合数字key1:[部位1,部位2,...],...}
    if placeKey in placeKeyListDict:
        return placeKeyListDict[placeKey]
    return []
def GetEquipPlaceByPlaceKey(placeKey):
    ## 获取装备位集合对应的部位信息,集合ID重复时,优先饼图
    placeList = []
    placeKeyRateListDict = IpyGameDataPY.GetFuncEvalCfg("EquipDropPartSets", 2, {}) # {集合数字key1:[[概率1,部位1],...],...}
    if placeKey in placeKeyRateListDict:
        placeRateList = placeKeyRateListDict[placeKey]
        place = GameWorld.GetResultByRandomList(placeRateList)
        if place:
            placeList = [place]
            #GameWorld.DebugLog("    掉落部位概率集合: placeKey=%s,placeRateList=%s,place=%s,placeList=%s" % (placeKey, placeRateList, place, placeList))
    if not placeList:
        placeKeyListDict = IpyGameDataPY.GetFuncEvalCfg("EquipDropPartSets", 1, {}) # {集合数字key1:[部位1,部位2,...],...}
        if placeKey in placeKeyListDict:
            placeList = placeKeyListDict[placeKey]
            #GameWorld.DebugLog("    掉落部位均衡集合: placeKey=%s,placeList=%s" % (placeKey, placeList))
    return placeList
def __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, optPlaceList):
    ''' 获取掉落优选部位
@@ -2310,6 +2371,12 @@
    elif mapID == ChConfig.Def_FBMapID_CrossPenglai:
        #跨服蓬莱仙境
        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_CrossPenglai)
    # 个人首杀记录
    ipyData = IpyGameDataPY.GetIpyGameDataNotLog("BOSSFirstKill", npcID)
    if ipyData:
        GY_Query_BossFirstKill.SetPlayerFirstKillBoss(curPlayer, npcID)
    return
    
#################################################
@@ -3162,7 +3229,8 @@
        #    GameWorld.DebugLog("伤血玩家血量为0,清除该伤血!playerID=%s" % hurtID)
        #    return True
        
        if hurtPlayer.GetInitOK() and not hurtPlayer.GetVisible():
        curNPC = self.__Instance
        if hurtPlayer.GetInitOK() and (not hurtPlayer.GetVisible() or hurtPlayer.GetSightLevel() != curNPC.GetSightLevel()):
            GameWorld.DebugLog("伤血玩家不可见,清除该伤血!playerID=%s" % hurtID)
            return True
        
@@ -3199,7 +3267,7 @@
                    #GameWorld.DebugLog("队员不在本线路,不计!playerID=%s" % playerID)
                    continue
                
                if curTeamPlayer.GetInitOK() and not curTeamPlayer.GetVisible():
                if curTeamPlayer.GetInitOK() and (not curTeamPlayer.GetVisible() or curTeamPlayer.GetSightLevel() != curNPC.GetSightLevel()):
                    #GameWorld.DebugLog("队员不可见,不计!playerID=%s" % playerID)
                    continue
                
@@ -4333,7 +4401,7 @@
    #  @param HurtType 伤血类型
    #  @param HurtID 伤血ID
    #  @return 返回值无意义
    def __NPCDropItem(self, dropPlayer, hurtType, hurtID, ownerPlayerList=[]):
    def __NPCDropItem(self, dropPlayer, hurtType, hurtID, ownerPlayerList=[], isOnlySelfSee=False):
        if not dropPlayer:
            return
        curNPC = self.__Instance
@@ -4432,7 +4500,7 @@
                    SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr)
                    
            else:
                self.__MapCreateItem(curItem, resultX, resultY, ownerType, ownerID)
                self.__MapCreateItem(curItem, resultX, resultY, ownerType, ownerID, isOnlySelfSee=isOnlySelfSee)
        return
    #---------------------------------------------------------------------
    ## NPC被杀死逻辑处理
@@ -4631,13 +4699,24 @@
                if maxPlayerLV < curPlayer.GetLV():
                    maxPlayerLV = curPlayer.GetLV()
                    dropPlayer = curPlayer
                if isGameBoss and curPlayer.GetOfficialRank() < GetRealmLV(curNPC):
                    GameWorld.Log("玩家境界不足,无法获得Boss归属奖励! playerRealmLV=%s,npcID=%s,npcRealmLV=%s"
                                  % (curPlayer.GetOfficialRank(), npcID, GetRealmLV(curNPC)), curPlayer.GetPlayerID())
                    continue
                self.__KilledByPlayerSetPrize(curPlayer)
                ownerPlayerList.append(curPlayer)
            self.__ownerPlayerList = ownerPlayerList
            
            #调用物品掉落
            self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
            #调用物品掉落,boss一人一份
            if isGameBoss and hurtType in [ChConfig.Def_NPCHurtTypePlayer, ChConfig.Def_NPCHurtTypeTeam, ChConfig.Def_NPCHurtTypeSpecial]:
                isOnlySelfSee = len(ownerPlayerList) > 1
                for curPlayer in ownerPlayerList:
                    self.__NPCDropItem(curPlayer, ChConfig.Def_NPCHurtTypePlayer, curPlayer.GetPlayerID(), [curPlayer], isOnlySelfSee=isOnlySelfSee)
            elif dropPlayer:
                self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
        #被队伍杀死
        elif curTeam != None:
            self.__KilledByTeamSetPrize(curTeam, hurtType, hurtID)
@@ -5067,8 +5146,15 @@
        teamMaxLV = 0
        dropPlayer = None
        ownerPlayerList = []
        npcID = curNPC.GetNPCID()
        isGameBoss = ChConfig.IsGameBoss(curNPC)
        #遍历队伍,半径为一屏半的距离内的所有队伍/团队成员,可以获得经验
        for curPlayer in playerlist:
            if isGameBoss and curPlayer.GetOfficialRank() < GetRealmLV(curNPC):
                GameWorld.Log("队员境界不足,无法获得Boss归属奖励! playerRealmLV=%s,npcID=%s,npcRealmLV=%s"
                              % (curPlayer.GetOfficialRank(), npcID, GetRealmLV(curNPC)), curPlayer.GetPlayerID())
                continue
            curPlayerLV = curPlayer.GetLV()
            if teamMaxLV < curPlayerLV:
                teamMaxLV = curPlayerLV
@@ -5079,9 +5165,14 @@
            self.__DoNormalTeamExp(curPlayer)
            self.__KillNPCFuncEx(curPlayer, curNPC, maxHurtID, True)
        self.__ownerPlayerList = ownerPlayerList
        #调用物品掉落
        self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
        #调用物品掉落,boss一人一份
        if isGameBoss and hurtType in [ChConfig.Def_NPCHurtTypePlayer, ChConfig.Def_NPCHurtTypeTeam, ChConfig.Def_NPCHurtTypeSpecial]:
            isOnlySelfSee = len(ownerPlayerList) > 1
            for curPlayer in ownerPlayerList:
                self.__NPCDropItem(curPlayer, ChConfig.Def_NPCHurtTypePlayer, curPlayer.GetPlayerID(), [curPlayer], isOnlySelfSee=isOnlySelfSee)
        elif dropPlayer:
            self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
        #GameWorld.Log("队伍杀死怪物奖励,逻辑成功结束")
        return
    
@@ -5297,7 +5388,7 @@
    #  @param dropType: 掉落类型
    #  @param ownerID: 归属者
    #  @return: None
    def __MapCreateItem(self, curItem, posX, posY, dropType, ownerID):
    def __MapCreateItem(self, curItem, posX, posY, dropType, ownerID, isOnlySelfSee=False):
        if not curItem:
            return
        
@@ -5315,8 +5406,8 @@
        
        # 在地上添加物品(统一接口)
        dropNPCID = 0 if not ChConfig.IsGameBoss(curNPC) else curNPCID
        specOwnerIDList = self.__AllKillerDict.keys() if (len(self.__AllKillerDict) > 1 or dropType == ChConfig.Def_NPCHurtTypeSpecial) else []
        curMapItem = ChItem.AddMapDropItem(posX, posY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList], dropNPCID=dropNPCID)
        specOwnerIDList = [player.GetPlayerID() for player in self.__ownerPlayerList] if dropType == ChConfig.Def_NPCHurtTypeSpecial else []
        curMapItem = ChItem.AddMapDropItem(posX, posY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList], dropNPCID=dropNPCID, isOnlySelfSee=isOnlySelfSee)
        
        #设置该物品生前拥有者(那个NPC掉落的)
        if curMapItem == None:
@@ -6299,34 +6390,35 @@
#};
## 购买BOSS可击杀次数
def OnBuyKillBossCnt(index, clientData, tick):
#    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
#    killBossMark = clientData.KillBossMark
#    killBossCntLimitDict = ReadChConfig.GetEvalChConfig("KillBossCntLimit")
#    curBossLimitInfo = []
#    for limitInfo in killBossCntLimitDict.values():
#        if killBossMark == limitInfo[0]:
#            curBossLimitInfo = limitInfo
#            break
#    if not curBossLimitInfo:
#        return
#
#    killBossMark, limitCnt, canBuyCnt, buyCost, sysMark1, sysMark2= curBossLimitInfo
#    hasKillCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Boss_KillCnt%killBossMark, 0)
#    hasBuyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, 0)
#    playerID = curPlayer.GetPlayerID()
#    if hasBuyCnt >= canBuyCnt:
#        GameWorld.Log('购买BOSS可击杀次数, 已达到今日最大可购买次数,hasBuyCnt=%s, canBuyCnt=%s'%(hasBuyCnt, canBuyCnt), playerID)
#        return
#    costGold = eval(buyCost)
#    infoDict = {"index":index, ChConfig.Def_Cost_Reason_SonKey:index}
#    isOK = PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGold,
#                                  ChConfig.Def_Cost_BuyKillBossCnt, infoDict)
#
#    if not isOK:
#        return
#    # 增加购买次数
#    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, hasBuyCnt + 1)
#    BossHurtMng.NotifyAttackBossCnt(curPlayer)
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    killBossMark = clientData.KillBossMark
    buyTimesVIPPriID = IpyGameDataPY.GetFuncEvalCfg("KillBossCntLimit1", 1, {}).get(killBossMark)
    if not buyTimesVIPPriID:
        return
    canBuyCnt = PlayerVip.GetPrivilegeValue(curPlayer, buyTimesVIPPriID)
    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)
    if not costGold:
        return
    infoDict = {"index":killBossMark, ChConfig.Def_Cost_Reason_SonKey:killBossMark}
    isOK = PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGold,
                                  ChConfig.Def_Cost_BuyKillBossCnt, infoDict)
    if not isOK:
        return
    # 增加购买次数
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Boss_KillCntBuyCnt%killBossMark, hasBuyCnt + 1)
    BossHurtMng.NotifyAttackBossCnt(curPlayer, killBossMark)
    return
#// A2 23 NPC秀结束 #tagCMNPCShowEnd