public bool Buy(Creature creature, long itemEntityId, bool moveToInventory, bool directBankTransaction)
{
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)
{
// Don't warn, this might happen when items are moved while
// a player has the shop open.
Send.MsgBox(creature, Localization.Get("The item is not available."));
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;
// Allow direct transaction only for buying with gold
if (directBankTransaction && paymentMethod != PaymentMethod.Gold)
{
Send.MsgBox(creature, Localization.Get("You can't by this item via direct bank transaction."));
return false;
}
// 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.
// However, the points payment method prices are absolute, the
// client displays them as is.
if (item.Data.StackType == StackType.Stackable && paymentMethod != PaymentMethod.Points)
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:
// Disable direct bank transaction if price is less than 50k
if (directBankTransaction && price < 50000)
directBankTransaction = false;
// Check gold
var gold = 0;
if (directBankTransaction)
{
gold = creature.Client.Account.Bank.Gold;
price = price + (int)(price * 0.05f); // Fee
}
else
gold = creature.Inventory.Gold;
canPay = (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:
if (directBankTransaction)
creature.Client.Account.Bank.RemoveGold(creature, price);
else
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;
}
}