public BaseItem TakeItemAmountFromSlot(byte inventory, short slot, short amount, bool takeStars) { var item = GetItem(inventory, slot); if (item == null) { return(null); } if (!takeStars) { if (item.Amount - amount < 0) { return(null); } } bool removeItem = false; BaseItem newItem; if (takeStars && Constants.isStar(item.ItemID)) { // Take the whole item newItem = item; removeItem = true; } else { newItem = item.SplitInTwo(amount); removeItem = item.Amount == 0 && Constants.isStar(item.ItemID) == false; } if (removeItem) { SetItem(inventory, slot, null); TryRemoveCashItem(item); InventoryPacket.SwitchSlots(Character, slot, 0, inventory); } else { // Update item InventoryPacket.AddItem(Character, inventory, item, false); } return(newItem); }
/// <summary> /// Try to remove <paramref name="amount"/> amount of itemid <paramref name="itemid"/>. /// Does not 'remove' stacks, keeps them as-is (with 0 items). /// </summary> /// <param name="itemid">The Item ID</param> /// <param name="amount">Amount</param> /// <returns>Amount of items that were _not_ taken away</returns> public int TakeItem(int itemid, int amount) { if (amount == 0) { return(0); } int initialAmount = amount; var isRechargeable = Constants.isRechargeable(itemid); byte inventory = Constants.getInventory(itemid); for (short i = 1; i <= MaxSlots[inventory - 1]; i++) { BaseItem item = GetItem(inventory, i); if (item == null || item.ItemID != itemid) { continue; } var maxRemove = Math.Min(item.Amount, amount); item.Amount -= (short)maxRemove; if (item.Amount == 0 && !isRechargeable) { // Your item. Gone. SetItem(inventory, i, null); TryRemoveCashItem(item); InventoryPacket.SwitchSlots(Character, i, 0, inventory); } else { // Update item with new amount InventoryPacket.AddItem(Character, inventory, item, false); } amount -= maxRemove; } return(initialAmount - amount); }
public static void HandleNPCShop(Character chr, Packet packet) { if (chr.ShopNPCID == 0) { return; } var shopInfo = DataProvider.NPCs[chr.ShopNPCID].Shop; var transferId = "" + chr.ID + "-" + chr.ShopNPCID + "-" + RNG.Range.generate(0, long.MaxValue).ToString(); byte type = packet.ReadByte(); switch ((ShopReq)type) { case ShopReq.Buy: { short slot = packet.ReadShort(); int itemid = packet.ReadInt(); short amount = packet.ReadShort(); if (amount < 1 || (Constants.isEquip(itemid) && amount != 1)) { Program.MainForm.LogAppend("Disconnecting player: trying to buy a negative amount of items OR multiple equips. " + packet); chr.Player.Socket.Disconnect(); return; } if (slot < 0 || slot >= shopInfo.Count) { SendShopResult(chr, ShopRes.BuyUnknown); return; } ShopItemData sid = shopInfo[slot]; int costs = amount * sid.Price; if (false && sid.Stock == 0) { SendShopResult(chr, ShopRes.BuyNoStock); return; } if (sid.ID != itemid) { SendShopResult(chr, ShopRes.BuyUnknown); return; } if (costs > chr.Inventory.Mesos) { SendShopResult(chr, ShopRes.BuyNoMoney); return; } if (Constants.isRechargeable(itemid)) { costs = amount * sid.Price; if (amount > DataProvider.Items[itemid].MaxSlot) // You can't but multiple sets at once { SendShopResult(chr, ShopRes.BuyUnknown); return; } } if (!chr.Inventory.HasSlotsFreeForItem(itemid, amount, true)) { SendShopResult(chr, ShopRes.BuyUnknown); return; } Common.Tracking.MesosTransfer.PlayerBuysFromShop(chr.ID, chr.ShopNPCID, costs, transferId); Common.Tracking.ItemTransfer.PlayerBuysFromShop(chr.ID, chr.ShopNPCID, itemid, amount, transferId, null); chr.Inventory.AddNewItem(itemid, amount); SendShopResult(chr, ShopRes.BuySuccess); sid.Stock -= amount; chr.AddMesos(-costs); break; } case ShopReq.Sell: { short itemslot = packet.ReadShort(); int itemid = packet.ReadInt(); short amount = packet.ReadShort(); byte inv = Constants.getInventory(itemid); BaseItem item = chr.Inventory.GetItem(inv, itemslot); if (item == null || item.ItemID != itemid || amount < 1 || // Do not trigger this when selling stars and such. (!Constants.isRechargeable(itemid) && amount > item.Amount) || (Constants.isEquip(itemid) ? DataProvider.Equips.ContainsKey(itemid) == false : DataProvider.Items.ContainsKey(itemid) == false) || item.CashId != 0) { Program.MainForm.LogAppend("Disconnecting player: invalid trade packet: " + packet); chr.Player.Socket.Disconnect(); return; } int sellPrice = 0; if (Constants.isEquip(itemid)) { var ed = DataProvider.Equips[itemid]; sellPrice = ed.Price; } else { var id = DataProvider.Items[itemid]; sellPrice = id.Price * amount; } if (sellPrice < 0) { SendShopResult(chr, ShopRes.SellIncorrectRequest); return; } // Change amount here (rechargeables are sold as 1) if (Constants.isRechargeable(item.ItemID)) { amount = item.Amount; } Common.Tracking.MesosTransfer.PlayerSellsToShop(chr.ID, chr.ShopNPCID, sellPrice, transferId); Common.Tracking.ItemTransfer.PlayerSellsToShop(chr.ID, chr.ShopNPCID, item.ItemID, amount, transferId, item); if (amount == item.Amount) { chr.Inventory.SetItem(inv, itemslot, null); chr.Inventory.TryRemoveCashItem(item); InventoryPacket.SwitchSlots(chr, itemslot, 0, inv); } else { item.Amount -= amount; InventoryPacket.AddItem(chr, inv, item, false); } chr.AddMesos(sellPrice); SendShopResult(chr, ShopRes.SellSuccess); break; } case ShopReq.Recharge: { short itemslot = packet.ReadShort(); byte inv = 2; BaseItem item = chr.Inventory.GetItem(inv, itemslot); if (item == null || !Constants.isRechargeable(item.ItemID)) { Program.MainForm.LogAppend("Disconnecting player: invalid trade packet: " + packet); chr.Player.Socket.Disconnect(); return; } ShopItemData sid = shopInfo.FirstOrDefault((a) => a.ID == item.ItemID); if (sid == null) { Program.MainForm.LogAppend("Disconnecting player: Item not found in shop; not rechargeable?"); chr.Player.Socket.Disconnect(); return; } if (sid.UnitRechargeRate <= 0.0) { SendShopResult(chr, ShopRes.RechargeIncorrectRequest); return; } ItemData data = DataProvider.Items[item.ItemID]; short maxslot = (short)(data.MaxSlot + chr.Skills.GetRechargeableBonus()); short toFill = (short)(maxslot - item.Amount); int sellPrice = (int)Math.Ceiling(-1.0 * sid.UnitRechargeRate * toFill); sellPrice = Math.Max(sellPrice, 1); if (chr.Inventory.Mesos > -sellPrice) { Common.Tracking.MesosTransfer.PlayerBuysFromShop(chr.ID, chr.ShopNPCID, -sellPrice, transferId); Common.Tracking.ItemTransfer.PlayerBuysFromShop(chr.ID, chr.ShopNPCID, item.ItemID, (short)(maxslot - item.Amount), transferId, item); item.Amount = maxslot; chr.AddMesos(sellPrice); InventoryPacket.AddItem(chr, inv, item, false); SendShopResult(chr, ShopRes.RechargeSuccess); } else { SendShopResult(chr, ShopRes.RechargeNoMoney); // no muney? hier! suk a kok! } break; } case ShopReq.Close: chr.ShopNPCID = 0; chr.NpcSession = null; break; default: { Program.MainForm.LogAppend("Unknown NPC shop action: " + packet); break; } } }