Example #1
0
        private static void ReadNPCs()
        {
            ushort Count = Reader.ReadUInt16();

            for (ushort i = 0; i < Count; i++)
            {
                NPCData npc = new NPCData();
                npc.ID    = Reader.ReadInt32();
                npc.Quest = ReadString();
                npc.Trunk = Reader.ReadInt16();
                npc.Shop  = new List <ShopItemData>();
                byte ItemCount = Reader.ReadByte();
                for (byte iw = 0; iw < ItemCount; iw++)
                {
                    ShopItemData item = new ShopItemData();
                    item.ID    = Reader.ReadInt32();
                    item.Price = Reader.ReadInt32();
                    item.Stock = Reader.ReadInt32();
                    npc.Shop.Add(item);
                }
                NPCs.Add(npc.ID, npc);
            }
        }
Example #2
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;
            }
            }
        }