Town Market — NPC Price Mode
Related: 10 — Economy & Markets, 37 — Economic map zones, 19 — NPCs, 08 — Inventory & storage.
1. Summary
Market-hall listings support two pricing modes:
| Mode | Meaning |
|---|---|
| Fixed | Seller sets unit copper ≥ 1 (player order book — 10 §4) |
| NPC price | Mode, not a copper value. Goods sit in hall escrow until buying NPCs sweep the dump queue |
NPC price is a convenience dump queue: players list loot once at the hall instead of visiting each merchant. Only NPCs purchase these listings. Players never buy NPC-price lots.
Sweeps are instant (no pathing). Eligible NPCs run on a per-NPC phase schedule (default morning + afternoon). Matching lots are bought FIFO per template. Sellers are paid each NPC’s normal buy price minus a per-NPC convenience fee. Crown hall sales tax does not apply to NPC-price sweeps (fee only).
2. Design principles
| Principle | Meaning |
|---|---|
| Mode, not quote | Listing stores NpcPrice; copper is resolved at sweep from that NPC’s buy table + rates |
| Dump queue only | Players cannot purchase NPC-price listings |
| FIFO | Same template: oldest listing first (listing_id / creation order) |
| Fee, not tax | Convenience fee on NPC-price sweeps; hall market_sales_tax_* stays for Fixed player buys |
| Instant sweep | Phase-enter edge trigger; no walk-to-hall choreography |
| Notify sellers | Log + toast when online; pending notices flush on join if offline |
| Economy sink | Bought goods leave the world (same dump-valve role as face-to-face NPC buys) |
3. Listing model
Escrow listing fields (conceptual):
| Field | Fixed | NPC price |
|---|---|---|
pricing |
Fixed { unit_price_copper } |
NpcPrice |
| Player buy | Allowed (bank + tax) | Forbidden |
| Reprice | Change unit copper | N/A (mode has no copper) |
| Delist | Return goods | Same |
List flow at clerk: source → stack → qty → pricing mode → (if Fixed) unit copper → submit.
Browse labels: Fixed shows copper; NPC price shows “NPC price”. Seller can delist own NPC-price lots. Enter/buy on NPC-price lots is rejected for players.
4. NPC economy authoring
On NPC definition economy (content-admin NPCs tab + YAML):
| Field | Default | Meaning |
|---|---|---|
buy_rate / sell_rate |
0.5 / 1.25 | Existing face-to-face rates |
market_convenience_fee_bps |
500 (5%) |
Deducted from NPC buy price on hall sweeps |
market_buy_phases |
[morning, afternoon] |
World-clock phases that trigger a sweep on phase enter |
market_buy_pct |
25 |
Percent of each matching listing’s remaining qty bought per visit |
market_buy_all_at_most |
4 |
If remaining ≤ this, buy the entire listing this visit (skips pct). 0 disables |
market_buy_max_qty_per_visit |
null |
Optional hard cap per listing per visit |
market_buy_enabled |
true |
When false, wishlist/shop only — no hall sweeps |
Eligibility for a template: market_buy_enabled and the template has base_value_copper > 0 (any listable valued item). NPC buys[] still supplies fixed-coin overrides when present.
Halls in scope: market halls in the region whose zone-share rules include the listing (10 §4.2).
5. Sweep (phase enter)
On world-clock phase change, for each NPC whose market_buy_phases contains the new phase:
- Collect NPC-price listings whose template is on this NPC’s buy list (zone-visible halls).
- Group / order by template, then FIFO (ascending listing id / creation).
- For each listing, buy
- if
market_buy_all_at_most > 0andremaining ≤ market_buy_all_at_most:qty = remaining - else
qty = min(remaining, max(1, floor(remaining × market_buy_pct / 100)), max_cap_or_∞). Unit pay =npc_buy_price_copper(...)after convenience fee (integer divide). If the pre-fee unit is 0, skip. If the post-fee unit would be 0 but the pre-fee unit is at least 1, pay 1 copper (cheap stacks still move).
- if
- Credit seller bank for
unit × qty(NPC treasury / mint — same inflation model as shop sells). - Sink goods; reduce or remove listing; ledger (
MarketSell/ fee category as implemented). - Queue seller notice (see §6).
Multiple NPCs in the same phase: process NPCs in stable id order. Each sees remaining qty after prior NPCs.
Empty market_buy_phases → no sweeps (face-to-face shop still works).
6. Seller notifications
| State | Delivery |
|---|---|
| Online | Interaction / game log: {NpcLabel} bought {qty}× {ItemLabel} at market for {copper}. |
| Toast | Success toast from that log line (gfx feedback classifier) |
| Offline | Persist pending_market_notices on character; flush to log/toast on join (same pattern as pending bank credits) |
7. Settlement vs Fixed buys
| Fixed (player buyer) | NPC price (NPC sweep) | |
|---|---|---|
| Buyer | Player bank debit | NPC treasury (no player debit) |
| Seller | Bank credit − crown tax | Bank credit − convenience fee only |
| Goods | To buyer dest | Sunk |
Tax zone market_sales_* |
Applies | Does not apply |
8. Client UX
| Step | Behavior |
|---|---|
| List | After qty: choose Fixed or NPC price; Fixed still prompts for copper |
| Browse | NPC-price rows show “NPC price”; buy confirm not offered / rejected for players |
| Delist | Own Fixed and NPC-price lots |
| Sale | Log + toast (§6) |
Prefer item / NPC labels over raw ids.
9. Content-admin & designer notes
- NPCs tab: economy fields in §4 (fee, phases, pct, clear-at-most, max qty, enabled).
- Example content: enable sweeps on town buyers (Ada, blacksmith, butcher, cook) with defaults.
- Designer note:
docs/player-markets.md(NPC-price dump queue + fee vs tax).
10. Design notes
NPC-price mode keeps the open player book honest while giving a one-stop dump for loot that merchants already want. FIFO protects earlier listers when several players dump the same template. Instant sweeps keep v1 simple; walk-to-hall theater is out of scope.