//[TestMethod()]
        public void Command_Should_Recognize_Bad_Command()
        {
            // ARRANGE
            Character toon = null;
            InventoryItem invItem = new InventoryItem();

            // Get the client's character info
            string charName = "Badass";
            DataLoadOptions dlo = new DataLoadOptions();
            dlo.LoadWith<Character>(c => c.Account);
            dlo.LoadWith<Character>(c => c.Zone);
            dlo.LoadWith<Character>(c => c.InventoryItems);
            dlo.LoadWith<InventoryItem>(ii => ii.Item);
            using (EmuDataContext dbCtx = new EmuDataContext()) {
                dbCtx.ObjectTrackingEnabled = false;
                dbCtx.LoadOptions = dlo;
                toon = dbCtx.Characters.SingleOrDefault(c => c.Name == charName);
            }

            ZonePlayer zp = new ZonePlayer(1, toon, 1, new Client(new System.Net.IPEndPoint(0x2414188f, 123)));

            // ACT
            zp.MsgMgr.ReceiveChannelMessage("someTarget", "!shitCMd /badArg:200", 8, 0, 100);

            // ASSERT
        }
 internal static void SendItemPacket(Client client, InventoryItem invItem, int slotId, ItemPacketType packetType)
 {
     invItem.SlotID = slotId;
     _log.DebugFormat("Sending item packet for {0}", invItem);
     //_log.DebugFormat("Serialized inv item: {0}", invItem.Serialize());
     ItemPacket item = new ItemPacket(packetType, invItem.Serialize());
     AppOpCode opCode = packetType == ItemPacketType.ViewLink ? AppOpCode.ItemLinkResponse : AppOpCode.ItemPacket;
     //_log.DebugFormat("Serialized Item packet: {0}", BitConverter.ToString(item.Serialize()));
     EQRawApplicationPacket itemPack = new EQRawApplicationPacket(opCode, client.IPEndPoint, item.Serialize());
     client.SendApplicationPacket(itemPack);
 }
        //[TestMethod()]
        public void Weapon_Should_Equip_Correctly()
        {
            // ARRANGE
            Character toon = null;
            InventoryItem invItem = new InventoryItem();
            Item item = null;

            // Get the client's character info
            string charName = "Badass";
            DataLoadOptions dlo = new DataLoadOptions();
            dlo.LoadWith<Character>(c => c.Account);
            dlo.LoadWith<Character>(c => c.Zone);
            dlo.LoadWith<Character>(c => c.InventoryItems);
            dlo.LoadWith<InventoryItem>(ii => ii.Item);
            using (EmuDataContext dbCtx = new EmuDataContext()) {
                dbCtx.ObjectTrackingEnabled = false;
                dbCtx.LoadOptions = dlo;
                toon = dbCtx.Characters.SingleOrDefault(c => c.Name == charName);
            }

            ZonePlayer zp = new ZonePlayer(1, toon, 1, new Client(new System.Net.IPEndPoint(0x2414188f, 123)));

            // Get the inventory item we're giving to the char
            using (EmuDataContext dbCtx = new EmuDataContext()) {
                dbCtx.ObjectTrackingEnabled = false;
                item = dbCtx.Items.SingleOrDefault(i => i.ItemID == 5023);
            }
            invItem.Item = item;

            // ACT
            zp.AutoGiveItem(ref invItem);

            // ASSERT
        }
        public void Item_Should_Stack_Correctly_In_A_Container()
        {
            // ARRANGE
            Character toon = null;
            InventoryItem invItem = new InventoryItem();
            Item item = null;

            // Get the client's character info
            string charName = "Badass";
            DataLoadOptions dlo = new DataLoadOptions();
            dlo.LoadWith<Character>(c => c.Account);
            dlo.LoadWith<Character>(c => c.Zone);
            dlo.LoadWith<Character>(c => c.InventoryItems);
            dlo.LoadWith<InventoryItem>(ii => ii.Item);
            using (EmuDataContext dbCtx = new EmuDataContext()) {
                dbCtx.ObjectTrackingEnabled = false;
                dbCtx.LoadOptions = dlo;
                toon = dbCtx.Characters.SingleOrDefault(c => c.Name == charName);
            }

            ZonePlayer zp = new ZonePlayer(1, toon, 1, new Client(new System.Net.IPEndPoint(0x2414188f, 123)));

            // Get the inventory item (bone chips) we're giving to the char
            using (EmuDataContext dbCtx = new EmuDataContext()) {
                dbCtx.ObjectTrackingEnabled = false;
                item = dbCtx.Items.SingleOrDefault(i => i.ItemID == 13073);
            }
            invItem.Item = item;
            invItem.Charges = 1;    // Giving one bone chip

            // ACT
            if (!zp.AutoGiveItem(ref invItem))
                zp.GiveItem(invItem, (int)InventorySlot.Cursor);
        }
        /// <summary>Swaps a whole item or stack.</summary>
        /// <returns>True if swap occurs, else false.</returns>
        private bool SwapItem(InventoryItem srcInvItem, int fromSlotId, InventoryItem destInvItem, int toSlotId, bool fireEvent)
        {
            // Check that the source item is able to go to the dest slot and that the destination item non-existant or can be swapped
            if (ValidateSlot(srcInvItem, toSlotId) && (destInvItem == null || ValidateSlot(destInvItem, fromSlotId))) {
                if (fromSlotId == (int)InventorySlot.Cursor)
                    _cursorQueue.Dequeue(); // If we're moving something from the cursor, dequeue it

                if (srcInvItem.Item.ItemClass == Item.ITEM_CLASS_CONTAINER) { // Are we moving a container from the source slot?
                    // Clear items from any possible containers
                    ClearBagContents(toSlotId);     // We can assume the items are both containers as we've validated by this point
                    ClearBagContents(fromSlotId);

                    // Move source container's items to the destination container slots
                    int idx = 0;
                    foreach (InventoryItem invItem in srcInvItem.SubItems()) {
                        int toContSlotID = GetSlotIdWithinContainer(toSlotId, idx);
                        int fromContSlotID = GetSlotIdWithinContainer(fromSlotId, idx);
                        //_log.DebugFormat("Moving item from within a container @ slot {0} to slot {1}", fromContSlotID, toContSlotID);

                        this[toContSlotID] = invItem;
                        idx++;
                    }
                }

                if (destInvItem != null && destInvItem.Item.ItemClass == Item.ITEM_CLASS_CONTAINER) {
                    // Move destination container's items to the source container slots
                    int idx = 0;
                    int fromContSlotID = GetSlotIdWithinContainer(fromSlotId, idx);
                    foreach (InventoryItem invItem in destInvItem.SubItems())
                        this[fromContSlotID + idx++] = invItem;
                }

                // Swap the source and destination items
                this[toSlotId] = srcInvItem;
                this[fromSlotId] = destInvItem;

                if (fireEvent) {
                    OnItemMoved(new ItemMoveEventArgs((uint)fromSlotId, (uint)toSlotId, 0, false));
                    if (destInvItem != null)
                        OnItemMoved(new ItemMoveEventArgs((uint)toSlotId, (uint)fromSlotId, 0, false));
                }

                return true;
            }
            else
                return false;
        }
Example #6
0
        /// <summary>Gives a stack of items to the player.</summary>
        /// <returns>True if the ENTIRE stack is successfully given.</returns>
        internal bool GiveStack(ref InventoryItem invItem)
        {
            if (!invItem.Item.stackable || invItem.Charges >= invItem.Item.stacksize) {
                _log.ErrorFormat("Tried to stack item {0} with {1} charges.  Item {2} stackable with a stack size of {3}",
                    invItem.Item.Name, invItem.Charges, invItem.Item.stackable ? "is" : "isn't", invItem.Item.stacksize);
                return false;
            }

            InventoryItem ii = null;
            for (int i = (int)InventorySlot.PersonalSlotsBegin; i <= (int)InventorySlot.PersonalSlotsEnd; i++) {
                ii = this.InvMgr[i];
                if (ii != null) {
                    if (ii.ItemID == invItem.ItemID && ii.Charges < ii.Item.stacksize) {
                        // we have a matching item with available space
                        _log.DebugFormat("Trying to give {0} charges from item {1} to item {2} in slot {3} that has {4} charges",
                            invItem.Charges, invItem.Item.Name, ii.Item.Name, i, ii.Charges);
                        this.InvMgr.MoveCharges(ref invItem, ii);

                        if (invItem.Charges > 0)
                            return GiveStack(ref invItem);

                        return true;
                    }
                    else if (ii.Item.IsContainer) {
                        foreach (InventoryItem subItem in ii.SubItems()) {
                            if (subItem.ItemID == invItem.ItemID && subItem.Charges < subItem.Item.stacksize) {
                                // we have a matching sub-item with available space
                                this.InvMgr.MoveCharges(ref invItem, subItem);

                                if (invItem.Charges > 0)
                                    return GiveStack(ref invItem);

                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
Example #7
0
        internal static void Create(string charName, CharacterCreate charCreateStruct)
        {
            // TODO: old emu does some in depth validation of race/class combinations and ability scores.  Will add later if necessary

            using (EmuDataContext dbCtx = new EmuDataContext())
            {
                DataLoadOptions dlo = new DataLoadOptions();
                dlo.LoadWith<StartingItem>(si => si.Item);
                dbCtx.LoadOptions = dlo;

                Character toon = dbCtx.Characters.SingleOrDefault(c => c.Name == charName);
                toon.Race = (short)charCreateStruct.Race;
                toon.Class = (byte)charCreateStruct.Class;
                toon.Gender = (byte)charCreateStruct.Gender;
                toon.Deity = (int)charCreateStruct.Deity;
                toon.STR = (short)charCreateStruct.STR;
                toon.STA = (short)charCreateStruct.STA;
                toon.AGI = (short)charCreateStruct.AGI;
                toon.DEX = (short)charCreateStruct.DEX;
                toon.WIS = (short)charCreateStruct.WIS;
                toon.INT = (short)charCreateStruct.INT;
                toon.CHA = (short)charCreateStruct.CHA;
                toon.Face = (byte)charCreateStruct.Face;
                toon.EyeColor1 = (byte)charCreateStruct.EyeColor1;
                toon.EyeColor2 = (byte)charCreateStruct.EyeColor2;
                toon.HairStyle = (byte)charCreateStruct.HairStyle;
                toon.HairColor = (byte)charCreateStruct.HairColor;
                toon.Beard = (byte)charCreateStruct.Beard;
                toon.BeardColor = (byte)charCreateStruct.BeardColor;
                toon.LastSeenDate = DateTime.Now;
                toon.CharLevel = 1;
                toon.PracticePoints = 5;
                toon.HP = 1000;     // just here for dev, later will be set elsewhere
                toon.HungerLevel = 6000;
                toon.ThirstLevel = 6000;
                toon.Platinum = (uint)EQEmulator.Servers.WorldServer.ServerConfig.StartingPlat;
                toon.Gold = (uint)EQEmulator.Servers.WorldServer.ServerConfig.StartingGold;

                SetRacialStartingAbilities(ref toon);   // Sets languages and skills that are racially determined
                SetClassStartingAbilities(ref toon);    // Sets skills determined by class

                // Get the character's start zone
                StartZone startZone = dbCtx.StartZones.SingleOrDefault(sz => sz.PlayerChoice == charCreateStruct.StartZone
                    && sz.PlayerClass == charCreateStruct.Class && sz.PlayerDeity == charCreateStruct.Deity && sz.PlayerRace == charCreateStruct.Race);
                CharacterBind cb = new CharacterBind();
                toon.X = toon.Y = toon.Z = 0.0F;
                cb.X = cb.Y = cb.Z = 0.0F;
                toon.Heading = 0.0F;

                if (startZone != null)  // TODO: should heading for zone and bind be set to some default setting?
                {
                    // Found a start zone in the db... load up the bind info from that
                    toon.ZoneID = startZone.ZoneID;
                    toon.ZoneName = startZone.Zone.ShortName;
                    toon.X = startZone.X;
                    toon.Y = startZone.Y;
                    toon.Z = startZone.Z;

                    if (startZone.BindZoneID != null)
                    {
                        cb.ZoneID = startZone.BindZoneID.Value;
                        cb.X = startZone.BindX.Value;
                        cb.Y = startZone.BindY.Value;
                        cb.Z = startZone.BindZ.Value;
                    }
                    else
                        cb.ZoneID = startZone.ZoneID;
                }
                else
                    SetDefaultStartZone(charCreateStruct.StartZone, ref toon, ref cb);

                Zone zone = null;

                // Load safe points for start zone coords if necessary
                if (toon.X == 0.0F && toon.Y == 0.0F && toon.Z == 0.0F)
                {
                    zone = dbCtx.Zones.SingleOrDefault(z => z.ZoneID == toon.ZoneID);
                    toon.X = zone.SafeX;
                    toon.Y = zone.SafeY;
                    toon.Z = zone.SafeZ;
                }

                // Load safe points for start bind coords if necessary
                if (cb.X == 0.0F && cb.Y == 0.0F && cb.Z == 0.0F)
                {
                    zone = dbCtx.Zones.SingleOrDefault(z => z.ZoneID == cb.ZoneID);
                    if (zone != null)
                    {
                        cb.X = zone.SafeX;
                        cb.Y = zone.SafeY;
                        cb.Z = zone.SafeZ;
                    }
                    else
                        _log.ErrorFormat("Unable to load safe points for bind zone {0}", cb.ZoneID);
                }

                cb.Heading = toon.Heading.Value;
                toon.CharacterBinds.Add(cb);

                // Get starting items
                var startingItems = from si in dbCtx.StartingItems
                                    where (si.Race == toon.Race.Value || si.Race == 0) && (si.Class == toon.Class.Value || si.Class == 0)
                                    && (si.DeityID == (toon.Deity ?? 0) || si.DeityID == 0) && (si.ZoneID == toon.ZoneID.Value || si.ZoneID == 0)
                                    select si;

                int siSlotId = 22;    // for initial items with unspecified slots, just dump them to the personal inv slots
                foreach (StartingItem si in startingItems) {
                    InventoryItem ii = new InventoryItem {
                        ItemID = si.ItemID,
                        Charges = si.ItemCharges,
                        Color = si.Item.Color ?? 0,
                        SlotID = si.Slot
                    };

                    if (ii.SlotID < 0) {  // for unspecified inventory slots, find an open slot
                        ii.SlotID = siSlotId;
                        siSlotId++;
                    }

                    toon.InventoryItems.Add(ii);
                }

                dbCtx.SubmitChanges();
            }
        }
Example #8
0
 internal void GiveItem(InventoryItem invItem)
 {
     InventoryItem newItem = invItem.ToNewInventoryItem();
     AddItem(newItem, true, true);
 }
 partial void UpdateInventoryItem(InventoryItem instance);
 partial void DeleteInventoryItem(InventoryItem instance);
 partial void InsertInventoryItem(InventoryItem instance);
		private void detach_InventoryItems(InventoryItem entity)
		{
			this.SendPropertyChanging();
			entity.Character = null;
		}
		private void attach_InventoryItems(InventoryItem entity)
		{
			this.SendPropertyChanging();
			entity.Item = this;
		}
Example #14
0
        internal void AddItem(InventoryItem invItem, bool equip, bool wearChange)
        {
            if (equip) {
                EquipableType equipSlot = EquipableType.Unequipable;
                short equipMat = 0;

                if (invItem.Item.Material == 0 || (invItem.Item.slots & (1 << (int)InventorySlot.Primary | 1 << (int)InventorySlot.Secondary)) > 0) {
                    if (invItem.Item.IDFile.Length > 2)
                        equipMat = short.Parse(invItem.Item.IDFile.Substring(2));
                }
                else
                    equipMat = (short)invItem.Item.Material;

                if ((invItem.Item.slots & (1 << (int)InventorySlot.Primary)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Primary))) {
                    // TODO: add weapon procs (need spells in I think)

                    equipSlot = EquipableType.Primary;
                }
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Secondary)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Secondary))) {
                    if (this.Level >= 13 || invItem.Item.Damage == 0) {     // TODO: add check here for if we are a pet... pets will take anything?
                        if (invItem.Item.ItemType == (byte)ItemType.OneHandBash || invItem.Item.ItemType == (byte)ItemType.OneHandSlash
                        || invItem.Item.ItemType == (byte)ItemType.Shield || invItem.Item.ItemType == (byte)ItemType.Pierce) {

                            // TODO: add weapon procs (need spells in I think)

                            equipSlot = EquipableType.Secondary;
                        }
                    }
                }
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Head)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Head)))
                    equipSlot = EquipableType.Head;
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Chest)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Chest)))
                    equipSlot = EquipableType.Chest;
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Arms)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Arms)))
                    equipSlot = EquipableType.Arms;
                else if ((invItem.Item.slots & ((1 << (int)InventorySlot.Bracer1) | (1 << (int)InventorySlot.Bracer2))) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Bracer)))
                    equipSlot = EquipableType.Bracer;
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Hands)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Hands)))
                    equipSlot = EquipableType.Hands;
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Legs)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Legs)))
                    equipSlot = EquipableType.Legs;
                else if ((invItem.Item.slots & (1 << (int)InventorySlot.Feet)) > 0 && (!_equipedItems.ContainsKey((byte)EquipableType.Feet)))
                    equipSlot = EquipableType.Feet;

                if (equipSlot != EquipableType.Unequipable) {
                    _equipedItems[(byte)equipSlot] = invItem;   // Equip the item
                    invItem.SlotID = (int)InventoryManager.GetEquipableSlot(equipSlot);

                    if (wearChange) {
                        WearChange wc = new WearChange();
                        wc.SpawnId = (short)this.ID;
                        wc.WearSlotId = (byte)equipSlot;
                        wc.Material = equipMat;
                        OnWearChanged(new WearChangeEventArgs(wc)); // Fire wear changed event
                    }

                    CalcStatModifiers();
                }
            }

            _lootItems.Add(invItem);    // SlotID stored if it was equipped
        }
Example #15
0
        internal void CmdSummonItem(Dictionary<string, string> arguments)
        {
            string itemIdStr = "0";
            int itemId;

            if (arguments != null)
                arguments.TryGetValue("id", out itemIdStr);

            itemId = int.Parse(itemIdStr);

            // Get the inventory item we're summoning
            InventoryItem invItem = new InventoryItem();
            invItem.Charges = 1;
            Item item = null;
            using (EmuDataContext dbCtx = new EmuDataContext()) {
                dbCtx.ObjectTrackingEnabled = false;
                item = dbCtx.Items.SingleOrDefault(i => i.ItemID == itemId);
            }

            if (item == null) {
                SendSpecialMessage(MessageType.Default, "No item found with that Id.");
                return;
            }

            invItem.Item = item;

            if (_zp.TargetMob == null)
                _zp.GiveItem(invItem, (int)InventorySlot.Cursor);
            else {
                if (_zp.TargetMob is NpcMob)
                    ((NpcMob)_zp.TargetMob).GiveItem(invItem);
                else if (_zp.TargetMob is ZonePlayer)
                    ((ZonePlayer)_zp.TargetMob).GiveItem(invItem, (int)InventorySlot.Cursor);

                SendSpecialMessage(MessageType.Default, "Gave {0} to {1}.", item.Name, _zp.TargetMob.Name);
            }
        }
Example #16
0
        internal void AddLoot(Npc npc)
        {
            Random rand = new Random();

            // Coin
            if (npc.Loot.MinCash > npc.Loot.MaxCash)
                _log.ErrorFormat("{0}'s minCash({1}) > maxCash({2}), please fix.", npc.Name, npc.Loot.MinCash, npc.Loot.MaxCash);
            else if (npc.Loot.MaxCash > 0) {
                uint cash = 0;

                if (npc.Loot.MaxCash == npc.Loot.MinCash)
                    cash = npc.Loot.MaxCash;
                else
                    cash = (uint)rand.Next((int)npc.Loot.MinCash, (int)npc.Loot.MaxCash + 1);

                if (cash != 0) {
                    this.Platinum = cash / 1000;
                    cash -= this.Platinum * 1000;
                    this.Gold = cash / 100;
                    cash -= this.Gold * 100;
                    this.Silver = cash / 10;
                    cash -= this.Silver * 10;
                    this.Copper = cash;
                }
            }

            // Items
            int sumProb = 0, roll = 0, probIter = 0;

            foreach (LootEntry le in npc.Loot.LootEntries) {
                for (int i = 0; i < le.MaxDrops; i++) {
                    if (rand.Next(0, 100) < le.Probability) {
                        sumProb = le.LootDrops.Sum(ld => ld.Probability);     // Get total probability of all loot drops
                        roll = rand.Next(0, sumProb + 1);

                        probIter = 0;
                        foreach (LootDrop ld in le.LootDrops) {
                            probIter += ld.Probability;
                            if (roll < probIter) {
                                InventoryItem invItem = new InventoryItem()
                                {
                                    Charges = ld.ItemCharges,
                                    Color = ld.Item.Color ?? 0,
                                    Item = ld.Item,
                                    ItemID = ld.ItemID,
                                    SlotID = 0
                                };

                                AddItem(invItem, ld.Equipable, false);
                                break;
                            }
                        }
                    }
                }
            }
        }
        internal void MoveCharges(ref InventoryItem invItemFrom, InventoryItem invItemTo)
        {
            int chargesEmpty = invItemTo.Item.stacksize - invItemTo.Charges.Value;
            int chargesToMove = invItemFrom.Charges < chargesEmpty ? invItemFrom.Charges.Value : chargesEmpty;
            invItemTo.Charges += (byte)chargesToMove;
            invItemFrom.Charges -= (byte)chargesToMove;

            ZoneServer.SendItemPacket(_zp.Client, invItemTo, invItemTo.SlotID, Packets.ItemPacketType.Trade);
            _log.DebugFormat("Moved {0} charges from item {1} in slot {2} to item {3} in slot {4}",
                chargesToMove, invItemFrom.Item.Name, invItemFrom.SlotID, invItemTo.Item.Name, invItemTo.SlotID);
        }
Example #18
0
        /// <summary>Gives an item to the player.  Ensure slot is valid by calling various validators before calling this function.</summary>
        internal InventoryItem GiveItem(InventoryItem invItem, int slotId)
        {
            //_log.DebugFormat("Placing item {0}({1}) into slot {2}", invItem.Item.Name, invItem.ItemID, slotId);
            InventoryItem newItem = invItem.ToNewInventoryItem();
            this.InvMgr[slotId] = newItem;

            ZoneServer.SendItemPacket(this.Client, newItem, ItemPacketType.Trade);

            // TODO: container contents - this may be tricky as each item (if any) in a container are sent separate from the container (above).
            // This means the above item probably can't have the subItems already calculated?  Also probably have to recurse this routine due to
            // arbitrary levels of nested containers

            // TODO: Does loot work differently than say trading items?  Orig emu had a separate giveLoot routine.  Maybe clone invItem to an
            // invItem that doesn't have subItems calculated

            this.InvMgr.CalculateSubItems(InventoryLocations.Personal);
            CalcStatModifiers();
            return this.InvMgr[slotId];
        }
 internal bool ValidateSlot(InventoryItem invItem, int slotID)
 {
     if (invItem.Item.ItemClass == Item.ITEM_CLASS_CONTAINER)    // Is item a bag?
         return InventoryManager.SlotSupportsContainers(slotID);
     else if (InventoryManager.SlotIsInContainer(slotID))    // Is item IN a bag?
         return invItem.Item.Size <= GetBagForSlot(slotID).Item.BagSize;     // Can it fit?
     else if (slotID > (int)InventorySlot.EquipSlotsEnd)     // Everything else left should be cool
         return true;
     else if (invItem.Item.ValidateEquipable(_zp.Race, _zp.Class, _zp.Level, slotID))    // Can we equip it?
         return true;
     else
         return false;
 }
Example #20
0
        /// <summary>Automatically locates and places the specified item into an appropriate slot.</summary>
        /// <returns>True if item was successfully placed.</returns>
        internal bool AutoGiveItem(ref InventoryItem invItem)
        {
            Item item = invItem.Item;

            // First, try to equip
            if (item.ValidateEquipable(this.Race, this.Class, this.Level)) {    // Useable in a worn slot? TODO: check for attuneable items
                for (int i = 0; i <= (int)InventorySlot.EquipSlotsEnd; i++) {
                    if (this.InvMgr[i] == null) {   // Empty slot?
                        if (i == (int)InventorySlot.Primary && item.IsTwoHandedWeapon && this.InvMgr[(int)InventorySlot.Secondary] != null)
                            continue;   // can't equip a two hander with something already in the secondary slot
                        else if (i == (int)InventorySlot.Secondary) {
                            if (this.InvMgr[(int)InventorySlot.Primary] != null && this.InvMgr[(int)InventorySlot.Primary].Item.IsTwoHandedWeapon)
                                continue;   // can't equip in secondary if primary is a two hander
                            if (item.IsWeapon && !this.CanDualWield())
                                continue;   // can't dual wield, so no equiping for you
                        }

                        if (item.ValidateEquipable(i)) {    // Good so far, but can we use it in this slot?
                            GiveItem(invItem, i);
                            return true;
                        }
                    }
                }
            }

            // Second, try to stack it
            if (item.stackable) {
                _log.DebugFormat("Auto-stacking {1} item(s) of {0}", item.Name, invItem.Charges);
                if (GiveStack(ref invItem)) {   // Was ALL of the stack stacked somewhere?
                    CalcStatModifiers();
                    return true;
                }
            }

            // Last, put into a free spot in inventory
            int intoSlotId = this.InvMgr.GetFreeSlot(item.Size, item.IsContainer);

            if (intoSlotId != (int)InventorySlot.Invalid) {
                _log.DebugFormat("Found free slot for {0} at {1}", item.Name, intoSlotId);
                GiveItem(invItem, intoSlotId);
                return true;
            }

            _log.Debug("Can't find a free spot in inventory, all full apparently.");
            return false;
        }
 internal static void SendItemPacket(Client client, InventoryItem invItem, ItemPacketType packetType)
 {
     SendItemPacket(client, invItem, invItem.SlotID, packetType);
 }