/// <summary> /// /// </summary> /// <param name="creature"></param> /// <param name="itemEntityId"></param> /// <param name="moveToInventory"></param> /// <returns></returns> public bool Buy(Creature creature, long itemEntityId, bool moveToInventory) { var shop = this; var owner = creature.Temp.CurrentShopOwner; // Get item // In theory someone could buy an item without it being visible // to him, but he would need the current entity id that // changes on each restart. It's unlikely to ever be a problem. var item = shop.GetItem(itemEntityId); if (item == null) { Log.Warning("NpcShopScript.Buy: Item '{0:X16}' doesn't exist in shop.", itemEntityId); return(false); } // Check stock if (item.Stock == 0) { Send.MsgBox(creature, Localization.Get("This item is not in stock anymore.")); return(false); } // Determine which payment method to use, the same way the client // does to display them. Points > Stars > Ducats > Gold. var paymentMethod = PaymentMethod.Gold; if (item.OptionInfo.StarPrice > 0) { paymentMethod = PaymentMethod.Stars; } if (item.OptionInfo.DucatPrice > 0) { paymentMethod = PaymentMethod.Ducats; } if (item.OptionInfo.PointPrice > 0) { paymentMethod = PaymentMethod.Points; } // Get buying price var price = int.MaxValue; switch (paymentMethod) { case PaymentMethod.Gold: price = item.OptionInfo.Price; break; case PaymentMethod.Stars: price = item.OptionInfo.StarPrice; break; case PaymentMethod.Ducats: price = item.OptionInfo.DucatPrice; break; case PaymentMethod.Points: price = item.OptionInfo.PointPrice; break; } // The client expects the price for a full stack to be sent // in the ItemOptionInfo, so we have to calculate the actual price here. if (item.Data.StackType == StackType.Stackable) { price = (int)(price / (float)item.Data.StackMax * item.Amount); } // Wednesday: Decrease in prices (5%) for items in NPC shops, // including Remote Shop Coupons and money deposit for Exploration Quests. if (ErinnTime.Now.Month == ErinnMonth.AlbanHeruin) { price = (int)(price * 0.95f); } // Check currency var canPay = false; switch (paymentMethod) { case PaymentMethod.Gold: canPay = (creature.Inventory.Gold >= price); break; case PaymentMethod.Stars: canPay = (creature.Inventory.Stars >= price); break; case PaymentMethod.Ducats: canPay = false; break; // TODO: Implement ducats. case PaymentMethod.Points: canPay = (creature.Points >= price); break; } if (!canPay) { switch (paymentMethod) { case PaymentMethod.Gold: Send.MsgBox(creature, Localization.Get("Insufficient amount of gold.")); break; case PaymentMethod.Stars: Send.MsgBox(creature, Localization.Get("Insufficient amount of stars.")); break; case PaymentMethod.Ducats: Send.MsgBox(creature, Localization.Get("Insufficient amount of ducats.")); break; case PaymentMethod.Points: Send.MsgBox(creature, Localization.Get("You don't have enough Pon.\nYou will need to buy more.")); break; } return(false); } // Buy, adding item, and removing currency var success = false; var newItem = new Item(item); // Set guild data if (newItem.HasTag("/guild_robe/") && creature.Guild != null && creature.Guild.HasRobe) { // EBCL1:4:-11042446;EBCL2:4:-7965756;EBLM1:1:45;EBLM2:1:24;EBLM3:1:6;GLDNAM:s:Name; newItem.Info.Color1 = creature.Guild.Robe.RobeColor; newItem.Info.Color2 = GuildRobe.GetColor(creature.Guild.Robe.BadgeColor); newItem.Info.Color3 = GuildRobe.GetColor(creature.Guild.Robe.EmblemMarkColor); newItem.MetaData1.SetInt("EBCL1", (int)GuildRobe.GetColor(creature.Guild.Robe.EmblemOutlineColor)); newItem.MetaData1.SetInt("EBCL2", (int)GuildRobe.GetColor(creature.Guild.Robe.StripesColor)); newItem.MetaData1.SetByte("EBLM1", creature.Guild.Robe.EmblemMark); newItem.MetaData1.SetByte("EBLM2", creature.Guild.Robe.EmblemOutline); newItem.MetaData1.SetByte("EBLM3", creature.Guild.Robe.Stripes); newItem.MetaData1.SetString("GLDNAM", creature.Guild.Name); } // Cursor if (!moveToInventory) { success = creature.Inventory.Add(newItem, Pocket.Cursor); } // Inventory else { success = creature.Inventory.Add(newItem, false); } if (success) { // Reset gold price if payment method wasn't gold, as various // things depend on the gold price, like repair prices. // If any payment method but gold was used, the gold price // would be 0. if (paymentMethod != PaymentMethod.Gold) { newItem.ResetGoldPrice(); } // Reduce gold/points switch (paymentMethod) { case PaymentMethod.Gold: creature.Inventory.Gold -= price; break; case PaymentMethod.Stars: creature.Inventory.Stars -= price; break; case PaymentMethod.Ducats: break; // TODO: Implement ducats. case PaymentMethod.Points: creature.Points -= price; break; } // Reduce stock if (item.Stock > 0) { // Don't let it go below 0, that would mean unlimited. item.Stock = Math.Max(0, item.Stock - 1); if (item.Stock == 0) { // Refresh shop, so the item disappears. Send.ClearNpcShop(creature); Send.AddToNpcShop(creature, this.GetTabs(creature, owner)); } Send.ServerMessage(creature, "Debug: Stock remaining: {0}", item.Stock); } } return(success); }
public void NpcShopBuyItem(ChannelClient client, Packet packet) { var entityId = packet.GetLong(); var targetPocket = packet.GetByte(); // 0:cursor, 1:inv var unk = packet.GetByte(); // storage gold? var creature = client.GetCreatureSafe(packet.Id); // Check session // Not compatible with remote shop access, unless we bind it to NPCs. //client.NpcSession.EnsureValid(); // Check open shop if (creature.Temp.CurrentShop == null) { throw new ModerateViolation("Tried to buy an item with a null shop."); } // Get item // In theory someone could buy an item without it being visible // to him, but he would need the current entity id that // changes on each restart. It's unlikely to ever be a problem. var item = creature.Temp.CurrentShop.GetItem(entityId); if (item == null) { Log.Warning("NpcShopBuyItem: Item '{0:X16}' doesn't exist in shop.", entityId); goto L_Fail; } // Determine which payment method to use, the same way the client // does to display them. Points > Stars > Ducats > Gold. var paymentMethod = PaymentMethod.Gold; if (item.OptionInfo.StarPrice > 0) { paymentMethod = PaymentMethod.Stars; } if (item.OptionInfo.DucatPrice > 0) { paymentMethod = PaymentMethod.Ducats; } if (item.OptionInfo.PointPrice > 0) { paymentMethod = PaymentMethod.Points; } // Get buying price var price = int.MaxValue; switch (paymentMethod) { case PaymentMethod.Gold: price = item.OptionInfo.Price; break; case PaymentMethod.Stars: price = item.OptionInfo.StarPrice; break; case PaymentMethod.Ducats: price = item.OptionInfo.DucatPrice; break; case PaymentMethod.Points: price = item.OptionInfo.PointPrice; break; } // The client expects the price for a full stack to be sent // in the ItemOptionInfo, so we have to calculate the actual price here. if (item.Data.StackType == StackType.Stackable) { price = (int)(price / (float)item.Data.StackMax * item.Amount); } // Wednesday: Decrease in prices (5%) for items in NPC shops, // including Remote Shop Coupons and money deposit for Exploration Quests. if (ErinnTime.Now.Month == ErinnMonth.AlbanHeruin) { price = (int)(price * 0.95f); } // Check currency var canPay = false; switch (paymentMethod) { case PaymentMethod.Gold: canPay = (creature.Inventory.Gold >= price); break; case PaymentMethod.Stars: canPay = (creature.Inventory.Stars >= price); break; case PaymentMethod.Ducats: canPay = false; break; // TODO: Implement ducats. case PaymentMethod.Points: canPay = (creature.Points >= price); break; } if (!canPay) { switch (paymentMethod) { case PaymentMethod.Gold: Send.MsgBox(creature, Localization.Get("Insufficient amount of gold.")); break; case PaymentMethod.Stars: Send.MsgBox(creature, Localization.Get("Insufficient amount of stars.")); break; case PaymentMethod.Ducats: Send.MsgBox(creature, Localization.Get("Insufficient amount of ducats.")); break; case PaymentMethod.Points: Send.MsgBox(creature, Localization.Get("You don't have enough Pon.\nYou will need to buy more.")); break; } goto L_Fail; } // Buy, adding item, and removing currency var success = false; // Set guild data if (item.HasTag("/guild_robe/") && creature.Guild != null && creature.Guild.HasRobe) { // EBCL1:4:-11042446;EBCL2:4:-7965756;EBLM1:1:45;EBLM2:1:24;EBLM3:1:6;GLDNAM:s:Name; item.Info.Color1 = creature.Guild.Robe.RobeColor; item.Info.Color2 = GuildRobe.GetColor(creature.Guild.Robe.BadgeColor); item.Info.Color3 = GuildRobe.GetColor(creature.Guild.Robe.EmblemMarkColor); item.MetaData1.SetInt("EBCL1", (int)GuildRobe.GetColor(creature.Guild.Robe.EmblemOutlineColor)); item.MetaData1.SetInt("EBCL2", (int)GuildRobe.GetColor(creature.Guild.Robe.StripesColor)); item.MetaData1.SetByte("EBLM1", creature.Guild.Robe.EmblemMark); item.MetaData1.SetByte("EBLM2", creature.Guild.Robe.EmblemOutline); item.MetaData1.SetByte("EBLM3", creature.Guild.Robe.Stripes); item.MetaData1.SetString("GLDNAM", creature.Guild.Name); } // Cursor if (targetPocket == 0) { success = creature.Inventory.Add(item, Pocket.Cursor); } // Inventory else if (targetPocket == 1) { success = creature.Inventory.Add(item, false); } if (success) { // Reset gold price if payment method wasn't gold, as various // things depend on the gold price, like repair prices. // If any payment method but gold was used, the gold price // would be 0. if (paymentMethod != PaymentMethod.Gold) { item.ResetGoldPrice(); } // Reduce switch (paymentMethod) { case PaymentMethod.Gold: creature.Inventory.Gold -= price; break; case PaymentMethod.Stars: creature.Inventory.Stars -= price; break; case PaymentMethod.Ducats: break; // TODO: Implement ducats. case PaymentMethod.Points: creature.Points -= price; break; } } // Response Send.NpcShopBuyItemR(creature, success); return; L_Fail: Send.NpcShopBuyItemR(creature, false); }