Shops
Shops is for the NPC traders (shops run by a character) and the vending machines. You can list them, read their stock and prices, change what they charge, and get told about trades. Each shop is a ShopInfo, a snapshot taken when you asked.
Shops list shops, read prices, and hear about trades
Call All() to list the shops, Stock(shopId) for what one has, and PriceOf for a price. Subscribe to Bought, Sold or PriceQuery to hear about trades.
public static class Shops
{
public static event Action<TradeArgs> Bought;
public static event Action<TradeArgs> Sold;
public static event Action<PriceQueryArgs> PriceQuery;
public static bool IsAvailable { get; }
public static List<ShopInfo> All();
public static ShopInfo Open();
public static List<StockItem> Stock(string shopId);
public static float PriceOf(string shopId, int itemId, int count, bool playerBuys, out MoneyCurrency currency);
}
| Method | Returns | What it does |
|---|---|---|
All() | List<ShopInfo> | Every trader and vending machine in the scene you are in. |
Open() | ShopInfo | The trader whose trade screen is open. null when none. |
Stock(shopId) | List<StockItem> | What the shop has for sale. |
PriceOf(shopId, itemId, count, playerBuys, out currency) | float | The price for a stack. |
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when a shop event could not be set up. |
| Event | Gives you | When it fires |
|---|---|---|
Bought | TradeArgs | The player bought something. |
Sold | TradeArgs | The player sold something. |
PriceQuery | PriceQueryArgs | The game is working out a trader’s price. |
ShopInfo one shop
Shops.All() gives you one of these for each shop. Pass its Id to Stock and PriceOf.
public sealed class ShopInfo
{
public string Id { get; }
public string Name { get; }
public ShopKind Kind { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | string | Names this shop. Use it with Stock and PriceOf. |
Name | string | The shop’s title, or its object name when it has none. |
Kind | ShopKind | Trader or vending machine. |
StockItem one line of a shop's stock
Shops.Stock(shopId) returns one of these for each line of a shop’s stock. UnitPrice is the price of one.
public sealed class StockItem
{
public int ItemId { get; }
public string Name { get; }
public int Count { get; }
public float UnitPrice { get; }
public MoneyCurrency Currency { get; }
}
| Property | Type | What it means |
|---|---|---|
ItemId | int | The item id. |
Name | string | The item’s name. |
Count | int | How many the shop has. |
UnitPrice | float | The price of one. |
Currency | MoneyCurrency | The money the price is in. |
TradeArgs what you get when a trade happens
Bought and Sold pass you one of these. Price is the money that really moved, and Shop says where it happened.
public sealed class TradeArgs
{
public int ItemId { get; }
public int Count { get; }
public float Price { get; }
public MoneyCurrency Currency { get; }
public ShopInfo Shop { get; }
}
| Property | Type | What it means |
|---|---|---|
ItemId | int | The item that was traded. |
Count | int | How many were asked for. |
Price | float | The money that really moved, in Currency. |
Currency | MoneyCurrency | The money used. |
Shop | ShopInfo | The shop. |
PriceQueryArgs what you get when the game asks for a trader's price
PriceQuery gives you one of these while the game works out a trader’s price. Set Price in your handler to change it.
public sealed class PriceQueryArgs
{
public ShopInfo Shop { get; }
public int ItemId { get; }
public int Count { get; }
public bool PlayerBuys { get; }
public MoneyCurrency Currency { get; }
public float Price { get; set; }
}
| Property | Type | What it means |
|---|---|---|
Shop | ShopInfo | The shop. |
ItemId | int | The item. |
Count | int | How many the price is for. |
PlayerBuys | bool | true when the player buys from the shop. false when the player sells to it. |
Currency | MoneyCurrency | The money the price is in. |
Price | float | The price for the whole stack of Count. Your handler can change it. |
ShopKind a trader or a vending machine
ShopInfo.Kind holds one of these: Trader for a shop run by an NPC, and Vending for a vending machine.
public enum ShopKind
{
Trader = 0,
Vending = 1
}
| Value | Meaning |
|---|---|
Trader | A shop run by an NPC. |
Vending | A vending machine. |
Things to know
All()lists the NPC traders and the vending machines. A shop that has no id is left out and can’t be addressed.Open()gives the trader whose trade screen is open right now, ornull. Stock and prices are looked up by item id. (traders areTradeobjects, includingTradeSpecial.Open()readsTradePanel.activeTrade.)- A trader’s price is worked out for a brand new item. The trader sells at its buying-price setting times the item’s value, and buys at its selling-price setting. The money (OC or RM) follows the trader’s own price settings, as in the game. (the trader’s
basePurchasePriceandbaseSellPrice, applied to a fresh item with no meta.) - Because it ignores the liquid, quality or container state of a real item, a trader’s price can differ from the price of one particular item in the world.
- A vending machine’s stock is every item it sells, with its count and price.
PriceOfgives a price for a vending machine only whenplayerBuysistrue, because a machine does not buy from the player. (the price is the entry’sGetPrice().) BoughtandSoldfire after a trade really went through.Priceis the money that moved, taken from the balance before and after, so it matches what the player really paid or got.Countis how many were asked for, and for a vending machine it is always 1. A vending machine raisesBoughtonly. (they follow a successful gameTrade.BuyorTrade.Sell(and theTradeSpecialoverrides), or a successfulVendingMachine.Buy.)- Any other money change made by a handler or game script during the same trade is counted in
Pricetoo. - A trade made with
Traders.BuyorTraders.Sellraises its events when the trade is finished, and none if it is refused or cancelled. See Traders. - The framework can make trades with traders for you.
Traders.BuyandTraders.Sellbuy from or sell to a trader by id and item id, and give a reason when they refuse. The trade needs the game’s own slot objects, and those calls handle that. See Traders.
How PriceQuery works
The game asks for a trader’s price all the time: for price checks, for labels and for every trade. PriceQuery lets your handler change the price each time.
PriceQueryfires for every trader price the game works out. It also runs during a trader trade’s own price checks. (it is raised from a postfix on the game’sTrade.GetItemStackPrice.)- Handlers run in the order they were added, and each one sees the price the last one left. Each may set
Price. A value that is not a real number is ignored, and the price stays as it was. - After all handlers have run, a changed price is adjusted to fit the game’s rules. It is at least 1 OC for each unit (or the RM equivalent), at most 16,000,000, and rounded like the game does: OC to whole units, RM to 0.1. A handler can’t make an item free, because that minimum is the game’s own.
- With no
PriceQueryhandler, the framework does almost nothing on the game’s frequent price calls. An unchanged price is returned exactly as the game worked it out. PriceOfincludes the same adjustments, so it matches what the game charges.
Limits
PriceQueryis not raised for vending machine prices.- Inside a
PriceQueryhandler,Shops.PriceOfand the game’s own price calls give the price before any changes.PriceQuerydoes not run again inside itself. - During a trader trade, a
PriceQueryhandler can read and set the price, but can’t start a trader trade, and the framework’s money and item writes are refused too (see Traders).