예제 #1
0
        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());
        }
예제 #2
0
        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);
                }
            }
        }