API and Hooks
Peddler exposes a small API for macros and other modules, and fires namespaced hooks at every significant point in a shopping session.
Getting the API
Section titled “Getting the API”The same object is available two ways once the module is ready:
const api = game.modules.get('peddler').api;// orconst api = globalThis.Peddler;The API is assigned during the Foundry ready hook. To be sure the API exists before you touch it, use peddler.ready instead of ready.
Method reference
Section titled “Method reference”| Member | Signature | Notes |
|---|---|---|
version | getter | Returns the installed module version string, or null. |
openShop | openShop({ shopUuid, userId } = {}) | Async. Opens the vignette for the given shop actor UUID. userId defaults to the current user. Returns the vignette application, or null if entry was refused. |
openShopSettings | openShopSettings(shopActor) | Async. Opens the shop settings window for a shop actor, reusing the window already open for that actor. Returns the settings application. |
setupShop | setupShop(actor, archetypeId = null) | Async, GM only. Converts an actor into a shop, creates its dialogue journal, and returns the created journal page. Pass null for a blank tree. |
archetypes | getter | Returns the array of valid archetype id strings for setupShop. See Shop Archetypes. |
openTreeEditor | openTreeEditor(page) | Opens the Dialogue Tree Editor for a journal entry page. Brings an existing editor for that page to front. |
notify | notify(message, { type, timeout, permanent, anchor } = {}) | Shows a Peddler-styled toast and returns { dismiss }. Shorthands: notify.info, notify.success, notify.warn, notify.error. |
getTrust | getTrust(shopActor) | Returns { key, value, steps } for the shop archetype’s trust counter, or null when the actor is not a shop. steps is the archetype’s ladder of rung values. |
setTrust | setTrust(shopActor, value) | Async. Sets the shop’s trust counter to an absolute value, routed to the primary GM. Returns { ok: true, value } when the value is already set, or { ok: false, reason: 'validation' } for a non-shop actor or a non-numeric value. |
runRestock | runRestock(shopActor, options = {}) | Async. Runs a restock cycle for a shop actor. Routes to the primary GM, so a player caller needs ownership of the actor. Returns the restock result, or { ok: false, reason }. |
getShopConfig | getShopConfig(actor) | Returns the actor’s validated and normalized shop configuration, or null when the actor is not a shop. |
updateShopConfig | updateShopConfig(actor, changes) | Async. Merges changes into the shop configuration and writes it to the actor. Returns { ok: true, config }, or { ok: false, reason: 'validation', errors } when the merged result fails validation. |
setActorModifier | setActorModifier(shopActor, buyerActor, patch) | Async. Merge-patches one buyer’s entry in a shop’s per-actor price modifiers. The patch takes buy, sell, perItem keyed by item id with its own buy and sell, and a source string. Values must be zero or greater. Runs on the primary GM’s client; a player caller needs owner permission on the shop actor. Returns { ok: true }, or { ok: false, reason } with validation, permission, no-gm, or rollback. |
registry | getter | Registration surface for other modules. registry.registerPredicate(id, definition), registry.registerEffect(id, definition), and registry.registerFilter(id, definition) add entries usable in the Dialogue Tree Editor. Ids must be namespaced as <module-id>.<name>. An unnamespaced id or one that is already registered is refused and returns null. registry.ids() returns { predicates, effects, filters }. |
A registered effect definition takes { label, kind, args, apply } and an optional gmOnly. A remote effect runs its apply(args, scope, { user }) on the primary GM’s client and may return an outcome object. A client effect runs apply(args, scope) on the shopping player’s client. A local effect runs apply(args, scope) immediately, wherever the choice is taken, with no round trip to the GM; gmOnly has no effect on it. A gmOnly remote effect asked for by a player is refused.
Hook reference
Section titled “Hook reference”All hook names are prefixed with peddler.. Payloads are a single object argument unless noted.
| Hook | Fires when | Payload |
|---|---|---|
peddler.ready | The module API has been assigned. | The API object itself. |
peddler.preOpenShop | Before a vignette opens. Return false from a listener to cancel the open. | { shopActor, userId } |
peddler.openShop | The vignette is created, before its first render. | { shopActor, userId, sessionId } |
peddler.sessionStart | The vignette has rendered and the session is live. | { session } |
peddler.nodeEnter | The walker enters a node. | { session, node } |
peddler.nodeExit | The walker leaves a node through a choice. | { session, node, choice } |
peddler.choiceMade | The player picks a choice, including free-text matches. | { session, choice } |
peddler.preTrade | Before a trade is priced and committed, after its lines are validated. Return false from a listener to cancel the trade. | { shopActor, buyerActor, lines, user } |
peddler.trade | A trade commits successfully. | { shopActor, buyerActor, summary } |
peddler.tradeRollback | A trade fails mid-commit and its document changes are undone. | { shopActor, buyerActor, reason, lines, total } |
peddler.sessionEnd | The session ends. | { session, reason } |
peddler.shopOpened | World time advances past a scheduled shop’s opening hour. Primary GM client only. | { actor, time } |
peddler.restock | A shop restock cycle completes. Primary GM client only. | { actor, restocked, added, refilled, deleted, unresolved } |
A peddler.preTrade listener may mutate the lines array. A line whose price is set to { abbr, amount } uses that value in place of the item’s base value, and still passes through the shop’s price modifiers. Lines are re-validated after the hook, so a listener that empties or corrupts the cart fails the trade with validation.
Session hooks fire on the shopping player’s client. Trades commit on the primary GM’s client over Foundry’s query system, so peddler.trade and peddler.tradeRollback fire there. Treat these two hooks as the trade integration point; the underlying queries are internal and not public API. A macro that reacts to a trade should account for running on that one client.
The trade summary is { added, sold, total, currency }, where added and sold are arrays of { name, qty, uuid, itemId } rows. uuid is the source item and itemId is the id of the item created on the receiving actor, or null when none was created.
On peddler.restock, added counts the items actually created on the shop actor and unresolved counts table results that pointed at a missing document or something other than an Item. The rollback lines are the priced trade lines and total is the priced trade total.
A choice in the Dialogue Tree Editor can also fire a custom hook under the peddler. prefix through its effect list, with an author-defined payload.
Trade outcomes
Section titled “Trade outcomes”Transaction nodes resolve to one of four outcome strings:
successinsufficient_fundsout_of_stockcancelled
The tree routes on the outcome. When a Transaction node has no dedicated choice for insufficient_funds or out_of_stock, the walker falls back to its cancelled choice. A peddler.preTrade listener returning false also resolves the transaction as cancelled.
System and theme integration
Section titled “System and theme integration”System support ships inside the module; there is no adapter registration API. See System Adapters for what each system integration covers.
Peddler requires 3DS Atlas. It registers itself with Atlas for shared theming under the .peddler scope, routes its console output through the Atlas logger, and reads the primary GM from Atlas to decide which client runs automation and commits trades. Atlas owns the window frames and the base palette of every Peddler application. See Themes and Chassis.