Violet

Shop

On this page

Read and interact with the NPC shop dialog (CShopDlg) while it's open: list the items the NPC sells, buy and sell, and close the dialog.

Shop must be open

Every function here requires an NPC shop dialog to be open. When no shop is open, is_open() returns false, get_items() returns nil, and the action functions return false. Talk to a shop NPC first (see NPC).

Shop Item Structure

get_items() returns an array of objects describing the goods the NPC offers for sale (i.e. what you can buy):

PropertyTypeDescription
idnumberItem template ID
positionnumberCommodity index — pass this as index to buy()
countnumberStock quantity for the entry (nStock)
pricenumberUnit price in mesos (nPrice)
unit_pricenumberPer-charge unit price for rechargeables (dUnitPrice), else 0
max_per_slotnumberMaximum quantity per slot (nMaxPerSlot)
namestringReadable item name

Functions

core.shop.is_open() -> boolean

Returns true if an NPC shop dialog is currently open.


core.shop.get_items() -> table<shop_item> | nil

Returns the items the open NPC shop sells (CShopDlg::m_aSellItem). Returns nil if no shop is open. Each entry's position is the index used by buy().

lua
if core.shop.is_open() then
    for _, item in ipairs(core.shop.get_items()) do
        core.log(string.format("[%d] %s x%d - %d mesos",
            item.position, item.name, item.count, item.price))
    end
end

core.shop.buy(index: number, item_id: number, count: number, price?: number) -> boolean

Buys count of the commodity at index. index and item_id come from get_items() (position and id). price is the per-unit price; when omitted it's resolved from the matching shop entry. Returns true if the request was sent, or false (plus an error string) if no shop is open or the index couldn't be matched and no explicit price was given.

ParameterTypeDescription
indexnumberCommodity index (get_items().position)
item_idnumberItem template ID (get_items().id)
countnumberQuantity to buy
pricenumberOptional. Per-unit price; auto-resolved from the shop entry when omitted.
lua
-- Buy 100 of whatever sits at commodity index 4
local items = core.shop.get_items()
for _, item in ipairs(items) do
    if item.position == 4 then
        core.shop.buy(item.position, item.id, 100)
        break
    end
end

core.shop.sell(position: number, item_id: number, count: number) -> boolean

Sells count of the inventory item at slot position. Returns true if the request was sent, or false if no shop is open or a previous sell is still awaiting the server's acknowledgement.

ParameterTypeDescription
positionnumberInventory slot position of the item to sell
item_idnumberItem template ID
countnumberQuantity to sell
Quest / untradeable items

The server rejects (and may disconnect on) attempts to sell quest, not-for-sale, or cash items. Only sell items you know are sellable.


core.shop.close() -> boolean

Closes the open shop dialog. Returns true if a shop was open and the close was issued, false otherwise.

Example

lua
-- Restock mana potions, then sell off junk etc items
if not core.shop.is_open() then
    core.log_warning("No shop open")
    return
end

-- Buy 1000 mana potions if the shop carries them
local MANA_POTION = 2000059
for _, item in ipairs(core.shop.get_items()) do
    if item.id == MANA_POTION then
        core.shop.buy(item.position, item.id, 1000)
        core.log("Bought 1000x " .. item.name)
        break
    end
end

-- Sell every etc item (tab_id 4) in the bag
for _, item in ipairs(core.inventory.get_etc_items()) do
    core.shop.sell(item.position, item.id, item.count)
end

core.shop.close()