From d0f5f9922f17f5bff4288173f18a9ed827d95db8 Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期六, 22 六月 2019 15:00:13 +0800 Subject: [PATCH] 1 装备评分增加装备掉率参数固定值 DropEquipPer --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py | 1729 +++++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 1,202 insertions(+), 527 deletions(-) diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py index 0120100..75f9138 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py @@ -37,7 +37,6 @@ import ShareDefine import ChItem #import AICommon -import PlayerAction import ChPyNetSendPack import DataRecordPack import NetPackCommon @@ -45,14 +44,13 @@ import PlayerActivity import PlayerSuccess import BossHurtMng -import PlayerSuperMarket import GameLogic_FamilyInvade import GameLogic_GatherSoul import FormulaControl -import PlayerMagicWeapon import PlayerBossReborn import PlayerFairyCeremony import PlayerNewFairyCeremony +import GameLogic_CrossGrassland import PlayerWeekParty import PlayerActLogin import FamilyRobBoss @@ -97,8 +95,6 @@ #初始化处理间隔 curNPC.SetIsNeedProcess(False) - #设定致命一击伤害百分比 - curNPC.SetSuperHit(ChConfig.Def_SuperHitPercent) #初始化这个NPC的时钟 curNPC.SetTickTypeCount(ChConfig.TYPE_NPC_Tick_Count) return @@ -169,6 +165,15 @@ randMaxLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV) strengthenLV = random.randint(randMinLV, randMaxLV) + # 木桩怪最大、平均成长等级处理,直接取归属玩家等级 + 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()) @@ -401,15 +406,18 @@ return attrDict def GiveKillNPCDropPrize(curPlayer, mapID, npcCountDict, exp_rate=None, mailTypeKey=None, isMail=False, - extraItemList=[], prizeMultiple=1, dropItemMapInfo=[], curGrade=0): + extraItemList=[], prizeMultiple=1, dropItemMapInfo=[], curGrade=0, isVirtualDrop=False): '''给玩家击杀NPC掉落奖励 @param mapID: 击杀的NPC所在地图ID,注意次地图并不一定是玩家当前地图 @param npcCountDict: 执行单次时所击杀的npc数量字典 {npcID:count, ...} @param exp_rate: 击杀怪物享受的经验比例 @param mailTypeKey: 获取物品背包空间不足时发送的邮件模板key @param isMail: 是否强制发送邮件,若是则不考虑背包空间,否的话只在背包空间不足时才发送邮件 - @param extraItemList: 固定附加物品列表,如果需执行多次,则此固定产出列表需在外层处理好,内层不做多次执行处理。[[itemID, itemCount, isBind], ...] + @param extraItemList: 固定附加物品列表,如果需执行多次,则此固定产出列表需在外层处理好,内层不做多次执行处理。[[itemID, itemCount, isAuctionItem], ...] @param prizeMultiple: 奖励倍值, 对所有奖励有效,等于击杀多次NPC,多倍附加物品 + @param dropItemMapInfo: 掉落地板信息 [dropPosX, dropPosY, 是否仅自己可见, 堆叠物品是否散开] + @param curGrade: 评级 + @param isVirtualDrop: 是否给物品虚拟掉落表现 ''' if not exp_rate: exp_rate = PlayerControl.GetPlayerExpRate(curPlayer) @@ -418,7 +426,7 @@ totalExp = 0 totalMoney = 0 itemCountDict = {} - itemBindDict = {} + auctionItemIDList = [] if prizeMultiple > 1: hadDropItemKeyList, hadDropItemPlaceList = [], [] # 已经掉落过的物品集合key列表, 已经掉落过的装备部位列表 @@ -440,11 +448,11 @@ # 掉落有概率因素,需多次执行 for dCount in xrange(1, totalCount + 1): - isKillCountDropEquipEx = dCount == 1 # 同一只NPC一次处理中多次击杀的情况,只算一次附加装备处理 - dropInfo = GetNPCDropInfo(curPlayer, mapID, npcID, isKillCountDropEquipEx=isKillCountDropEquipEx, curGrade=curGrade) + isKillCountDrop = dCount == 1 # 同一只NPC一次处理中多次击杀的情况,只算一次附加装备处理 + dropInfo = GetNPCDropInfo(curPlayer, mapID, npcID, isKillCountDrop=isKillCountDrop, curGrade=curGrade) if not dropInfo: continue - dropIDList, dropIDBindDict, dropMoneyCnt, moneyValue = dropInfo + dropIDList, auctionIDList, dropMoneyCnt, moneyValue = dropInfo totalMoney += (dropMoneyCnt * moneyValue) for itemID in dropIDList: @@ -476,12 +484,14 @@ hadDropItemKeyList.append(itemKey) itemCountDict[itemID] = itemCountDict.get(itemID, 0) + 1 - itemBindDict[itemID] = dropIDBindDict.get(itemID, 1) + if itemID in auctionIDList and itemID not in auctionItemIDList: + auctionItemIDList.append(itemID) # 固定附加物品 - for itemID, itemCount, isBind in extraItemList: + for itemID, itemCount, isAuctionItem in extraItemList: itemCountDict[itemID] = itemCountDict.get(itemID, 0) + itemCount * prizeMultiple - itemBindDict[itemID] = isBind + if isAuctionItem and itemID not in auctionItemIDList: + auctionItemIDList.append(itemID) needSpace = 0 prizeItemList = [] @@ -491,64 +501,34 @@ if not itemData: continue - isBind = itemBindDict.get(itemID, 1) + isAuctionItem = itemID in auctionItemIDList if ItemCommon.GetIsEquip(itemData): for _ in xrange(itemCount): - curItem = ItemControler.GetOutPutItemObj(itemID) + curItem = ItemControler.GetOutPutItemObj(itemID, 1, isAuctionItem, curPlayer=curPlayer) if curItem: needSpace += 1 prizeItemList.append(curItem) jsonItemList.append(ItemCommon.GetJsonItem(curItem)) else: - needSpace += int(math.ceil(itemCount / float(itemData.GetPackCount()))) - prizeItemList.append([itemID, itemCount, isBind]) - jsonItemList.append(ItemCommon.GetJsonItem([itemID, itemCount, isBind])) + needSpace += ItemControler.GetItemNeedPackCount(IPY_GameWorld.rptItem, itemData, itemCount, isAuctionItem) + prizeItemList.append([itemID, itemCount, isAuctionItem]) + jsonItemList.append(ItemCommon.GetJsonItem([itemID, itemCount, isAuctionItem])) #成就 if not dropItemMapInfo: PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_PickUpItem, itemCount, [itemID]) ## 直接掉地板上 if dropItemMapInfo: - dropPosX, dropPosY, isOnlySelfSee = dropItemMapInfo[:3] + dropPosX, dropPosY = dropItemMapInfo[:2] + isOnlySelfSee = dropItemMapInfo[2] if len(dropItemMapInfo) > 2 else False # 是否仅自己可见 isDropDisperse = dropItemMapInfo[3] if len(dropItemMapInfo) > 3 else False # 堆叠的物品是否散开掉落 - if isDropDisperse: - dropItemList = [] - for itemInfo in prizeItemList: - if isinstance(itemInfo, list): - itemID, itemCount, isBind = itemInfo - for _ in xrange(itemCount): - dropItemList.append([itemID, 1, isBind]) - else: - dropItemList.append(itemInfo) + ## 虚拟掉落表现 + if isVirtualDrop: + DoGiveItemByVirtualDrop(curPlayer, prizeItemList, npcID, dropPosX, dropPosY, isDropDisperse, mailTypeKey) else: - dropItemList = prizeItemList - index = 0 - playerID = curPlayer.GetPlayerID() - gameMap = GameWorld.GetMap() - for posX, posY in ChConfig.Def_DropItemAreaMatrix: - resultX = dropPosX + posX - resultY = dropPosY + posY + DoMapDropPrizeItem(curPlayer, prizeItemList, npcID, dropPosX, dropPosY, isDropDisperse, isOnlySelfSee) - if not gameMap.CanMove(resultX, resultY): - #玩家不可移动这个点 - continue - - if index > len(dropItemList) - 1: - break - - curItem = dropItemList[index] - index += 1 - if isinstance(curItem, list): - itemID, itemCount, isBind = curItem - curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, False) - - if not curItem: - continue - - ChItem.AddMapDropItem(resultX, resultY, curItem, ownerInfo=[ChConfig.Def_NPCHurtTypePlayer, playerID], - dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee) - ## 发邮件 或 背包空间不足 elif isMail or needSpace > ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace): mailItemList = [] @@ -568,8 +548,8 @@ event = [ChConfig.ItemGive_NPCDrop, False, {"NPCID":npcID}] for prizeItem in prizeItemList: if isinstance(prizeItem, list): - itemID, itemCount, isBind = prizeItem - ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isBind, [IPY_GameWorld.rptItem], + itemID, itemCount, isAuctionItem = prizeItem + ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem], event=event) else: ItemControler.DoLogic_PutItemInPack(curPlayer, prizeItem, event=event) @@ -584,6 +564,117 @@ # % (mapID, npcCountDict, exp_rate, mailTypeKey, isMail, extraItemList)) #GameWorld.DebugLog(" totalExp=%s,totalMoney=%s,needSpace=%s,jsonItemList=%s" % (totalExp, totalMoney, needSpace, jsonItemList)) return jsonItemList, totalExp, totalMoney + +def DoMapDropPrizeItem(curPlayer, prizeItemList, npcID, dropPosX, dropPosY, isDropDisperse=True, isOnlySelfSee=True): + ## 奖励物品真实掉落地图,先拆开分散再掉落 + + if isDropDisperse: + dropItemList = [] + for itemInfo in prizeItemList: + if isinstance(itemInfo, list): + itemID, itemCount, isAuctionItem = itemInfo + for _ in xrange(itemCount): + dropItemList.append([itemID, 1, isAuctionItem]) + else: + dropItemList.append(itemInfo) + else: + dropItemList = prizeItemList + index = 0 + playerID = curPlayer.GetPlayerID() + gameMap = GameWorld.GetMap() + for posX, posY in ChConfig.Def_DropItemAreaMatrix: + resultX = dropPosX + posX + resultY = dropPosY + posY + + if not gameMap.CanMove(resultX, resultY): + #玩家不可移动这个点 + continue + + if index > len(dropItemList) - 1: + break + + curItem = dropItemList[index] + index += 1 + if isinstance(curItem, list): + itemID, itemCount, isAuctionItem = curItem + curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isAuctionItem, curPlayer=curPlayer) + + if not curItem: + continue + + ChItem.AddMapDropItem(resultX, resultY, curItem, ownerInfo=[ChConfig.Def_NPCHurtTypePlayer, playerID], + dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee) + return + +def DoGiveItemByVirtualDrop(curPlayer, giveItemList, npcID, dropPosX=0, dropPosY=0, isDropDisperse=True, mailTypeKey="ItemNoPickUp"): + ## 给物品并且做假掉落表现,直接先堆叠给物品,再拆开做虚假掉落表现 + + mapID = PlayerControl.GetCustomMapID(curPlayer) + lineID = PlayerControl.GetCustomLineID(curPlayer) + if not mapID: + mapID = GameWorld.GetGameWorld().GetMapID() + + playerID = curPlayer.GetPlayerID() + giveItemObjList = [] + virtualItemDropList = [] + itemControl = ItemControler.PlayerItemControler(curPlayer) + for itemInfo in giveItemList: + if isinstance(itemInfo, list): + itemID, itemCount, isAuctionItem = itemInfo + curItem = ItemControler.GetOutPutItemObj(itemID, itemCount, isAuctionItem, curPlayer=curPlayer) + if not curItem: + continue + else: + curItem = itemInfo + itemID = curItem.GetItemTypeID() + itemCount = curItem.GetCount() + isAuctionItem = ItemControler.GetIsAuctionItem(curItem) + dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem) + giveItemObjList.append(curItem) + + # 散开掉落 + if isDropDisperse: + for _ in xrange(itemCount): + virtualItemDropList.append([itemID, dropItemDataStr]) + else: + virtualItemDropList.append([itemID, dropItemDataStr]) + + # 先通知掉落,再给物品,因为前端表现弹框需要这个顺序需求 + gameMap = GameWorld.GetMap() + index = 0 + for posX, posY in ChConfig.Def_DropItemAreaMatrix: + if dropPosX or dropPosY: + resultX = dropPosX + posX + resultY = dropPosY + posY + if not gameMap.CanMove(resultX, resultY): + #玩家不可移动这个点 + continue + else: + resultX, resultY = 0, 0 + if index > len(virtualItemDropList) - 1: + break + itemID, dropItemDataStr = virtualItemDropList[index] + index += 1 + SendVirtualItemDrop(curPlayer, itemID, resultX, resultY, dropItemDataStr) + + # 再给物品 + mailItemList = [] + for itemObj in giveItemObjList: + itemID = itemObj.GetItemTypeID() + mailItem = ItemCommon.GetMailItemDict(itemObj) + equipInfo = [itemObj.GetEquipPlace(), ItemCommon.GetItemClassLV(itemObj), itemObj.GetItemColor(), + itemObj.GetSuiteID(), itemObj.GetUserData()] + packIndex = ChConfig.GetItemPackType(itemObj.GetType()) + if not itemControl.PutInItem(packIndex, itemObj, event=[ChConfig.ItemGive_Pickup, False, {"NPCID":npcID}]): + mailItemList.append(mailItem) + + if npcID: + SendGameServerGoodItemRecord(curPlayer, mapID, lineID, npcID, itemID, equipInfo) + + # 放不下的发邮件 + if mailItemList: + PlayerControl.SendMailByKey(mailTypeKey, [playerID], mailItemList, [mapID]) + return ################################### NPC掉落 ################################### Def_NPCMaxDropRate = 1000000 # NPC掉落相关的最大概率, 数值设定 @@ -651,13 +742,13 @@ GameWorld.DebugLog("脱机挂杀怪掉落: npcID=%s,killCount=%s,itemJobList=%s,dropRatePlusValue=%s,equipDropRatePlus=%s,equipDropDoCountPlus=%s" % (npcID, killCount, itemJobList, dropRatePlusValue, equipDropRatePlus, equipDropDoCountPlus), playerID) - dropEquipInfoList = [] # [(阶,颜色,部位集合key, 件数), ...] + dropEquipInfoList = [] # [(阶,颜色, 件数), ...] # 1.装备只算饼图概率 pieRateDoCnt = ipyDrop.GetPieRateDoCnt() if pieRateDoCnt and ipyDrop.GetPieRateDrop(): pieRateDoCnt = __GetNPCDropDoCountChange(pieRateDoCnt, doCountRate + equipDropDoCountPlus, doCountAdd) pieRateDoCnt *= killCount - pieRateDropList = ipyDrop.GetPieRateDrop() # [(概率,0),(概率,(阶,颜色,部位集合key)),...] + pieRateDropList = ipyDrop.GetPieRateDrop() # [(概率,0),(概率,(阶,颜色)),...] if equipDropRatePlus: dropRateList = GameWorld.GetPlusPieList(pieRateDropList, equipDropRatePlus) GameWorld.DebugLog(" 装备配置饼图: %s,equipDropRatePlus=%s" % (pieRateDropList, equipDropRatePlus), playerID) @@ -674,50 +765,52 @@ preRate = rate if not equipInfo: continue - classLV, color, placeKey = equipInfo + classLV, color = equipInfo totalRate = curRate * pieRateDoCnt # 总概率 dropCount = totalRate / maxRate # 可掉落件数 rateEx = totalRate % maxRate # 剩余概率 if GameWorld.CanHappen(rateEx, maxRate): dropCount += 1 - GameWorld.DebugLog(" 装备掉率: curRate=%s,totalRate=%s,rateEx=%s,dropCount=%s,classLV=%s,color=%s,placeKey=%s" - % (curRate, totalRate, rateEx, dropCount, classLV, color, placeKey), playerID) + GameWorld.DebugLog(" 装备掉率: curRate=%s,totalRate=%s,rateEx=%s,dropCount=%s,classLV=%s,color=%s" + % (curRate, totalRate, rateEx, dropCount, classLV, color), playerID) if not dropCount: continue - dropEquipInfoList.append([classLV, color, placeKey, dropCount]) - GameWorld.DebugLog(" 装备掉落结果: killCount=%s,[阶,颜色,部位集合,件数]=%s" % (killCount, dropEquipInfoList), playerID) + dropEquipInfoList.append([classLV, color, dropCount]) + GameWorld.DebugLog(" 装备掉落结果: killCount=%s,[阶,颜色,件数]=%s" % (killCount, dropEquipInfoList), playerID) - placeDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1) - - # 颜色对应星级概率 + placeKeyListDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1) + colorSuitRateDict = ipyDrop.GetEquipColorSuitInfo() # 装备颜色对应套装概率 {颜色:套装概率, ...} + colorSuitPlaceKeyInfoDict = ipyDrop.GetEquipPartKeyRateInfo() # 装备部位集合信息 {(颜色,是否套装):部位集合key, ...} dropEquipIDDict = {} - colorStarRateDict = ipyDrop.GetEquipStarInfo() # {颜色:[(概率, 星级),...], ...}, 没有配置的默认最低星 紫-0,橙红-1 - for classLV, color, placeKey, dropCount in dropEquipInfoList: - if placeKey not in placeDict: - GameWorld.ErrLog("部位集合key不存在!npcID=%s,placeKey=%s" % (npcID, placeKey)) - continue - starCountDict = {} # {星级:件数, ...} - placeList = placeDict[placeKey] - if color in colorStarRateDict: - colorStarRateList = colorStarRateDict[color] + for classLV, color, dropCount in dropEquipInfoList: + suitCountDict = {} # {套装:件数, ...} + if color in colorSuitRateDict: + suitRate = colorSuitRateDict[color] for _ in xrange(dropCount): - star = GameWorld.GetResultByRandomList(colorStarRateList, 0) # 默认0星 - starCountDict[star] = starCountDict.get(star, 0) + 1 - elif color >= ChConfig.Def_Quality_Orange: # 橙色及以上的默认1星 - starCountDict[1] = dropCount + isSuit = GameWorld.CanHappen(suitRate, maxRate=Def_NPCMaxDropRate) + suitCountDict[isSuit] = suitCountDict.get(isSuit, 0) + 1 else: - starCountDict[0] = dropCount + suitCountDict[0] = dropCount - for star, curStarDropCount in starCountDict.items(): - randEquipIDList = __GetEquipIDList(npcID, classLV, color, placeList, star, itemJobList) + for isSuit, curDropCount in suitCountDict.items(): + colorSuitKey = (color, isSuit) + if colorSuitKey not in colorSuitPlaceKeyInfoDict: + GameWorld.ErrLog("未配置颜色是否套装对应部位集合key! npcID=%s,color=%s,isSuit=%s" % (npcID, color, isSuit)) + continue + placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey] + if placeKey not in placeKeyListDict: + 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 - for _ in xrange(curStarDropCount): + for _ in xrange(curDropCount): randItemID = random.choice(randEquipIDList) dropIDList.append(randItemID) dropEquipIDDict[randItemID] = [color, placeKey] - GameWorld.DebugLog(" 掉落装备: npcID=%s,itemID=%s,classLV=%s,color=%s,star=%s,placeKey=%s,itemJobList=%s,randEquipIDList=%s" - % (npcID, randItemID, classLV, color, star, placeKey, itemJobList, randEquipIDList), playerID) + GameWorld.DebugLog(" 掉落装备: npcID=%s,itemID=%s,classLV=%s,color=%s,isSuit=%s,placeKey=%s,itemJobList=%s,randEquipIDList=%s" + % (npcID, randItemID, classLV, color, isSuit, placeKey, itemJobList, randEquipIDList), playerID) # 2. 指定物品ID库 itemIDDropRateDict = ipyDrop.GetItemIDDropRate() # {物品ID:概率, ...} @@ -743,10 +836,6 @@ # 检查掉落互斥ID组 dropIDList = __RemoveMutexDropID(dropIDList, IpyGameDataPY.GetFuncCfg("MutexDrop", 1)) - # 获取掉落物品绑定信息 - isGameBoss = ChConfig.IsGameBoss(npcData) - dropIDBindDict = __GetNPCDropItemBindInfo(mapID, isGameBoss, dropIDList, dropEquipIDDict) - # 掉落金币 dropMoneyDoCnt = ipyDrop.GetDropMoneyDoCnt() dropMoneyRate = ipyDrop.GetDropMoneyRate() @@ -763,12 +852,18 @@ for dropID in dropIDList: dropIDCountDict[dropID] = dropIDCountDict.get(dropID, 0) + 1 + auctionIDList = [] + if ipyDrop.GetAucionItemCanSell(): + for dropID in dropIDCountDict.keys(): + if IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropID): + auctionIDList.append(dropID) + if dropIDCountDict: - GameWorld.DebugLog(" 最终掉落: npcID=%s,killCount=%s,dropIDCountDict=%s,dropIDBindDict=%s,dropMoney=%s" - % (npcID, killCount, dropIDCountDict, dropIDBindDict, dropMoney), playerID) - return dropIDCountDict, dropIDBindDict, dropMoney + GameWorld.DebugLog(" 最终掉落: npcID=%s,killCount=%s,dropIDCountDict=%s,auctionIDList=%s,dropMoney=%s" + % (npcID, killCount, dropIDCountDict, auctionIDList, dropMoney), playerID) + return dropIDCountDict, auctionIDList, dropMoney -def GetNPCDropInfo(dropPlayer, mapID, npcID, ownerPlayerList=[], ipyDrop=None, isSingle=True, isKillCountDropEquipEx=True, curGrade=0): +def GetNPCDropInfo(dropPlayer, mapID, npcID, ownerPlayerList=[], ipyDrop=None, isSingle=True, isKillCountDrop=True, curGrade=0): '''获取NPC掉落信息, 击杀及扫荡通用,调用该函数获得掉落信息,然后再看掉落地板上还是直接放入背包 @param dropPlayer: 用于判断调用相关用的玩家示例,该玩家并不一定是击杀者,只是按一定规则设定的掉落判断依据的玩家 如队伍,取等级最大的玩家,该玩家并不一定是击杀者 @@ -776,11 +871,11 @@ @param npcID: 掉落物品的NPCID @param ownerPlayerList: 有归属的玩家列表 @param isSingle: 是否只处理单独玩家掉落逻辑,一般都默认True,目前只有场景杀怪掉落需要考虑摸怪的情况下才为False(外层特殊处理) - @return: dropIDList, dropIDBindDict, dropMoneyCnt, moneyValue + @return: dropIDList, auctionIDList, dropMoneyCnt, moneyValue None-没有掉落 --------------- dropIDList - 掉落的物品ID列表, 同个itemID可能在列表中有多个 [itemID, itemID, ...] - dropIDBindDict - 掉落的物品ID绑定信息 {itemID:是否绑定, ...} + auctionIDList - 掉落的拍品物品ID列表, [itemID, itemID, ...] dropMoneyCnt - 掉落金币位置数 moneyValue - 每个位置的金币数量 ''' @@ -805,21 +900,8 @@ return dropIDList = [] # 掉落的ID列表 - dropIDBindDict = {} + auctionIDList = [] dropMoneyCnt, moneyValue = 0, 0 - - # 1. 击杀次数掉落 - killCountDropIDList = [] - killCountDropInfo = ipyDrop.GetKillCountDrop() - if isSingle and killCountDropInfo: - needKillCount, isDropInItemPack, isBind, killDropItemList = killCountDropInfo - killCountDropIDList = GetKillCountDropItemList(dropPlayer, npcID, needKillCount, killDropItemList) - for kDropItemID in killCountDropIDList: - dropIDList.append(kDropItemID) # 单独玩家掉落处理的,直接加到掉落列表里,不考虑是否放入背包或掉落的情况,由使用的功能自行处理 - dropIDBindDict[kDropItemID] = isBind - #GameWorld.DebugLog("击杀次数掉落: kDropItemID=%s,needKillCount=%s,isDropInItemPack=%s,isBind=%s" - # % (kDropItemID, needKillCount, isDropInItemPack, isBind)) - itemJobList = [dropPlayer.GetJob()] if ipyDrop.GetIsDropJobSelf() else IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1) # 掉落装备职业列表 # 通用掉率相关 @@ -830,12 +912,23 @@ doCountRate = ChConfig.Def_MaxRateValue # 归属者相关信息 - dropEquipExKillCount = 0 # 装备附加掉落综合击杀次数,取次数最少的那个,至少第一次 + tagJob = 0 + dropEquipKillCountPub = 0 # 装备附加掉落综合击杀次数,取次数最大的那个,至少第一次 + dropItemIDKillCountPub = 0 # 物品ID附加掉落综合击杀次数,取次数最大的那个,至少第一次 equipDropRatePlus = 0 # 装备掉落概率提升 equipDropDoCountPlus = 0 # 装备掉落执行次数提升 for ownerPlayer in ownerPlayerList: - ownerKillCount = ownerPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID) + 1 - dropEquipExKillCount = ownerKillCount if not dropEquipExKillCount else min(dropEquipExKillCount, ownerKillCount) + killCountValue = ownerPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID) + equipPubKillCount = killCountValue % 100 + 1 + itemIDPubKillCount = killCountValue % 10000 / 100 + 1 + + if dropEquipKillCountPub < equipPubKillCount: + dropEquipKillCountPub = equipPubKillCount + tagJob = ownerPlayer.GetJob() + + if dropItemIDKillCountPub < itemIDPubKillCount: + dropItemIDKillCountPub = itemIDPubKillCount + equipDropRatePlus = max(equipDropRatePlus, PlayerControl.GetDropEquipPer(ownerPlayer)) equipDropDoCountPlus = max(equipDropDoCountPlus, PlayerControl.GetDropEquipDoCount(ownerPlayer)) @@ -849,185 +942,147 @@ #GameWorld.DebugLog("NPC掉落: npcID=%s,itemJobList=%s,dropRatePlusValue=%s,equipDropRatePlus=%s,equipDropDoCountPlus=%s,doCountRate=%s,doCountAdd=%s" # % (npcID, itemJobList, dropRatePlusValue, equipDropRatePlus, equipDropDoCountPlus, doCountRate, doCountAdd), playerID) - dropEquipInfoList = [] # [(阶,颜色,部位集合key), ...] - # 2. 装备库 - 饼图概率 + dropEquipInfoList = [] # [(阶,颜色), ...] + # 1. 装备库 - 饼图概率 pieRateDoCnt = ipyDrop.GetPieRateDoCnt() if pieRateDoCnt: pieRateDoCnt = __GetNPCDropDoCountChange(pieRateDoCnt, doCountRate + equipDropDoCountPlus, doCountAdd) dropEquipInfoList += __GetNPCPieRateEquipDrop(ipyDrop, pieRateDoCnt, equipDropRatePlus) - # 3. 装备库 - 独立概率 + # 2. 装备库 - 独立概率 indepRateDoCnt = ipyDrop.GetIndepRateDoCnt() if indepRateDoCnt: indepRateDoCnt = __GetNPCDropDoCountChange(indepRateDoCnt, doCountRate + equipDropDoCountPlus, doCountAdd) - dropEquipInfoList += __GetNPCIndepRateEquipDrop(ipyDrop, indepRateDoCnt, equipDropRatePlus, curGrade) - - #GameWorld.DebugLog("阶,颜色,部位集合key,dropEquipInfoList=%s" % (dropEquipInfoList)) - placeDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1) - # 第x次击杀,附加装备产出; 前x次击杀,附加装备产出; 归属者综合附加掉落,所有归属者都增加击杀次数; - # [次数,阶,颜色,[(概率,星级),...],部位集合key] - killCountDropEquipEx, killCountDropEquipEx2 = ipyDrop.GetKillCountDropEquipEx(), ipyDrop.GetKillCountDropEquipEx2() - isKillCountDropEquipEx = isKillCountDropEquipEx and (killCountDropEquipEx or killCountDropEquipEx2) - if isKillCountDropEquipEx and killCountDropEquipEx and dropEquipExKillCount == killCountDropEquipEx[0]: # 优先第x次击杀 - tagKillCount, tagClassLV, tagColor, tagStarRateList, tagPlaceKey = killCountDropEquipEx - elif isKillCountDropEquipEx and killCountDropEquipEx2 and dropEquipExKillCount <= killCountDropEquipEx2[0]: # 前x次击杀 - tagKillCount, tagClassLV, tagColor, tagStarRateList, tagPlaceKey = killCountDropEquipEx2 - else: - tagKillCount, tagClassLV, tagColor, tagStarRateList, tagPlaceKey = 0, 0, 0, [], 0 - maxRecordKillCount = tagKillCount # 需要记录的最大击杀次数, 超过此击杀次数后暂时不累加记录 - if tagStarRateList: - tagStar = GameWorld.GetResultByRandomList(tagStarRateList, 0) - tagStarMin = tagStarRateList[0][1] - else: - tagStar = None # 有0星的情况,所以这里默认使用None - tagStarMin = None - tagPlaceList = [] if tagPlaceKey not in placeDict else placeDict[tagPlaceKey] - tagPlace = 0 - tagJob = 0 - tagItemReplaceState = False + dropEquipInfoList += __GetNPCIndepRateEquipDrop(ipyDrop, indepRateDoCnt, equipDropRatePlus, curGrade) + #GameWorld.DebugLog("阶,颜色 key,dropEquipInfoList=%s" % (dropEquipInfoList)) - # 附加装备部位优先级分两个列表, 品质阶级都不满足的列表、品质阶级部分满足的列表 - # 部位优先级规则, 只算身上有穿的部位,没穿装备的不管 - #1)优先品质、阶数、星级都不满足,其次品质、阶数、星级部分满足 - #2)品质、阶数、星级都不满足时,按品质、阶数、星级、评分升序排序 - #3)品质、阶数、星级部分满足时,按品质、阶数、星级、评分升序排序 - #4)品质、阶数、星级都满足时,排除优先部位 - tagPlaceSortList, tagPlaceSortList2 = [], [] - for ownerPlayer in ownerPlayerList: - # 有附加目标装备需求的,统计该归属者身上需要附加给装备的部位 - playerEquip = ownerPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip) - if tagClassLV and tagColor and tagPlaceList: - for equipIndex in xrange(playerEquip.GetCount()): - if equipIndex not in tagPlaceList: - continue - curEquip = playerEquip.GetAt(equipIndex) - if curEquip.IsEmpty(): - continue - curEquipClassLV = ItemCommon.GetItemClassLV(curEquip) - curEquipColor = curEquip.GetItemColor() - curEquipStar = curEquip.GetItemQuality() - equipGS = ItemCommon.GetEquipGearScore(curEquip) - # 品质阶级都不满足 - if curEquipClassLV < tagClassLV and curEquipColor < tagColor and curEquipStar < tagStarMin: - tagPlaceSortList.append([curEquipColor, curEquipClassLV, curEquipStar, equipGS, equipIndex, ownerPlayer.GetJob()]) - # 品质阶级部分不满足 - elif curEquipClassLV < tagClassLV or curEquipColor < tagColor or curEquipStar < tagStarMin: - tagPlaceSortList2.append([curEquipColor, curEquipClassLV, curEquipStar, equipGS, equipIndex, ownerPlayer.GetJob()]) - - # 增加击杀次数 - killCount = ownerPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID) + 1 - if killCount <= maxRecordKillCount: - PlayerControl.NomalDictSetProperty(ownerPlayer, ChConfig.Def_PDict_NPCKillCount % npcID, killCount) - GameWorld.DebugLog("玩家击杀次数: npcID=%s,killCount=%s,maxRecordKillCount=%s" - % (npcID, killCount, maxRecordKillCount), ownerPlayer.GetPlayerID()) - - tagPlaceSortList.sort() # 升序排序 - tagPlaceSortList2.sort() # 升序排序 - if isKillCountDropEquipEx: - GameWorld.DebugLog("都不满足目标装备的优先级信息: npcID=%s, 数量=%s, 颜色,阶,星,评分,部位,职业=%s" % (npcID, len(tagPlaceSortList), tagPlaceSortList), playerID) - GameWorld.DebugLog("部分满足目标装备的优先级信息: npcID=%s, 数量=%s, 颜色,阶,星,评分,部位,职业=%s" % (npcID, len(tagPlaceSortList2), tagPlaceSortList2), playerID) - if tagPlaceSortList or tagPlaceSortList2: - isOptimalPlace = IpyGameDataPY.GetFuncCfg("DropEquipPlaceMode", 1) # 是否取最优解部位 - if isOptimalPlace: - tagPlaceSortList += tagPlaceSortList2 - if tagPlaceSortList: - tagPlace = tagPlaceSortList[0][-2] - tagJob = tagPlaceSortList[0][-1] - GameWorld.DebugLog("掉落目标部位取最优解: tagPlace=%s,tagJob=%s" % (tagPlace, tagJob), playerID) + # 3. 第x次击杀, 归属者公共附加掉落,所有归属者都增加击杀次数; + tagClassLV, tagColor, tagIsSuit, tagPlaceKey = 0, 0, 0, 0 + killCountDropEquipPub = ipyDrop.GetKillCountDropEquipPub() # 第x次击杀附加必掉装备 {次数:[阶,颜色,是否套装,部位集合key], ...} + killCountDropItemPub = ipyDrop.GetKillCountDropPub() # 击杀次数必掉(公共){击杀次数:[[物品ID, ...], [随机物品ID, ...]], ...} + maxRecordDropEquipKillCountPub = 0 if not killCountDropEquipPub else max(killCountDropEquipPub) # 需要记录的最大击杀次数, 超过此击杀次数后暂时不累加记录 + maxRecordDropItemIDKillCountPub = 0 if not killCountDropItemPub else max(killCountDropItemPub) + #GameWorld.DebugLog("maxRecordDropEquipKillCountPub=%s,maxRecordDropItemIDKillCountPub=%s" % (maxRecordDropEquipKillCountPub, maxRecordDropItemIDKillCountPub)) + #GameWorld.DebugLog("dropEquipKillCountPub=%s,dropItemIDKillCountPub=%s" % (dropEquipKillCountPub, dropItemIDKillCountPub)) + if isKillCountDrop and killCountDropEquipPub and dropEquipKillCountPub in killCountDropEquipPub: + tagClassLV, tagColor, tagIsSuit, tagPlaceKey = killCountDropEquipPub[dropEquipKillCountPub] + if (tagClassLV, tagColor) not in dropEquipInfoList: + dropEquipInfoList.insert(0, (tagClassLV, tagColor, tagIsSuit, tagPlaceKey, tagJob)) else: - randPlaceCountLimit = IpyGameDataPY.GetFuncCfg("DropEquipPlaceMode", 2) # 全不满足目标条件部位有几个时才优先随机 - if len(tagPlaceSortList) < randPlaceCountLimit: - tagPlaceSortList += tagPlaceSortList2 - else: - GameWorld.DebugLog("优先随机都不满足目标装备的,randPlaceCountLimit=%s" % randPlaceCountLimit, playerID) - randPlaceIndex = random.randint(0, len(tagPlaceSortList) - 1) - GameWorld.DebugLog("掉落目标部位随机, randPlaceIndex=%s, 颜色,阶,星,评分,部位,职业=%s" % (randPlaceIndex, tagPlaceSortList), playerID) - tagPlace = tagPlaceSortList[randPlaceIndex][-2] - tagJob = tagPlaceSortList[randPlaceIndex][-1] - GameWorld.DebugLog("掉落目标部位随机不满足条件的: tagPlace=%s,tagJob=%s" % (tagPlace, tagJob), playerID) + tagIndex = dropEquipInfoList.index((tagClassLV, tagColor)) + dropEquipInfoList[tagIndex] = (tagClassLV, tagColor, tagIsSuit, tagPlaceKey, tagJob) + GameWorld.DebugLog("第%s次击杀掉落指定目标装备信息: npcID=%s,tagClassLV=%s,tagColor=%s,tagIsSuit=%s,tagPlaceKey=%s,tagJob=%s,dropEquipInfoList=%s" + % (dropEquipKillCountPub, npcID, tagClassLV, tagColor, tagIsSuit, tagPlaceKey, tagJob, dropEquipInfoList), playerID) + elif isKillCountDrop and killCountDropItemPub and dropItemIDKillCountPub in killCountDropItemPub: + killCountItemIDList, killCountRandItemIDList = killCountDropItemPub[dropItemIDKillCountPub] + if killCountItemIDList: + dropIDList += killCountItemIDList + if killCountRandItemIDList: + klllCountRandItemID = random.choice(killCountRandItemIDList) + dropIDList.append(klllCountRandItemID) + GameWorld.DebugLog("第%s次击杀掉落指定目标物品信息: npcID=%s,killCountItemIDList=%s,killCountRandItemIDList=%s,dropIDList=%s" + % (dropItemIDKillCountPub, npcID, killCountItemIDList, killCountRandItemIDList, dropIDList), playerID) - if isKillCountDropEquipEx: - GameWorld.DebugLog("附加掉落指定目标装备信息: npcID=%s,玩家最少的击杀次数=%s,目标击杀数=%s,tagClassLV=%s,tagColor=%s,tagStar=%s,tagStarMin=%s,tagPlace=%s,tagJob=%s" - % (npcID, dropEquipExKillCount, tagKillCount, tagClassLV, tagColor, tagStar, tagStarMin, tagPlace, tagJob), playerID) - # 颜色对应星级概率 - dropEquipIDDict = {} - colorStarRateDict = ipyDrop.GetEquipStarInfo() # {颜色:[(概率, 星级),...], ...}, 没有配置的默认最低星 紫-0,橙红-1 - gradeColorStarRateDict = {} - fbGradeColorStarRateDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 2) # 评级影响品质星级概率 {npcID:{(颜色,星级):[D级影响概率, ..., S级影响概率], ...}, ...} - if npcID in fbGradeColorStarRateDict: - gradeColorStarRateDict = fbGradeColorStarRateDict[npcID] + for ownerPlayer in ownerPlayerList: + # 增加击杀次数 + killCountValue = ownerPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID) + equipPubKillCount = killCountValue % 100 + itemIDPubKillCount = killCountValue % 10000 / 100 + isUpd = False + if equipPubKillCount < maxRecordDropEquipKillCountPub: + equipPubKillCount += 1 + isUpd = True + if itemIDPubKillCount < maxRecordDropItemIDKillCountPub: + itemIDPubKillCount += 1 + isUpd = True + + if isUpd: + itemIDPriKillCount = killCountValue / 10000 + updKillCountValue = itemIDPriKillCount * 10000 + itemIDPubKillCount * 100 + equipPubKillCount + PlayerControl.NomalDictSetProperty(ownerPlayer, ChConfig.Def_PDict_NPCKillCount % npcID, updKillCountValue) + GameWorld.DebugLog("更新玩家击杀次数值: npcID=%s,killCountValue=%s,updKillCountValue=%s" % (npcID, killCountValue, updKillCountValue), ownerPlayer.GetPlayerID()) + + gradeColorSuitRateDict = {} + fbGradeColorSuitRateDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 2) # 评级影响颜色套装概率 {npcID:{颜色:[D级影响概率, ..., S级影响概率], ...}, ...} + if npcID in fbGradeColorSuitRateDict: + gradeColorSuitRateDict = fbGradeColorSuitRateDict[npcID] curGrade = curGrade if curGrade else GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade) + placeKeyListDict = IpyGameDataPY.GetFuncCfg("EquipDropPartSets", 1) colorDropCntDict = {} # 装备颜色已经掉落数 {颜色:数量, ...} - colorMaxDropCntDict = ipyDrop.GetIndepRateMaxDropCount() # {颜色:上限数量,...} - for classLV, color, placeKey in dropEquipInfoList: - - # 装备颜色对应最大掉落件数改为公共限制条件 + colorMaxDropCntDict = ipyDrop.GetEquipColorMaxDropCount() # {颜色:上限数量,...} + colorSuitRateDict = ipyDrop.GetEquipColorSuitInfo() # 装备颜色对应套装概率 {颜色:套装概率, ...} + colorSuitPlaceKeyInfoDict = ipyDrop.GetEquipPartKeyRateInfo() # 装备部位集合信息 {(颜色,是否套装):部位集合key, ...} + colorSuitPartOptimization = ipyDrop.GetColorSuitPartOptimization() # 部位颜色套评分优选掉落,十位代表颜色,个位代表套装 + optColor, optIsSuit = colorSuitPartOptimization / 10, colorSuitPartOptimization % 10 + optPlace = None # 优选部位 + + for dropEquipInfo in dropEquipInfoList: + classLV, color = dropEquipInfo[:2] if color in colorMaxDropCntDict: maxCount = colorMaxDropCntDict[color] dropCount = colorDropCntDict.get(color, 0) if dropCount >= maxCount: GameWorld.DebugLog("已超过该颜色装备最大掉落数,不掉!color=%s,maxCount=%s" % (color, maxCount), playerID) continue - colorDropCntDict[color] = dropCount + 1 - # 有附加目标装备时,如果常规掉落有产出同颜色的 且 还没替换过 则直接替换该装备 - if tagColor == color and tagClassLV and tagStar != None and tagPlace and not tagItemReplaceState: - tagItemReplaceState = True - randEquipIDList = __GetEquipIDList(npcID, tagClassLV, tagColor, tagPlaceList, tagStar, [tagJob], tagPlace) - if not randEquipIDList: - continue - randItemID = random.choice(randEquipIDList) - dropIDList.append(randItemID) - dropEquipIDDict[randItemID] = [tagColor, tagPlaceKey] - GameWorld.DebugLog("替换指定颜色装备: npcID=%s,itemID=%s,tagClassLV=%s,tagColor=%s,tagPlace=%s,tagStar=%s,tagJob=%s,randEquipIDList=%s" - % (npcID, randItemID, tagClassLV, tagColor, tagPlace, tagStar, tagJob, randEquipIDList), playerID) + if len(dropEquipInfo) == 5: + isSuit, placeKey, tagJob = dropEquipInfo[2:] + jobList = [tagJob] else: - if placeKey not in placeDict: - GameWorld.ErrLog("部位集合key不存在!npcID=%s,placeKey=%s" % (npcID, placeKey)) + isSuit = 0 + if color in colorSuitRateDict: + suitRate = colorSuitRateDict[color] + # 评级对套装率的影响 + if color in gradeColorSuitRateDict: + suitRateEffList = gradeColorSuitRateDict[color] + suitRateEff = 10000 if (curGrade <= 0 or curGrade > len(suitRateEffList)) else suitRateEffList[curGrade - 1] + suitRate = int(suitRate * suitRateEff / 10000.0) + isSuit = GameWorld.CanHappen(suitRate, maxRate=Def_NPCMaxDropRate) + colorSuitKey = (color, isSuit) + if colorSuitKey not in colorSuitPlaceKeyInfoDict: + GameWorld.ErrLog("未配置颜色是否套装对应部位集合key! npcID=%s,color=%s,isSuit=%s" % (npcID, color, isSuit)) continue - placeList = placeDict[placeKey] - if color in colorStarRateDict: - colorStarRateList = colorStarRateDict[color] - if gradeColorStarRateDict: - colorStarRateList = __GetFBGradeColorStarRateList(color, colorStarRateList, gradeColorStarRateDict, curGrade) - star = GameWorld.GetResultByRandomList(colorStarRateList, 0) # 默认0星 - elif color >= ChConfig.Def_Quality_Orange: # 橙色及以上的默认1星 - star = 1 - else: - star = 0 - - randEquipIDList = __GetEquipIDList(npcID, classLV, color, placeList, star, itemJobList) - if not randEquipIDList: - continue - randItemID = random.choice(randEquipIDList) - dropIDList.append(randItemID) - dropEquipIDDict[randItemID] = [color, placeKey] - GameWorld.DebugLog("掉落装备: npcID=%s,itemID=%s,classLV=%s,color=%s,star=%s,placeKey=%s,itemJobList=%s,randEquipIDList=%s" - % (npcID, randItemID, classLV, color, star, placeKey, itemJobList, randEquipIDList), playerID) - - # 如果没有替换指定装备,则指定装备直接当做附加赠送掉落给 - if not tagItemReplaceState and tagClassLV and tagColor and tagStar != None and tagPlace: - randEquipIDList = __GetEquipIDList(npcID, tagClassLV, tagColor, tagPlaceList, tagStar, [tagJob], tagPlace) - if randEquipIDList: - randItemID = random.choice(randEquipIDList) - dropIDList.append(randItemID) - dropEquipIDDict[randItemID] = [tagColor, tagPlaceKey] - GameWorld.DebugLog("掉落指定目标装备: npcID=%s,itemID=%s,tagClassLV=%s,tagColor=%s,tagStar=%s,tagPlace=%s,tagJob=%s,randEquipIDList=%s" - % (npcID, randItemID, tagClassLV, tagColor, tagStar, tagPlace, tagJob, randEquipIDList), playerID) + placeKey = colorSuitPlaceKeyInfoDict[colorSuitKey] + # 掉落优选部位处理 + if color == optColor and isSuit == optIsSuit and placeKey in placeKeyListDict and optPlace == None: + optPlace = __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, placeKeyListDict[placeKey]) + 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] + randEquipIDList = __GetEquipIDList(npcID, classLV, color, isSuit, placeList, jobList) + if not randEquipIDList: + continue + if color in colorMaxDropCntDict: + colorDropCntDict[color] = dropCount + 1 + 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) # 4. 指定物品ID库 dropIDList += __GetAppointDropItemIDList(dropPlayer, npcID, ipyDrop, doCountRate, doCountAdd) - # 检查掉落互斥ID组 - dropIDList = __RemoveMutexDropID(dropIDList, IpyGameDataPY.GetFuncCfg("MutexDrop", 1)) - - # 获取掉落物品绑定信息 - isGameBoss = ChConfig.IsGameBoss(npcData) - dropIDBindDict = __GetNPCDropItemBindInfo(mapID, isGameBoss, dropIDList, dropEquipIDDict) - - # 5. 私有掉落固定产出,所有掉落归属者每人一份,默认绑定,不区分职业 + # 5. 私有掉落 if isSingle: + # 击杀次数掉落 + killCountDropInfo = ipyDrop.GetKillCountDropPri() + if killCountDropInfo: + needKillCount, killDropItemList = killCountDropInfo[:2] + killCountDropIDList = GetKillCountDropItemList(dropPlayer, npcID, needKillCount, killDropItemList) + for kDropItemID in killCountDropIDList: + dropIDList.append(kDropItemID) # 单独玩家掉落处理的,直接加到掉落列表里,不考虑是否放入背包或掉落的情况,由使用的功能自行处理 + #GameWorld.DebugLog("击杀次数掉落: kDropItemID=%s,needKillCount=%s" % (kDropItemID, needKillCount)) + + # 固定产出,所有掉落归属者每人一份,默认绑定,不区分职业 fbGradePriItemIDDropDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 3) if npcID in fbGradePriItemIDDropDict: gradePriItemIDDropDict = fbGradePriItemIDDropDict[npcID] @@ -1040,12 +1095,11 @@ priDropIDList = ipyDrop.GetPriItemIDDrop() for priDropID in priDropIDList: dropIDList.append(priDropID) - dropIDBindDict[priDropID] = 1 #GameWorld.DebugLog("私有物品掉落: priDropID=%s" % priDropID) + + # 检查掉落互斥ID组 + dropIDList = __RemoveMutexDropID(dropIDList, IpyGameDataPY.GetFuncCfg("MutexDrop", 1)) - if dropIDList: - GameWorld.DebugLog("最终掉落物品: npcID=%s,dropIDList=%s,dropIDBindDict=%s" % (npcID, dropIDList, dropIDBindDict), playerID) - # 掉落金币 dropMoneyDoCnt = ipyDrop.GetDropMoneyDoCnt() dropMoneyRate = ipyDrop.GetDropMoneyRate() @@ -1062,90 +1116,52 @@ moneyValue = __GetDropMoneyValue(dropPlayer, ipyDrop) #GameWorld.DebugLog(" 掉落金币value=%s" % (moneyValue)) - if not dropIDList and isGameBoss: + if dropIDList: + if ipyDrop.GetAucionItemCanSell(): + for dropID in dropIDList: + if IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropID): + auctionIDList.append(dropID) + GameWorld.DebugLog("最终掉落物品: npcID=%s,dropIDList=%s" % (npcID, dropIDList), playerID) + GameWorld.DebugLog(" auctionIDList=%s" % (auctionIDList), playerID) + elif ChConfig.IsGameBoss(npcData): GameWorld.ErrLog("Boss没有掉落物品,NPCID=%s" % (npcID), dropPlayer.GetPlayerID()) - return dropIDList, dropIDBindDict, dropMoneyCnt, moneyValue + return dropIDList, auctionIDList, dropMoneyCnt, moneyValue -def __GetFBGradeColorStarRateList(color, colorStarRateList, gradeColorStarRateDict, curGrade): - # {(颜色,星级):[D级影响概率, ..., S级影响概率], ...} - newRateList = [] - commKey = (color, 0) # 代表都影响 - for i, rateInfo in enumerate(colorStarRateList): - rate, star = rateInfo - - if i == 0: - srcRate = rate - else: - srcRate = rate - colorStarRateList[i - 1][0] - - key = (color, star) - if not star: - newRate = srcRate - elif key in gradeColorStarRateDict: - starRateList = gradeColorStarRateDict[key] - starRate = 10000 if (curGrade <= 0 or curGrade > len(starRateList)) else starRateList[curGrade - 1] - newRate = int(srcRate * starRate / 10000.0) - elif commKey in gradeColorStarRateDict: - starRateList = gradeColorStarRateDict[commKey] - starRate = 10000 if (curGrade <= 0 or curGrade > len(starRateList)) else starRateList[curGrade - 1] - newRate = int(srcRate * starRate / 10000.0) - else: - newRate = srcRate - - if not newRateList: - newRateList.append([newRate, star]) - else: - newRateList.append([newRateList[-1][0] + newRate, star]) - - #GameWorld.DebugLog(" 副本评级影响颜色品质星级: color=%s,源=%s" % (color, colorStarRateList)) - #GameWorld.DebugLog(" curGrade=%s,gradeColorStarRateDict=%s" % (curGrade, gradeColorStarRateDict)) - #GameWorld.DebugLog(" newRateList=%s" % (newRateList)) - return newRateList - -def __GetNPCDropItemBindInfo(mapID, isGameBoss, dropIDList, dropEquipIDDict): - ## 获取NPC掉落物品绑定信息字典 - mapID = FBCommon.GetRecordMapID(mapID) - - unBindEquipPlaceKeyList = IpyGameDataPY.GetFuncCfg("EquipDropBindingRule", 3) # 非绑定部位集合key [部位集合key1, 部位集合key2, ...] - defaultMaxBindColor = IpyGameDataPY.GetFuncCfg("EquipDropBindingRule", 2) # 默认绑定最高颜色 - - bossDropBindIDList = IpyGameDataPY.GetFuncCfg("BossDropBindingRule", 1) # Boss掉落绑定的物品ID: [ID1, ID2, ...] - monsterDropNoBindIDList = IpyGameDataPY.GetFuncCfg("MonsterDropBindingRule", 1) # 小怪掉落不绑定的物品ID: [ID1, ID2, ...] - - mapDropBindDict = IpyGameDataPY.GetFuncCfg("MapDropBindRule", 1) # 地图掉落是否绑定:{MapID:是否绑定, ...} - mapDropItemNoBindDict = IpyGameDataPY.GetFuncCfg("MapDropItemNoBind", 1) # 地图掉落不绑定物品ID:{MapID:[ID1, ID2, ...],...} - mapDropItemBindDict = IpyGameDataPY.GetFuncCfg("MapDropItemBind", 1) # 地图掉落绑定物品ID:{MapID:[ID1, ID2, ...],...} - - mapDropItemIsBind = mapDropBindDict.get(mapID, None) - mapDropItemNoBindList = mapDropItemNoBindDict.get(mapID, []) - mapDropItemBindList = mapDropItemBindDict.get(mapID, []) - - dropIDBindDict = {} # 掉落物品ID绑定字典 {物品ID:是否绑定, ...} - for dropItemID in dropIDList: - if dropItemID in dropIDBindDict: +def __GetOptimizationEquipPlace(dropPlayer, classLV, optColor, optIsSuit, optPlaceList): + ''' 获取掉落优选部位 + 几个默认规则 + 1. 颜色大于指定优选颜色的,无论是否套装都不计算在内 + 2. 颜色小于指定优选颜色的,无论是否套装都计算在内 + ''' + #GameWorld.DebugLog("处理优选部位掉落: classLV=%s,optColor=%s,optIsSuit=%s,optPlaceList=%s" % (classLV, optColor, optIsSuit, optPlaceList)) + minGSPlace = None + minGS = None + equipPack = dropPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip) + for optPlace in optPlaceList: + ipyData = IpyGameDataPY.GetIpyGameData('EquipPlaceIndexMap', classLV, optPlace) + if not ipyData: continue - - # 装备绑定规则判断 - if dropItemID in dropEquipIDDict: - color, placeKey = dropEquipIDDict[dropItemID] - isBind = placeKey not in unBindEquipPlaceKeyList and color <= defaultMaxBindColor + equipIndex = ipyData.GetGridIndex() + curEquip = equipPack.GetAt(equipIndex) + if not curEquip or curEquip.IsEmpty(): + #GameWorld.DebugLog(" 没穿装备,直接默认返回该部位: optPlace=%s" % optPlace) + return optPlace + curColor = curEquip.GetItemColor() + curIsSuit = 1 if curEquip.GetSuiteID() else 0 + if curColor > optColor: + # 超过优选指定颜色的不算,无论是否有套装 + #GameWorld.DebugLog(" 颜色超过优选颜色,不算该部位: optPlace=%s,curColor=%s,curIsSuit=%s" % (optPlace, curColor, curIsSuit)) + continue + if curColor == optColor and curIsSuit >= optIsSuit: + # 与优选指定颜色相同,且满足是否套装的不算 + #GameWorld.DebugLog(" 颜色套装满足优选,不算该部位: optPlace=%s,curColor=%s,curIsSuit=%s" % (optPlace, curColor, curIsSuit)) + continue + curGS = ItemCommon.GetEquipGearScore(curEquip) + if minGS == None or curGS < minGS: + minGS = curGS + minGSPlace = optPlace - # 非装备 - else: - if dropItemID in mapDropItemBindList: - isBind = True - elif dropItemID in mapDropItemNoBindList: - isBind = False - elif mapDropItemIsBind != None: - isBind = mapDropItemIsBind - elif isGameBoss: - isBind = dropItemID in bossDropBindIDList - else: - isBind = dropItemID not in monsterDropNoBindIDList - - dropIDBindDict[dropItemID] = int(isBind) - - return dropIDBindDict + return minGSPlace def __GetNPCDropDoCountChange(doCount, doCountRate, doCountAdd): ## 获取掉落执行次数变更结果,可能增加 或 减少 @@ -1327,7 +1343,7 @@ itemData = GameWorld.GetGameData().GetItemByTypeID(itemID) if not itemData: continue - itemJob = itemData.GetJobLimit() / 100 + itemJob = itemData.GetJobLimit() if itemJob and itemJob != curPlayer.GetJob(): # 非本职业可用,不掉落 GameWorld.DebugLog("全服击杀次数必掉,非本职业可用,不掉落! itemID=%s" % itemID) @@ -1341,7 +1357,7 @@ itemData = GameWorld.GetGameData().GetItemByTypeID(rItemID) if not itemData: continue - itemJob = itemData.GetJobLimit() / 100 + itemJob = itemData.GetJobLimit() if itemJob and itemJob != curPlayer.GetJob(): # 非本职业可用,不掉落 GameWorld.DebugLog("全服击杀次数必掉随机,非本职业可用,不掉落! rItemID=%s" % rItemID) @@ -1355,10 +1371,10 @@ return dropItemIDList -def __GetEquipIDList(npcID, classLV, color, placeList, star, itemJobList, tagPlace=None): +def __GetEquipIDList(findID, classLV, color, isSuit, placeList, itemJobList, findType="NPC"): #存一个满足要求的所有的物品的列表 然后从当中随机选一个 - #注: 阶、颜色、星、职业、部位,这5个条件可确认唯一一件装备 - key = "%s_%s_%s" % (classLV, color, star) + #注: 阶、颜色、套装ID、职业、部位,这5个条件可确认唯一一件装备 + key = "%s_%s" % (classLV, color) if key in PyGameData.g_filterEquipDict: filterItemIDDict = PyGameData.g_filterEquipDict[key] @@ -1379,37 +1395,39 @@ continue if itemData.GetItemColor() != color: continue - #if itemData.GetEquipPlace() not in placeList: - # continue - if itemData.GetItemQuality() != star: - continue - itemJob = itemData.GetJobLimit() / 100 + suiteID = itemData.GetSuiteID() + itemJob = itemData.GetJobLimit() itemPlace = itemData.GetEquipPlace() - filterItemIDDict[(itemJob, itemPlace)] = itemData.GetItemTypeID() + itemID = itemData.GetItemTypeID() + if itemPlace not in filterItemIDDict: + filterItemIDDict[itemPlace] = [] + placeItemList = filterItemIDDict[itemPlace] + placeItemList.append([itemJob, suiteID, itemID]) PyGameData.g_filterEquipDict[key] = filterItemIDDict - GameWorld.Log("缓存掉落装备ID: classLV_color_star=%s, %s, %s" % (key, filterItemIDDict, PyGameData.g_filterEquipDict)) + GameWorld.Log("缓存产出装备ID: classLV_color=%s, %s, %s" % (key, filterItemIDDict, PyGameData.g_filterEquipDict)) itemIDList = [] - for itemJobPlace, itemID in filterItemIDDict.items(): - itemJob, itemPlace = itemJobPlace - # 有职业限制的物品才需判断是否在可掉落的职业里 - if itemJob and itemJob not in itemJobList: + for itemPlace, placeItemList in filterItemIDDict.items(): + if placeList and itemPlace not in placeList: continue - if itemPlace not in placeList: - continue - if tagPlace != None and itemPlace != tagPlace: - continue - itemIDList.append(itemID) - + for itemInfo in placeItemList: + itemJob, suiteID, itemID = itemInfo + if itemJob and itemJobList and itemJob not in itemJobList: + continue + curIsSuit = suiteID > 0 + if curIsSuit != isSuit: + continue + itemIDList.append(itemID) + if not itemIDList: - GameWorld.ErrLog("找不到可掉落的装备ID: npcID=%s,classLV=%s,color=%s,star=%s,placeList=%s,tagPlace=%s,itemJobList=%s" - % (npcID, classLV, color, star, placeList, tagPlace, itemJobList)) + GameWorld.ErrLog("找不到可产出的装备ID: %sID=%s,classLV=%s,color=%s,isSuit=%s,placeList=%s,itemJobList=%s" + % (findType, findID, classLV, color, isSuit, placeList, itemJobList)) return itemIDList def __GetNPCPieRateEquipDrop(ipyDrop, doCnt, equipDropPlus): ## 获取NPC饼图掉率装备掉落信息 dropEquipInfoList = [] - pieRateDropList = ipyDrop.GetPieRateDrop() # [(概率,0),(概率,(阶,颜色,部位集合key)),...] + pieRateDropList = ipyDrop.GetPieRateDrop() # 饼图概率掉落信息 [(概率,0),(概率,(阶,颜色)),...] dropRateList = pieRateDropList if not equipDropPlus else GameWorld.GetPlusPieList(pieRateDropList, equipDropPlus) #GameWorld.DebugLog("掉落饼图概率: %s, equipDropPlus=%s" % (pieRateDropList, equipDropPlus)) #GameWorld.DebugLog("实际饼图概率: %s" % (dropRateList)) @@ -1423,10 +1441,8 @@ def __GetNPCIndepRateEquipDrop(ipyDrop, doCnt, equipDropPlus, curGrade=0): ## 获取NPC独立掉率装备掉落信息 npcID = ipyDrop.GetNPCID() - indepRateDict = ipyDrop.GetIndepRateDrop() # {(阶,颜色,部位集合key):概率,...} - #colorMaxDropCntDict = ipyDrop.GetIndepRateMaxDropCount() - #GameWorld.DebugLog("独立概率装备掉落处理: indepRateDict=%s,colorMaxDropCntDict=%s,equipDropPlus=%s" - # % (indepRateDict, colorMaxDropCntDict, equipDropPlus)) + indepRateDict = ipyDrop.GetIndepRateDrop() # 独立概率掉落信息 {(阶,颜色):概率,...} + #GameWorld.DebugLog("独立概率装备掉落处理: indepRateDict=%s,equipDropPlus=%s" % (indepRateDict, equipDropPlus)) gradeColorRateDict = {} fbGradeColorRateDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 1) #{npcID:{颜色:[D级影响概率, ..., S级影响概率], ...}, ...} if npcID in fbGradeColorRateDict: @@ -1454,19 +1470,7 @@ curDropCount += 1 if not curDropCount: continue - #掉落颜色对应件数上限提到外部,修改为作为掉落装备的公共限制条件 - #======================================================================================= - # if color in colorMaxDropCntDict: - # maxCount = colorMaxDropCntDict[color] - # dropCount = colorDropCntDict.get(color, 0) - # if dropCount >= maxCount: - # #GameWorld.DebugLog(" 已超过该颜色装备最大掉落数,不掉!color=%s,maxCount=%s" % (color, maxCount)) - # continue - # maxCanDropCount = maxCount - dropCount - # curDropCount = min(curDropCount, maxCanDropCount) - # colorDropCntDict[color] = dropCount + curDropCount - # #GameWorld.DebugLog(" maxCanDropCount=%s,curDropCount=%s" % (maxCanDropCount, curDropCount)) - #======================================================================================= + for _ in xrange(curDropCount): dropEquipInfoList.append(dropInfo) #GameWorld.DebugLog("独立概率装备掉落结果: doCnt=%s, %s" % (doCnt, dropEquipInfoList)) @@ -1500,15 +1504,17 @@ def GetKillCountDropItemList(curPlayer, npcID, needKillCount, killDropItemList): ## 获取击杀次数额外掉落 - dropRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCountDrop % npcID) - killCount = dropRecord / 10 - if dropRecord % 10: - #GameWorld.DebugLog("杀掉次数已经掉落过! npcID=%s,killCount=%s,dropRecord=%s" % (npcID, killCount, dropRecord), curPlayer.GetPlayerID()) + killCountValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCKillCount % npcID) + killCountPri = killCountValue / 10000 + if killCountPri >= needKillCount: + #GameWorld.DebugLog("杀掉次数已经掉落过! npcID=%s,killCountValue=%s,dropRecord=%s" % (npcID, killCountValue, dropRecord), curPlayer.GetPlayerID()) return [] - killCount += 1 + killCountPri += 1 + updRecordValue = killCountPri * 10000 + killCountValue % 10000 + jobDropInfo = [] - if killCount >= needKillCount: + if killCountPri >= needKillCount: isJobLimit = 1 #[itemID,...] for dropItemID in killDropItemList: @@ -1516,18 +1522,17 @@ if not itemData: GameWorld.ErrLog("掉落物品ID不存在, dropItemID=%s" % dropItemID) continue - itemJob = itemData.GetJobLimit() / 100 + itemJob = itemData.GetJobLimit() if isJobLimit and itemJob and itemJob != curPlayer.GetJob(): # 非本职业可用,不掉落 #GameWorld.DebugLog("非本职业可用,不掉落! dropItemID=%s" % dropItemID) continue jobDropInfo.append(dropItemID) - recordValue = killCount * 10 + 1 - #GameWorld.DebugLog("击杀次数必掉落! npcID=%s,needKillCount=%s,jobDropInfo=%s,killDropItemList=%s,recordValue=%s" - # % (npcID, needKillCount, jobDropInfo, killDropItemList, recordValue), curPlayer.GetPlayerID()) - else: - recordValue = killCount * 10 - PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCKillCountDrop % npcID, recordValue) + GameWorld.DebugLog("击杀次数必掉落! npcID=%s,needKillCount=%s,jobDropInfo=%s,killDropItemList=%s,updRecordValue=%s" + % (npcID, needKillCount, jobDropInfo, killDropItemList, updRecordValue), curPlayer.GetPlayerID()) + + PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCKillCount % npcID, updRecordValue) + GameWorld.DebugLog("更新击杀次数比掉落值: killCountValue=%s,killCountPri=%s,updRecordValue=%s" % (killCountValue, killCountPri, updRecordValue), curPlayer.GetPlayerID()) return jobDropInfo ###################################################################### #--------------------------------------------------------------------- @@ -2056,6 +2061,114 @@ 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: + summonNPC.SetHP(hp) + summonNPC.SetHPEx(hpEx) + 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 @@ -2103,6 +2216,16 @@ lineRobotJobDict.pop(curNPC.GetID(), 0) PyGameData.g_fbRobotJobDict[lineID] = lineRobotJobDict + priWoodPilePlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_PriWoodPilePlayerID) + if priWoodPilePlayerID > 0 and priWoodPilePlayerID in PyGameData.g_playerPriWoodPileNPCDict: + priWoodPileNPCList = PyGameData.g_playerPriWoodPileNPCDict[priWoodPilePlayerID] + for priWoodNPC in priWoodPileNPCList: + if priWoodNPC and priWoodNPC.GetID() == curNPC.GetID(): + priWoodPileNPCList.remove(priWoodNPC) + if not priWoodPileNPCList: + PyGameData.g_playerPriWoodPileNPCDict.pop(priWoodPilePlayerID) + break + # C++设置npc死亡 curNPC.SetDead(curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason), curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerType), @@ -2110,31 +2233,34 @@ return def GameServer_KillGameWorldBoss(bossID, killPlayerName, hurtValue, isNotify=True, killerIDList=[]): - dataMapID = GameWorld.GetGameWorld().GetMapID() + mapID = GameWorld.GetGameWorld().GetMapID() realMapID = GameWorld.GetGameWorld().GetRealMapID() copyMapID = GameWorld.GetGameWorld().GetCopyMapID() - killMsg = str([bossID, killPlayerName, hurtValue, isNotify, realMapID, dataMapID, copyMapID, killerIDList]) + killMsg = str([bossID, killPlayerName, hurtValue, isNotify, mapID, realMapID, copyMapID, killerIDList]) GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'KillGameWorldBoss', killMsg, len(killMsg)) - GameWorld.DebugLog("Boss被击杀: bossID=%s,dataMapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s" % (bossID, dataMapID, realMapID, copyMapID, killerIDList)) + GameWorld.DebugLog("Boss被击杀: bossID=%s,mapID=%s,realMapID=%s,copyMapID=%s,killerIDList=%s" % (bossID, mapID, realMapID, copyMapID, killerIDList)) return def GameServe_GameWorldBossState(bossID, isAlive): - dataMapID = GameWorld.GetGameWorld().GetMapID() + mapID = GameWorld.GetGameWorld().GetMapID() realMapID = GameWorld.GetGameWorld().GetRealMapID() copyMapID = GameWorld.GetGameWorld().GetCopyMapID() - stateMsg = str([bossID, isAlive, dataMapID, realMapID, copyMapID]) + stateMsg = str([bossID, isAlive, mapID, realMapID, copyMapID]) GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState', '%s' % stateMsg, len(stateMsg)) - GameWorld.DebugLog("Boss状态变更: bossID=%s,isAlive=%s,dataMapID=%s,realMapID=%s,copyMapID=%s" - % (bossID, isAlive, dataMapID, realMapID, copyMapID)) + GameWorld.DebugLog("Boss状态变更: bossID=%s,isAlive=%s,mapID=%s,realMapID=%s,copyMapID=%s" + % (bossID, isAlive, mapID, realMapID, copyMapID)) if not isAlive: - if dataMapID in ChConfig.Def_CrossZoneMapTableName: - tableName = ChConfig.Def_CrossZoneMapTableName[dataMapID] + if mapID in ChConfig.Def_CrossZoneMapTableName: + tableName = ChConfig.Def_CrossZoneMapTableName[mapID] realMapID = GameWorld.GetGameWorld().GetRealMapID() copyMapID = GameWorld.GetGameWorld().GetCopyMapID() - zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, dataMapID, copyMapID) + zoneIpyData = IpyGameDataPY.GetIpyGameData(tableName, realMapID, mapID, copyMapID) if not zoneIpyData: return zoneID = zoneIpyData.GetZoneID() + GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0) + elif mapID in ChConfig.Def_CrossDynamicLineMap: + zoneID = FBCommon.GetCrossDynamicLineMapZoneID() GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID), 0) else: GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID, 0) @@ -2337,8 +2463,9 @@ moveDestY = resultPos.GetPosY() if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove and \ - (GameWorld.GetGameWorld().GetTick() - curNPC.GetActionTick()) < 1200: - # Move接口调用太快会导致不移动 + (GameWorld.GetGameWorld().GetTick() - curNPC.GetActionTick()) < 800: + # .Move( 接口调用太快会导致移动时间不够长(不足一格)导致无法移动 或者移动过慢问题 + # SetDestPos 调用会导致反向移动偏快 curNPC.SetDestPos(moveDestX, moveDestY) return #======================================================================= @@ -3395,7 +3522,8 @@ #得到范围内随机一个点, 普通小怪走法 PosMap = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex()) - + if not PosMap: + return moveArea = min(curNPC.GetMoveArea(), 2) posX = curNPC.GetPosX() @@ -3667,14 +3795,13 @@ def DoHPPerLogic(self, dropType, ownerID): curNPC = self.__Instance curNPCID = curNPC.GetNPCID() - hpPerLogicNPCIDList = ReadChConfig.GetEvalChConfig('HPPerLogicNPCIDList') - if curNPCID not in hpPerLogicNPCIDList: + + hpPerLogicNPCIDDict = IpyGameDataPY.GetFuncEvalCfg('BossHPInformation', 1, {}) + hpPerLogicList = GameWorld.GetDictValueByKey(hpPerLogicNPCIDDict, curNPCID) + if not hpPerLogicList: return - - hpPerLogicDict = ReadChConfig.GetEvalChConfig('HPPerLogic_%s' % curNPCID) - - hpPerList = sorted(hpPerLogicDict.keys(), reverse=True) - + hpPerList, sysMark = hpPerLogicList + hpPerList = sorted(hpPerList, reverse=True) nowHPPer = GameObj.GetHP(curNPC) * 100 / GameObj.GetMaxHP(curNPC) # 当前百分比 hpPerLogicMark = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_HPPerLogicMark) logicHPPerList = hpPerList[hpPerLogicMark:] @@ -3687,16 +3814,12 @@ #GameWorld.DebugLog("DoHPPerLogic npcID=%s,hpPerLogicDict=%s,nowHPPer=%s,hpPerLogicMark=%s,logicHPPerList=%s" # % (curNPCID, str(hpPerLogicDict), nowHPPer, hpPerLogicMark, str(logicHPPerList))) - isNotify, dropItemTemplate, addPrestigeFormat = hpPerLogicDict[hpPer] - if isNotify: - PlayerControl.WorldNotify(0, "FB_liubo_0", [GameWorld.GetMap().GetMapID(), curNPCID, hpPer]) + + PlayerControl.WorldNotify(0, sysMark, [curNPCID, hpPer]) # if dropItemTemplate > 0: # self.__DropItemByTemplate(dropItemTemplate, dropType, ownerID) # PlayerControl.WorldNotify(0, "GeRen_admin_481766", [GameWorld.GetMap().GetMapID(), curNPCID, curNPCID]) - - if addPrestigeFormat != '': - self.__GiveNearbyPlayerPrestige(addPrestigeFormat, ChConfig.Def_Matrix_Six) hpPerLogicMark += 1 #GameWorld.DebugLog("DoHPPerLogic update hpPerLogicMark=%s" % (hpPerLogicMark)) @@ -3821,7 +3944,6 @@ ############################################ #初始化状态 curNPC.SetSpeed(curNPC.GetOrgSpeed()) - curNPC.SetSuperHit(ChConfig.Def_SuperHitPercent) curNPC.SetAtkInterval(curNPC.GetBaseAtkInterval()) # #先清空异常 @@ -4007,11 +4129,11 @@ #杀死NPC, 触发任务 self.__EventKillNpc() - #mapID = GameWorld.GetMap().GetMapID() + mapID = GameWorld.GetMap().GetMapID() killerName = "" if not self.__Killer else self.__Killer.GetPlayerName() # 记录boss击杀信息的NPC bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID) - if bossIpyData: + if bossIpyData and mapID not in [ChConfig.Def_FBMapID_ZhuXianBoss, ChConfig.Def_FBMapID_SealDemon]: if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family: killerName = FamilyRobBoss.FamilyOwnerBossOnKilled(curNPC, self.__OwnerHurtID) #KillerJob = 0 if not self.__Killer else self.__Killer.GetJob() @@ -4104,7 +4226,7 @@ def __NPCSpecialDropItem(self, dropPlayer, ownerPlayerList, ipyDrop): '''特殊掉落 (私有特殊掉落 + 击杀次数特殊掉落), 支持摸怪 @return: None - @return: [[ownerPlayer, itemID, isBind, isDropInItemPack], ...] + @return: [[ownerPlayer, itemID, isAuctionItem, isDropInItemPack], ...] ''' curNPC = self.__Instance npcID = curNPC.GetNPCID() @@ -4116,7 +4238,21 @@ GameWorld.DebugLog("超过最大可掉落等级,不掉落物品,特殊掉落!npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV)) return specDropItemList + auctionItemCanSell = ipyDrop.GetAucionItemCanSell() + # 击杀次数掉落算摸怪 + killCountDropInfo = ipyDrop.GetKillCountDropPri() + if killCountDropInfo: + for feelPlayer in self.__FeelPlayerList: + needKillCount, killDropItemList, isDropInItemPack = killCountDropInfo + killCountDropItemList = GetKillCountDropItemList(feelPlayer, npcID, needKillCount, killDropItemList) + for dropItemID in killCountDropItemList: + isAuctionItem = 1 if auctionItemCanSell and IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropItemID) else 0 + specDropItemList.append([feelPlayer, dropItemID, isAuctionItem, isDropInItemPack]) + GameWorld.DebugLog("击杀次数必掉(可摸怪): npcID=%s,dropItemID=%s,needKillCount=%s,isDropInItemPack=%s,isAuctionItem=%s" + % (npcID, dropItemID, needKillCount, isDropInItemPack, isAuctionItem), feelPlayer.GetPlayerID()) + # 私有掉落 + isDropInItemPack = False fbGradePriItemIDDropDict = IpyGameDataPY.GetFuncEvalCfg("FBGradeEquipDropRate", 3) if npcID in fbGradePriItemIDDropDict: gradePriItemIDDropDict = fbGradePriItemIDDropDict[npcID] @@ -4127,25 +4263,12 @@ priDropIDList += [priItemID] * priItemCount else: priDropIDList = ipyDrop.GetPriItemIDDrop() - - # 击杀次数掉落算摸怪 - killCountDropInfo = ipyDrop.GetKillCountDrop() - if killCountDropInfo: - for feelPlayer in self.__FeelPlayerList: - needKillCount, isDropInItemPack, isBind, killDropItemList = killCountDropInfo - killCountDropItemList = GetKillCountDropItemList(feelPlayer, npcID, needKillCount, killDropItemList) - for dropItemID in killCountDropItemList: - specDropItemList.append([feelPlayer, dropItemID, isBind, isDropInItemPack]) - GameWorld.DebugLog("击杀次数必掉(可摸怪): npcID=%s,dropItemID=%s,needKillCount=%s,isDropInItemPack=%s,isBind=%s" - % (npcID, dropItemID, needKillCount, isDropInItemPack, isBind), feelPlayer.GetPlayerID()) - - # 私有掉落算归属 - for ownerPlayer in ownerPlayerList: - - for dropItemID in priDropIDList: - specDropItemList.append([ownerPlayer, dropItemID, 1, False]) # 默认绑定 + for dropItemID in priDropIDList: + isAuctionItem = 1 if auctionItemCanSell and IpyGameDataPY.GetIpyGameDataNotLog("AuctionItem", dropItemID) else 0 + for ownerPlayer in ownerPlayerList: + specDropItemList.append([ownerPlayer, dropItemID, isAuctionItem, isDropInItemPack]) # 默认绑定 #GameWorld.DebugLog("私有物品掉落: dropItemID=%s" % dropItemID, ownerPlayer.GetPlayerID()) - + return specDropItemList def __NPCDropItemByPlayers(self, dropPlayerList, mapID, ipyDrop): @@ -4156,13 +4279,13 @@ return #GameWorld.DebugLog("NPC多玩家混合掉落: dropPlayerCount=%s" % len(dropPlayerList)) - dropItemBindDict = {} + auctionItemIDList = [] dropItemList = [] for dropPlayer in dropPlayerList: dropInfo = GetNPCDropInfo(dropPlayer, mapID, npcID, ipyDrop=ipyDrop) if not dropInfo: continue - dropIDList, dropIDBindDict, dropMoneyCnt, moneyValue = dropInfo + dropIDList, auctionIDList, dropMoneyCnt, moneyValue = dropInfo moneyID = self.__GetDropMoneyModelID(moneyValue) if dropMoneyCnt: dropIDList += [moneyID] * dropMoneyCnt @@ -4171,7 +4294,7 @@ #GameWorld.DebugLog(" dropPlayerID=%s,dropIDList=%s" % (dropPlayerID, dropIDList)) for dropID in dropIDList: dropItemList.append([dropID, dropPlayerID]) - dropItemBindDict.update(dropIDBindDict) + auctionItemIDList += auctionIDList #打乱物品顺序 random.shuffle(dropItemList) @@ -4192,8 +4315,8 @@ itemID, ownerID = dropItemList[index] index += 1 itemCnt = moneyValue if itemID == moneyID else 1 - isBind = dropItemBindDict.get(itemID, 1) - curItem = self.__CreateDropItem(curNPC, itemID, itemCnt, isBind) + iaAuctionItem = itemID in auctionItemIDList + curItem = self.__CreateDropItem(curNPC, itemID, itemCnt, iaAuctionItem, dropPlayer) if not curItem: continue self.__MapCreateItem(curItem, resultX, resultY, ChConfig.Def_NPCHurtTypePlayer, ownerID) @@ -4210,14 +4333,18 @@ if not dropPlayer: return curNPC = self.__Instance + if curNPC.GetType() in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]: + GameWorld.DebugLog("木桩怪,不掉落物品!") + return npcID = curNPC.GetNPCID() mapID = GameWorld.GetMap().GetMapID() mapID = FBCommon.GetRecordMapID(mapID) isGameBoss = ChConfig.IsGameBoss(curNPC) + if mapID in [ChConfig.Def_FBMapID_MunekadoTrial, ChConfig.Def_FBMapID_DemonKing, ChConfig.Def_FBMapID_SealDemon, ChConfig.Def_FBMapID_ZhuXianBoss]: + GameWorld.DebugLog("该地图不走直接掉落物品逻辑!mapID=%s" % mapID) + return if isGameBoss: GameWorld.Log("NPC开始掉落: npcID=%s,dropPlayerID=%s" % (npcID, dropPlayer.GetPlayerID()), dropPlayer.GetPlayerID()) - if mapID == ChConfig.Def_FBMapID_MunekadoTrial: - return ipyDrop = GetNPCDropIpyData(npcID) if not ipyDrop: if isGameBoss: @@ -4229,17 +4356,17 @@ # dropPlayerList = GameLogic_MunekadoTrial.GetCanDropPlayerList() # return self.__NPCDropItemByPlayers(dropPlayerList, mapID, ipyDrop) - dropIDList, dropIDBindDict, dropMoneyCnt, moneyValue = [], {}, 0, 0 + dropIDList, auctionIDList, dropMoneyCnt, moneyValue = [], [], 0, 0 dropInfo = GetNPCDropInfo(dropPlayer, mapID, npcID, ownerPlayerList, ipyDrop, False) if dropInfo: - dropIDList, dropIDBindDict, dropMoneyCnt, moneyValue = dropInfo + dropIDList, auctionIDList, dropMoneyCnt, moneyValue = dropInfo moneyID = self.__GetDropMoneyModelID(moneyValue) if moneyID and dropMoneyCnt: dropIDList += [moneyID] * dropMoneyCnt specItemSign = "SpecItem" - playerSpecDropList = self.__NPCSpecialDropItem(dropPlayer, ownerPlayerList, ipyDrop) # 特殊掉落 [[ownerPlayer, itemID, isBind, isDropInItemPack], ...] 私有特殊掉落 + 击杀次数特殊掉落 + playerSpecDropList = self.__NPCSpecialDropItem(dropPlayer, ownerPlayerList, ipyDrop) # 特殊掉落 [[ownerPlayer, itemID, isAuctionItem, isDropInItemPack], ...] 私有特殊掉落 + 击杀次数特殊掉落 dropIDList += [specItemSign] * len(playerSpecDropList) if len(dropIDList) > 5: @@ -4272,23 +4399,23 @@ if not playerSpecDropList: continue itemCnt = 1 - ownerPlayer, itemID, isBind, isDropInItemPack = playerSpecDropList[0] + ownerPlayer, itemID, isAuctionItem, isDropInItemPack = playerSpecDropList[0] ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, ownerPlayer.GetPlayerID() playerSpecDropList = playerSpecDropList[1:] else: ownerPlayer = dropPlayer ownerType, ownerID = hurtType, hurtID itemCnt = moneyValue if itemID == moneyID else 1 - isBind = dropIDBindDict.get(itemID, 1) - - curItem = self.__CreateDropItem(curNPC, itemID, itemCnt, isBind) + isAuctionItem = itemID in auctionIDList + + curItem = self.__CreateDropItem(curNPC, itemID, itemCnt, isAuctionItem, dropPlayer) if not curItem: continue if mapID == ChConfig.Def_FBMapID_GatherSoul:#聚魂副本特殊处理 - GameLogic_GatherSoul.KillGatherSoulNPCDropAward(itemID, itemCnt, isBind) + GameLogic_GatherSoul.KillGatherSoulNPCDropAward(itemID, itemCnt, isAuctionItem) dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem) - self.SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr) + SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr) curItem.Clear() continue @@ -4296,24 +4423,12 @@ curItem.SetUserAttr(ShareDefine.Def_IudetSource, ShareDefine.Item_Source_VirtualItemDrop) dropItemDataStr = ChItem.GetMapDropItemDataStr(curItem) #可以放入背包 - if ItemControler.DoLogic_PutItemInPack(ownerPlayer, curItem, True, True, - event=["NPCDrop", False, {"npcID":npcID}]): + if ItemControler.DoLogic_PutItemInPack(ownerPlayer, curItem, event=["NPCDrop", False, {"npcID":npcID}]): #通知客户端 - self.SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr) + SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr) else: self.__MapCreateItem(curItem, resultX, resultY, ownerType, ownerID) - return - - def SendVirtualItemDrop(self, player, itemID, posX, posY, userDataStr): - #通知客户端 - vItemDrop = ChPyNetSendPack.tagMCVirtualItemDrop() - vItemDrop.ItemTypeID = itemID - vItemDrop.PosX = posX - vItemDrop.PosY = posY - vItemDrop.UserData = userDataStr - vItemDrop.UserDataLen = len(vItemDrop.UserData) - NetPackCommon.SendFakePack(player, vItemDrop) return #--------------------------------------------------------------------- ## NPC被杀死逻辑处理 @@ -4543,8 +4658,7 @@ lastTimeHurtObj = self.__FindLastTimeHurtObj() if lastTimeHurtObj[0] == None and lastTimeHurtObj[1] == None: return - - PlayerAction.GetAwardOnKillNPC(lastTimeHurtObj, curNPC) + return ## 最后一击处理 @@ -4905,10 +5019,13 @@ #if self.__GetIsLog(): # GameWorld.Log("玩家增加个人经验,npcID=%s,addExp=%s" % (curNPC.GetNPCID(), add_Exp), curPlayer.GetPlayerID()) - + addSkillID = 0 + if curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID) == curPlayer.GetID(): + addSkillID = curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason) + #设定人物获得经验 playerControl = PlayerControl.PlayerControl(curPlayer) - playerControl.AddExp(add_Exp, ShareDefine.Def_ViewExpType_KillNPC) + playerControl.AddExp(add_Exp, ShareDefine.Def_ViewExpType_KillNPC, addSkillID=addSkillID) self.__KillNPCFuncEx(curPlayer, curNPC, curPlayer.GetPlayerID(), False) @@ -5119,8 +5236,11 @@ return #GameWorld.Log("普通队伍杀死怪物,队伍分享人数 = %s,个人经验增加 玩家 = %s, 增加 = %s"%(playerCount, curPlayer.GetPlayerID(), add_Exp)) #设定人物获得经验 + addSkillID = 0 + if curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerID) == curPlayer.GetID(): + addSkillID = curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason) playerControl = PlayerControl.PlayerControl(curPlayer) - playerControl.AddExp(add_Exp, ShareDefine.Def_ViewExpType_KillNPC) + playerControl.AddExp(add_Exp, ShareDefine.Def_ViewExpType_KillNPC, addSkillID=addSkillID) return #--------------------------------------------------------------------- @@ -5205,21 +5325,373 @@ #self.__SetItemProtect(curMapItem, dropType, ownerID) return - def __CreateDropItem(self, curNPC, itemID, count, isBind): + def __CreateDropItem(self, curNPC, itemID, count, isAuctionItem, dropPlayer): ## 创建掉落的物品 - curItem = ItemControler.GetOutPutItemObj(itemID) + curItem = ItemControler.GetOutPutItemObj(itemID, count, isAuctionItem, curPlayer=dropPlayer) if not curItem: return - - curMapID = GameWorld.GetMap().GetMapID() - curMapID = FBCommon.GetRecordMapID(curMapID) - - # 掉落数量 - curItem.SetCount(count) - curItem.SetIsBind(isBind) return curItem + ##----------------------------------------- 归属 ----------------------------------------------- + + def RefreshDropOwner(self, tick, refreshInterval=3000, isDead=False): + ## 刷新boss掉落归属 + # @return: 可攻击的掉落归属目标玩家 + + curNPC = self.__Instance + tagObj = None # 即将攻击的目标, 归属最大伤血取最大伤血玩家或队伍队员,其他取最大仇恨 + ownerType, ownerID = 0, 0 + dropOwnerType = GetDropOwnerType(curNPC) + if isDead: + GameWorld.Log("Boss死亡: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s" + % (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType)) + if dropOwnerType == ChConfig.DropOwnerType_MaxHurt: + maxHurtObj = self.RefreshHurtList(tick, refreshInterval) + if maxHurtObj: + ownerType, ownerID = maxHurtObj.GetValueType(), maxHurtObj.GetValueID() + if ownerType == ChConfig.Def_NPCHurtTypeTeam: + tagObj = self.__GetMaxHurtTeamPlayer(ownerID, isDead) + elif ownerType == ChConfig.Def_NPCHurtTypePlayer: + tagObj = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer) + + elif dropOwnerType == ChConfig.DropOwnerType_Family: + ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(self, curNPC, tick, refreshInterval) + if ownerInfo: + tagObj, ownerFamilyID = ownerInfo + ownerType, ownerID = ChConfig.Def_NPCHurtTypeFamily, ownerFamilyID + + elif dropOwnerType == ChConfig.DropOwnerType_Contend: + tagObj = self.__RefreshContendOwner() + if tagObj: + ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, tagObj.GetPlayerID() + + if isDead: + GameWorld.Log("ownerType=%s, ownerID=%s, tagObjID=%s" % (ownerType, ownerID, 0 if not tagObj else tagObj.GetPlayerID())) + + # 没有攻击目标,则刷新仇恨,支持主动怪 + if not tagObj: + angryObjType, maxAngryObj = None, None + self.RefreshAngryList(tick, refreshInterval, isUpdAngry=True) + maxAngry = self.GetMaxAngryTag() + if maxAngry: + angryID = maxAngry.GetObjID() + angryObjType = maxAngry.GetObjType() + #GameWorld.DebugLog("最大仇恨目标: ID=%s, Type=%s" % (angryID, angryObjType)) + maxAngryObj = GameWorld.GetObj(angryID, angryObjType) + + tagObj = maxAngryObj + if angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj and not ownerType: + if dropOwnerType == ChConfig.DropOwnerType_Contend: + ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID() + elif maxAngryObj.GetTeamID(): + ownerType, ownerID = ChConfig.Def_NPCHurtTypeTeam, maxAngryObj.GetTeamID() + else: + ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID() + + if isDead: + GameWorld.Log("angryObj, ownerType=%s, ownerID=%s" % (ownerType, ownerID)) + + self.UpdateDropOwner(tick, ownerType, ownerID, isDead) + return tagObj + + def __RefreshContendOwner(self): + ## 刷新boss争夺归属者,归属移除时不做刷新新归属,默认由后面的仇恨刷新 + + curNPC = self.__Instance + ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID) + ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType) + if not ownerID or ownerType != ChConfig.Def_NPCHurtTypePlayer: + return + + owner = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer) + if not owner: + return + + if not owner.GetVisible(): + GameWorld.DebugLog("竞争归属玩家不可见,移除归属!playerID=%s" % ownerID) + return + + if owner.GetHP() <= 0 or owner.GetPlayerAction() == IPY_GameWorld.paDie: + GameWorld.DebugLog("竞争归属玩家死亡,移除归属!playerID=%s" % ownerID) + return + + refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex()) + if not self.GetIsInRefreshPoint(owner.GetPosX(), owner.GetPosY(), refreshPoint): + GameWorld.DebugLog("竞争归属玩家不在boss范围里,移除归属!playerID=%s" % ownerID) + return + + #GameWorld.DebugLog("竞争归属玩家归属正常!playerID=%s" % ownerID) + return owner + + def __GetMaxHurtTeamPlayer(self, teamID, isDead): + ## 获取最大伤血队伍中攻击的目标队员 + + curNPC = self.__Instance + curTeam = GameWorld.GetTeamManager().FindTeam(teamID) + if curTeam: + refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex()) + if isDead: + GameWorld.Log("队伍成员数: teamID=%s,memberCount=%s" % (teamID, curTeam.GetMemberCount())) + for i in xrange(curTeam.GetMemberCount()): + curTeamPlayer = curTeam.GetMember(i) + if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0: + if isDead: + GameWorld.Log(" i=%s, 队员为空!" % i) + continue + if curTeamPlayer.GetHP() <= 0: + if isDead: + GameWorld.Log(" i=%s, 队员血量为0!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID())) + continue + if not curTeamPlayer.GetVisible(): + if isDead: + GameWorld.Log(" i=%s, 队员不可见!, memPlayerID=%s" % (i, curTeamPlayer.GetPlayerID())) + continue + if isDead: + GameWorld.Log(" i=%s, 队员坐标(%s, %s)! memPlayerID=%s" % (i, curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), curTeamPlayer.GetPlayerID())) + if self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint): + return curTeamPlayer + else: + GameWorld.ErrLog("找不到该队伍: teamID=%s" % teamID) + return + + def UpdateDropOwner(self, tick, ownerType=0, ownerID=0, isDead=False): + + curNPC = self.__Instance + npcID = curNPC.GetNPCID() + dropOwnerType = GetDropOwnerType(curNPC) + if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry, ChConfig.DropOwnerType_Family, ChConfig.DropOwnerType_Contend]: + #GameWorld.DebugLog("不需要展示掉落归属的NPC! npcID=%s,dropOwnerType=%s" % (npcID, dropOwnerType)) + return + + lastDropOwnerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID) + lastDropOwnerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType) + + key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID) + if lastDropOwnerID and (lastDropOwnerType != ownerType or lastDropOwnerID != ownerID): + GameWorld.Log("归属变更, 清除旧归属! key=%s,ownerType=%s,ownerID=%s,lastDropOwnerType=%s,lastDropOwnerID=%s" + % (key, ownerType, ownerID, lastDropOwnerType, lastDropOwnerID)) + self.__DelDropOwnerBuff(dropOwnerType, lastDropOwnerType, lastDropOwnerID, tick) + + killerDict, curTeam, hurtType, hurtID = {}, None, 0, 0 + + # 更新归属 + curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerID, ownerID) + curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerType, ownerType) + + if isDead: + GameWorld.Log("Boss归属: key=%s,ownerType=%s,ownerID=%s" % (key, ownerType, ownerID)) + + # 刷新归属 + if ownerType == ChConfig.Def_NPCHurtTypePlayer: + curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer) + if curPlayer: + playerID = curPlayer.GetPlayerID() + hurtType, hurtID = ChConfig.Def_NPCHurtTypePlayer, playerID + killerDict[playerID] = curPlayer + self.__AddDropOwnerPlayerBuff(curPlayer, tick) + if dropOwnerType == ChConfig.DropOwnerType_Contend: + curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, curNPC.GetID()) + + elif ownerType == ChConfig.Def_NPCHurtTypeTeam: + curTeam = GameWorld.GetTeamManager().FindTeam(ownerID) + if not curTeam: + return + + # 因为有击杀次数限制,所以不是所有的队员都可以获得归属,所以这里设置为特殊指定玩家掉落 + hurtType, hurtID = ChConfig.Def_NPCHurtTypeSpecial, 0 + if isDead: + GameWorld.Log("队伍成员数: %s" % (curTeam.GetMemberCount())) + refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex()) + for i in xrange(curTeam.GetMemberCount()): + curTeamPlayer = curTeam.GetMember(i) + if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0: + if isDead: + GameWorld.Log(" i=%s, 成员不存在!" % (i)) + continue + + if curTeamPlayer.GetCopyMapID() == GameWorld.GetGameWorld().GetCopyMapID() \ + and self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \ + and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False) and curTeamPlayer.GetVisible(): + self.__AddDropOwnerPlayerBuff(curTeamPlayer, tick) + killerDict[curTeamPlayer.GetPlayerID()] = curTeamPlayer + if isDead: + GameWorld.Log(" i=%s, 成员有归属权! memPlayerID=%s,背包剩余空格=%s" + % (i, curTeamPlayer.GetPlayerID(), ItemCommon.GetItemPackSpace(curTeamPlayer, IPY_GameWorld.rptItem))) + + # 不同线、或者距离超出boss范围的队员不加归属buff + else: + isOk = BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC) + if isOk: + GameWorld.DebugLog("删除归属队员buff: teamID=%s,playerID=%s" % (ownerID, curTeamPlayer.GetPlayerID())) + if isDead: + GameWorld.Log(" i=%s, 成员无归属权! memPlayerID=%s,copyMapID=%s,pos(%s,%s),CheckKillNPCByCnt=%s" + % (i, curTeamPlayer.GetPlayerID(), curTeamPlayer.GetCopyMapID(), + curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), + AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False))) + + elif ownerType == ChConfig.Def_NPCHurtTypeFamily: + + hurtType, hurtID = ChConfig.Def_NPCHurtTypeFamily, ownerID + refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex()) + copyPlayerMgr = GameWorld.GetMapCopyPlayerManager() + for index in xrange(copyPlayerMgr.GetPlayerCount()): + player = copyPlayerMgr.GetPlayerByIndex(index) + if not player: + continue + + # 归属仙盟 且 在boss区域内 + if player.GetFamilyID() == ownerID and self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint) and player.GetVisible(): + self.__AddDropOwnerPlayerBuff(player, tick) + + else: + isOk = BuffSkill.DelBuffBySkillID(player, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC) + if isOk: + GameWorld.DebugLog("删除非归属仙盟成员buff: teamID=%s,playerID=%s" % (ownerID, player.GetPlayerID())) + + if isDead: + #key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID) + teamID = curTeam.GetTeamID() if curTeam else 0 + if killerDict: + PyGameData.g_npcKillerInfo[key] = killerDict, curTeam, hurtType, hurtID + elif ownerType == ChConfig.Def_NPCHurtTypeFamily: + PyGameData.g_npcKillerInfo[key] = {}, None, hurtType, hurtID + + GameWorld.Log("Boss被击杀: npcID=%s,key=%s,playerIDList=%s,teamID=%s,hurtType=%s,hurtID=%s" + % (npcID, key, killerDict.keys(), teamID, hurtType, hurtID)) + return + + def __AddDropOwnerPlayerBuff(self, curPlayer, tick): + curNPC = self.__Instance + findBuff = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff)[0] + if not findBuff: + SkillCommon.AddBuffBySkillType_NoRefurbish(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC) + GameWorld.DebugLog("添加归属buff: playerID=%s" % curPlayer.GetPlayerID()) + return + + def __DelDropOwnerBuff(self, dropOwnerType, ownerType, ownerID, tick): + + curNPC = self.__Instance + if ownerType == ChConfig.Def_NPCHurtTypePlayer: + curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer) + if not curPlayer: + return + GameWorld.DebugLog("删除归属玩家buff: playerID=%s" % (ownerID)) + BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC) + if dropOwnerType == ChConfig.DropOwnerType_Contend: + curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, 0) + + elif ownerType == ChConfig.Def_NPCHurtTypeTeam: + curTeam = GameWorld.GetTeamManager().FindTeam(ownerID) + if not curTeam: + return + GameWorld.DebugLog("删除归属队伍buff: teamID=%s" % (ownerID)) + for i in xrange(curTeam.GetMemberCount()): + curTeamPlayer = curTeam.GetMember(i) + if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0: + continue + BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC) + return + + def DelayDropOwnerBuffDisappearTime(self): + ''' 延迟掉落归属buff消失时间 ''' + + curNPC = self.__Instance + ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID) + ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType) + + if ownerType == ChConfig.Def_NPCHurtTypePlayer: + curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer) + if not curPlayer: + return + self.__SetDropOwnerBuffDisappearTime(curPlayer) + + elif ownerType == ChConfig.Def_NPCHurtTypeTeam: + curTeam = GameWorld.GetTeamManager().FindTeam(ownerID) + if not curTeam: + return + for i in xrange(curTeam.GetMemberCount()): + curTeamPlayer = curTeam.GetMember(i) + if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0: + continue + self.__SetDropOwnerBuffDisappearTime(curTeamPlayer) + elif ownerType == ChConfig.Def_NPCHurtTypeFamily: + copyPlayerMgr = GameWorld.GetMapCopyPlayerManager() + for index in xrange(copyPlayerMgr.GetPlayerCount()): + player = copyPlayerMgr.GetPlayerByIndex(index) + if not player: + continue + self.__SetDropOwnerBuffDisappearTime(player) + + return + + def __SetDropOwnerBuffDisappearTime(self, curPlayer): + ''' 设置掉落归属buff消失时间 ''' + + curNPC = self.__Instance + findSkill = GameWorld.GetGameData().GetSkillBySkillID(ChConfig.Def_SkillID_DropOwnerBuff) + if not findSkill: + return + + buffType = SkillCommon.GetBuffType(findSkill) + buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType) + if buffTuple == (): + return + + RemainTime = 10000 # 延迟10秒消失 + tick = GameWorld.GetGameWorld().GetTick() + + buffStateManager = buffTuple[0] + for index in xrange(buffStateManager.GetBuffCount()): + curBuff = buffStateManager.GetBuff(index) + buffSkill = curBuff.GetSkill() + + if buffSkill.GetSkillTypeID() != ChConfig.Def_SkillID_DropOwnerBuff: + continue + + if curNPC.GetID() != curBuff.GetOwnerID(): + #GameWorld.DebugLog("非buff归属着,不设置消失时间!", curPlayer.GetPlayerID()) + break + + curBuff.SetCalcStartTick(tick) + curBuff.SetRemainTime(RemainTime) + + # 通知buff刷新 + buffStateManager.Sync_RefreshBuff(index, curBuff.GetRemainTime()) + #GameWorld.DebugLog("掉落归属buff消失时间: RemainTime=%s" % (RemainTime), curPlayer.GetPlayerID()) + break + return + ##--------------------------------------------- ----------------------------------------------- + +def OnPlayerKillNPCPlayer(curPlayer, defender, tick): + ## 玩家击杀了NPC相关的玩家 + contendNPCObjID = defender.GetDictByKey(ChConfig.Def_PlayerKey_ContendNPCObjID) + if contendNPCObjID: + curNPC = GameWorld.FindNPCByID(contendNPCObjID) + if not curNPC: + return + dropOwnerType = GetDropOwnerType(curNPC) + if dropOwnerType != ChConfig.DropOwnerType_Contend: + return + playerID = curPlayer.GetPlayerID() + GameWorld.DebugLog("玩家击杀竞争归属者! defPlayerID=%s,contendNPCObjID=%s,npcID=%s" + % (defender.GetPlayerID(), contendNPCObjID, curNPC.GetNPCID()), playerID) + npcControl = NPCControl(curNPC) + npcControl.UpdateDropOwner(tick, ChConfig.Def_NPCHurtTypePlayer, playerID, False) + + return + #--------------------------------------------------------------------- +def SendVirtualItemDrop(player, itemID, posX, posY, userDataStr): + #通知客户端假物品掉落 + vItemDrop = ChPyNetSendPack.tagMCVirtualItemDrop() + vItemDrop.ItemTypeID = itemID + vItemDrop.PosX = posX + vItemDrop.PosY = posY + vItemDrop.UserData = userDataStr + vItemDrop.UserDataLen = len(vItemDrop.UserData) + NetPackCommon.SendFakePack(player, vItemDrop) + return + def GetNPCExp(curPlayer, npcID): npcData = GameWorld.GetGameData().FindNPCDataByID(npcID) if not npcData: @@ -5260,21 +5732,6 @@ return max(value / pow(10, nlen), 1) -Def_CollNPCCfg_Len = 10 -( -Def_CollNPCCfg_CanTogether, # 是否允许同时采集 -Def_CollNPCCfg_SysMsgMark, # 不可同时采集提示 -Def_CollNPCCfg_CostItemInfo, # 采集消耗物品信息 -Def_CollNPCCfg_PrepareTime, # 采集时间毫秒 -Def_CollNPCCfg_ExpFormat, # 获得经验公式 -Def_CollNPCCfg_MoneyFormat, # 获得金币公式 -Def_CollNPCCfg_ZhenQi, # 获得的真气/魔魂 -Def_CollNPCCfg_GiveItemModeID, # 获得的物品信息模板编号 -Def_CollNPCCfg_NotCostItemNotify, # 消耗品不足提示 -Def_CollNPCCfg_LimitSysMsgMark, #采集上限提示 -) = range(Def_CollNPCCfg_Len) - - def CheckCanCollectByNPCID(curPlayer, npcID, collectNPCIpyData): # 根据NPCID判断是否可以采集 @@ -5310,9 +5767,13 @@ def OnCollectNPCBegin(curPlayer, curNPC, tick): ## 采集NPC开始采集 npcID = curNPC.GetNPCID() - collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID) + collectNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CollectNPC", npcID) if not collectNPCIpyData: - GameWorld.DebugLog("非特定采集NPC...") + #GameWorld.DebugLog("非特定采集NPC...") + return False + + if collectNPCIpyData.GetIsMissionCollectNPC(): + #GameWorld.DebugLog("任务采集物暂不处理") return False if not CheckCanCollectByNPCID(curPlayer, npcID, collectNPCIpyData): @@ -5415,6 +5876,10 @@ GameWorld.DebugLog(" 非特定采集NPC...npcID=%s" % npcID) return + if collectNPCIpyData.GetIsMissionCollectNPC(): + #GameWorld.DebugLog("任务采集物暂不处理") + return + PlayerState.DoCollectingLostHP(curPlayer, collectNPCIpyData, tick, True) if GameWorld.IsCrossServer(): @@ -5440,33 +5905,116 @@ DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData) return +#// A2 34 自定义场景中获取采集奖励 #tagCMGetCustomSceneCollectAward +# +#struct tagCMGetCustomSceneCollectAward +#{ +# tagHead Head; +# DWORD NPCID; //采集的NPCID +#}; +def OnGetCustomSceneCollectAward(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + 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.GetIpyGameData("CollectNPC", npcID) + if collectNPCIpyData: + DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData) + return + def DoGiveCollectNPCAward(curPlayer, npcID, collectNPCIpyData, collectCnt=1): GameWorld.DebugLog("给采集奖励: npcID=%s,collectCnt=%s" % (npcID, collectCnt)) if collectCnt <= 0: return + + if collectNPCIpyData.GetIsMissionCollectNPC(): + #GameWorld.DebugLog("任务采集物暂不处理") + return + isMaxTime = False # 是否达到了采集最大次数 limitMaxTime = collectNPCIpyData.GetMaxCollectCount() if limitMaxTime > 0: todayCollTime = GetTodayCollectCount(curPlayer, npcID) canCollectCnt = max(0, limitMaxTime - todayCollTime) collectCnt = min(collectCnt, canCollectCnt) if collectCnt <= 0: - GameWorld.DebugLog(" 该NPC已达到最大采集次数: todayCollTime=%s,limitMaxTime=%s" % (todayCollTime, limitMaxTime)) + GameWorld.DebugLog(" 该NPC已达到最大采集次数: npcID=%s,todayCollTime=%s,limitMaxTime=%s" % (npcID, todayCollTime, limitMaxTime)) return - updCollTime = todayCollTime + collectCnt + curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID) + updCollTime = curCollTime + collectCnt PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime) SyncCollNPCTime(curPlayer, [npcID]) - GameWorld.DebugLog(" 增加当日采集次数: todayCollTime=%s,updCollTime=%s" % (todayCollTime, updCollTime)) - - giveItemList = collectNPCIpyData.GetCollectAward() - if giveItemList: - itemID, itemCount, isBind = giveItemList - ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isBind, [IPY_GameWorld.rptItem]) + GameWorld.DebugLog(" 增加采集次数: npcID=%s,todayCollTime=%s,curCollTime=%s,updCollTime=%s" % (npcID, todayCollTime, curCollTime, updCollTime)) + isMaxTime = todayCollTime + collectCnt >= limitMaxTime + + awardItemList = [] + collectAwardCfg = collectNPCIpyData.GetCollectAward() + collectAppointAwardCfg = collectNPCIpyData.GetCollectAppointAward() + if collectAppointAwardCfg: + #缥缈草园的采集定制由缥缈寻访次数决定 + 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) + if awardItemList: + for itemID, itemCount, isAuctionItem in awardItemList: + ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem]) + if collectNPCIpyData.GetNotifyCollectResult(): + awardPack = ChPyNetSendPack.tagMCCollectAwardItemInfo() + awardPack.CollectNPCID = npcID + for itemID, itemCount, isAuctionItem in awardItemList: + awardItem = ChPyNetSendPack.tagMCCollectAwardItem() + awardItem.ItemID = itemID + awardItem.Count = itemCount + awardItem.IsAuctionItem = isAuctionItem + awardPack.AwardItemList.append(awardItem) + awardPack.Count = len(awardPack.AwardItemList) + NetPackCommon.SendFakePack(curPlayer, awardPack) + GameLogic_CrossGrassland.RecordGrasslandAward(curPlayer, awardItemList) + else: + GameWorld.ErrLog("采集物品没有奖励!npcID=%s" % (npcID)) #采集成就 PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, collectCnt, [npcID]) #SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID) + + GameLogic_CrossGrassland.DecCustomSceneNPCCount(curPlayer, npcID) + if isMaxTime: + GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer) + return ## 采集结果同步 @@ -5513,11 +6061,20 @@ def CollNPCTimeOnDay(curPlayer): ## 采集NPCOnDay处理 + DoResetCollectNPCTimeByType(curPlayer, [1]) + return + +def DoResetCollectNPCTimeByType(curPlayer, resetTypeList=[]): + '''重置采集物采集次数 + 重置类型: 0-不重置,1-每日5点,12-灵草园重置,14-仙草园重置 + ''' resetNPCIDList = [] ipyDataMgr = IpyGameDataPY.IPY_Data() for index in xrange(ipyDataMgr.GetCollectNPCCount()): ipyData = ipyDataMgr.GetCollectNPCByIndex(index) npcID = ipyData.GetNPCID() + if resetTypeList and ipyData.GetCollectResetType() not in resetTypeList: + continue if not ipyData.GetMaxCollectCount(): continue if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID): @@ -5526,6 +6083,7 @@ resetNPCIDList.append(npcID) if resetNPCIDList: + #GameWorld.DebugLog("重置采集次数: resetTypeList=%s,resetNPCIDList=%s" % (resetTypeList, resetNPCIDList), curPlayer.GetPlayerID()) SyncCollNPCTime(curPlayer, resetNPCIDList) return @@ -5675,7 +6233,7 @@ NetPackCommon.SendFakePack(curPlayer, npcInfoPack) return -def SendGameServerGoodItemRecord(mapID, npcID, playerName, playerID, itemID, equipInfo=[], serverGroupID=0): +def SendGameServerGoodItemRecord(curPlayer, mapID, lineID, npcID, itemID, equipInfo=[]): # @param equipInfo: [equipPlace, itemClassLV, itemColor, itemQuality, itemUserData] # GameWorld.DebugLog("检查物品是否发送GameServer: mapID=%s, npcID=%s, playerName=%s, itemID=%s" # % (mapID, npcID, playerName, itemID)) @@ -5695,18 +6253,21 @@ needRecord = True weightValue = recSpecialItemIDList.index(itemID) + 10000 else: - equipPlace, itemClassLV, itemColor, itemQuality, itemUserData = equipInfo - weightValue = itemColor*1000+itemQuality*100+itemClassLV + equipPlace, itemClassLV, itemColor, suiteID, itemUserData = equipInfo + isSuit = 1 if suiteID else 0 + weightValue = itemColor*1000+isSuit*100+itemClassLV recordCondition = GameWorld.GetDictValueByKey(recDropEquipInfoDict, equipPlace) if recordCondition: - needClassLV, needItemColor, needItemQuality = recordCondition - if itemClassLV >= needClassLV and itemColor >= needItemColor and itemQuality >= needItemQuality: + needClassLV, needItemColor, needItemSuite = recordCondition + if itemClassLV >= needClassLV and itemColor >= needItemColor and isSuit >= needItemSuite: needRecord = True if not needRecord: return - - dropEquipMsg = str([playerID, playerName, mapID, npcID, itemID, itemUserData, weightValue, serverGroupID]) + playerID = curPlayer.GetID() + playerName = curPlayer.GetName() + serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer) + dropEquipMsg = str([playerID, playerName, mapID, lineID, npcID, itemID, itemUserData, weightValue, serverGroupID, curPlayer.GetLV()]) GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'BossDropGoodItem', dropEquipMsg, len(dropEquipMsg)) GameWorld.DebugLog("发送GameServer记录拾取掉落好物品: %s" % dropEquipMsg, playerID) return @@ -5818,3 +6379,117 @@ sendPack.Value = speed curNPC.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength()) 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): + ## 收到跨服服务器同步的攻击NPC次数 + npcID = msgData["NPCID"] + attackCount = msgData["AttackCount"] + maxCount = msgData["MaxCount"] + UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount) + return + +def SyncNPCAttackCount(curPlayer, npcIDList): + ## 同步NPC攻击次数 + if not npcIDList: + return + + clientPack = ChPyNetSendPack.tagMCNPCAttackCountInfo() + for npcID in npcIDList: + attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID) + atkCountObj = ChPyNetSendPack.tagMCNPCAttackCount() + atkCountObj.NPCID = npcID + atkCountObj.AttackCount = attackCount + clientPack.NPCAttackCountList.append(atkCountObj) + clientPack.Count = len(clientPack.NPCAttackCountList) + NetPackCommon.SendFakePack(curPlayer, clientPack) + return + + +def OnNPCAttacked(atkObj, curNPC, skill, tick): + ## NPC被攻击 + __OnAttackedDropItem(atkObj, curNPC) + return + +## 每次被攻击掉落物品 +# @param atkObj 攻击发起者 +# @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 + + \ No newline at end of file -- Gitblit v1.8.0