예제 #1
0
        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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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;
            }
            }
        }
예제 #4
0
        public short AddItem2(BaseItem item, bool sendpacket = true)
        {
            byte  inventory = Constants.getInventory(item.ItemID);
            short slot      = 0;
            // see if there's a free slot
            BaseItem temp     = null;
            short    maxSlots = 1;

            if (DataProvider.Items.TryGetValue(item.ItemID, out ItemData itemData))
            {
                maxSlots = (short)itemData.MaxSlot;
                if (maxSlots == 0)
                {
                    // 1, 100 or specified
                    maxSlots = 100;
                }
            }
            for (short i = 1; i <= MaxSlots[inventory - 1]; i++)
            { // Slot 1 - 24, not 0 - 23
                temp = GetItem(inventory, i);
                if (temp != null)
                {
                    if (Constants.isStackable(item.ItemID) && item.ItemID == temp.ItemID && temp.Amount < maxSlots)
                    {
                        if (item.Amount + temp.Amount > maxSlots)
                        {
                            short amount = (short)(maxSlots - temp.Amount);
                            item.Amount -= amount;
                            temp.Amount  = maxSlots;
                            if (sendpacket)
                            {
                                InventoryPacket.AddItem(Character, inventory, temp, false);
                            }
                        }
                        else
                        {
                            item.Amount += temp.Amount;
                            // Removing the item looks a bit odd to me?
                            SetItem(inventory, i, null);
                            AddItem(inventory, i, item, false);
                            if (sendpacket)
                            {
                                InventoryPacket.AddItem(Character, inventory, item, false);
                            }
                            return(0);
                        }
                    }
                }
                else if (slot == 0)
                {
                    slot = i;
                    if (!Constants.isStackable(item.ItemID))
                    {
                        break;
                    }
                }
            }
            if (slot != 0)
            {
                SetItem(inventory, slot, item);
                if (sendpacket)
                {
                    InventoryPacket.AddItem(Character, inventory, item, true);
                }
                return(0);
            }
            else
            {
                return(item.Amount);
            }
        }
예제 #5
0
 public static void UpdatePet(Character chr, PetItem petItem)
 {
     InventoryPacket.AddItem(chr, Constants.getInventory(petItem.ItemID), petItem, false);
 }