//[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; }
/// <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; }
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(); } }
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; }
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 }
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); } }
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); }
/// <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; }
/// <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); }