public void DoLootRelease(ObjectGuid lguid) { Player player = GetPlayer(); Loot loot; if (player.GetLootGUID() == lguid) { player.SetLootGUID(ObjectGuid.Empty); } player.SendLootRelease(lguid); player.RemoveUnitFlag(UnitFlags.Looting); if (!player.IsInWorld) { return; } if (lguid.IsGameObject()) { GameObject go = player.GetMap().GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player, SharedConst.InteractionDistance))) { return; } loot = go.loot; if (go.GetGoType() == GameObjectTypes.Door) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go.UseDoorOrButton(); } else if (loot.isLooted() || go.GetGoType() == GameObjectTypes.FishingNode) { if (go.GetGoType() == GameObjectTypes.FishingHole) { // The fishing hole used once more go.AddUse(); // if the max usage is reached, will be despawned in next tick if (go.GetUseCount() >= go.GetGoValue().FishingHole.MaxOpens) { go.SetLootState(LootState.JustDeactivated); } else { go.SetLootState(LootState.Ready); } } else { go.SetLootState(LootState.JustDeactivated); } loot.clear(); } else { // not fully looted object go.SetLootState(LootState.Activated, player); // if the round robin player release, reset it. if (player.GetGUID() == loot.roundRobinPlayer) { loot.roundRobinPlayer.Clear(); } } } else if (lguid.IsCorpse()) // ONLY remove insignia at BG { Corpse corpse = ObjectAccessor.GetCorpse(player, lguid); if (!corpse || !corpse.IsWithinDistInMap(player, SharedConst.InteractionDistance)) { return; } loot = corpse.loot; if (loot.isLooted()) { loot.clear(); corpse.RemoveCorpseDynamicFlag(CorpseDynFlags.Lootable); } } else if (lguid.IsItem()) { Item pItem = player.GetItemByGuid(lguid); if (!pItem) { return; } ItemTemplate proto = pItem.GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto.GetFlags().HasAnyFlag(ItemFlags.IsProspectable | ItemFlags.IsMillable)) { pItem.m_lootGenerated = false; pItem.loot.clear(); uint count = pItem.GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) { count = 5; } player.DestroyItemCount(pItem, ref count, true); } else { if (pItem.loot.isLooted() || !proto.GetFlags().HasAnyFlag(ItemFlags.HasLoot)) // Only delete item if no loot or money (unlooted loot is saved to db) { player.DestroyItem(pItem.GetBagSlot(), pItem.GetSlot(), true); } } return; // item can be looted only single player } else { Creature creature = player.GetMap().GetCreature(lguid); bool lootAllowed = creature && creature.IsAlive() == (player.GetClass() == Class.Rogue && creature.loot.loot_type == LootType.Pickpocketing); if (!lootAllowed || !creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance)) { return; } loot = creature.loot; if (loot.isLooted()) { creature.RemoveDynamicFlag(UnitDynFlags.Lootable); // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!creature.IsAlive()) { creature.AllLootRemovedFromCorpse(); } loot.clear(); } else { // if the round robin player release, reset it. if (player.GetGUID() == loot.roundRobinPlayer) { loot.roundRobinPlayer.Clear(); Group group = player.GetGroup(); if (group) { if (group.GetLootMethod() != LootMethod.MasterLoot) { group.SendLooter(creature, null); } } // force dynflag update to update looter and lootable info creature.m_values.ModifyValue(creature.m_objectData).ModifyValue(creature.m_objectData.DynamicFlags); creature.ForceUpdateFieldChange(); } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot.RemoveLooter(player.GetGUID()); player.RemoveAELootedObject(loot.GetGUID()); }
void HandleAutostoreLootItem(LootItemPkt packet) { Player player = GetPlayer(); AELootResult aeResult = player.GetAELootView().Count > 1 ? new AELootResult() : null; // @todo Implement looting by LootObject guid foreach (LootRequest req in packet.Loot) { Loot loot = null; ObjectGuid lguid = player.GetLootWorldObjectGUID(req.Object); if (lguid.IsGameObject()) { GameObject go = player.GetMap().GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go.GetOwnerGUID() != player.GetGUID() && go.GetGoType() != GameObjectTypes.FishingHole) && !go.IsWithinDistInMap(player, SharedConst.InteractionDistance))) { player.SendLootRelease(lguid); continue; } loot = go.loot; } else if (lguid.IsItem()) { Item pItem = player.GetItemByGuid(lguid); if (!pItem) { player.SendLootRelease(lguid); continue; } loot = pItem.loot; } else if (lguid.IsCorpse()) { Corpse bones = ObjectAccessor.GetCorpse(player, lguid); if (!bones) { player.SendLootRelease(lguid); continue; } loot = bones.loot; } else { Creature creature = player.GetMap().GetCreature(lguid); bool lootAllowed = creature && creature.IsAlive() == (player.GetClass() == Class.Rogue && creature.loot.loot_type == LootType.Pickpocketing); if (!lootAllowed || !creature.IsWithinDistInMap(player, AELootCreatureCheck.LootDistance)) { player.SendLootError(req.Object, lguid, lootAllowed ? LootError.TooFar : LootError.DidntKill); continue; } loot = creature.loot; } player.StoreLootItem((byte)(req.LootListID - 1), loot, aeResult); // If player is removing the last LootItem, delete the empty container. if (loot.isLooted() && lguid.IsItem()) { player.GetSession().DoLootRelease(lguid); } } if (aeResult != null) { foreach (var resultValue in aeResult.GetByOrder()) { player.SendNewItem(resultValue.item, resultValue.count, false, false, true); player.UpdateCriteria(CriteriaTypes.LootItem, resultValue.item.GetEntry(), resultValue.count); player.UpdateCriteria(CriteriaTypes.LootType, resultValue.item.GetEntry(), resultValue.count, (ulong)resultValue.lootType); player.UpdateCriteria(CriteriaTypes.LootEpicItem, resultValue.item.GetEntry(), resultValue.count); } } }