Shops
The key words MUST, MUST NOT, and MAY below are used as in RFC 2119.
Shops are list-driven menus in the city. There are eight canonical counters: six vendor/service counters, plus the shared Storage Counter bank and the Guild Counter (a quest desk, not a vendor). Each is its own scene.
The shared shopping loop
Every vendor counter follows the same shape (the diagram above): on open it builds its lists and draws them, the player navigates a selection with the d-pad (with a hold-to-repeat), confirm opens a yes/no (or quantity) modal, and a successful buy/sell runs the transaction and redraws. A successful transaction MUST update meseta and inventory before the display refreshes.
Counters
| Counter | What it does | Tabs | Scene |
|---|---|---|---|
| Item Shop | Consumables, materials, technique disks, and buy-back. | Items · Materials · Disks · Sell | scenes/2d/shops/item_shop.tscn |
| Weapon Shop | Weapons / armor / units by class & requirement. | Weapons · Armor · Units · Sell | scenes/2d/shops/weapon_shop.tscn |
| Tekker | Identify unknown weapons & grind weapons. | Grind · Identify | scenes/2d/shops/tekker.tscn |
| Photon Collector | Trade photon drops (not meseta) for grinders / crystals / materials. | — | scenes/2d/shops/photon_shop.tscn |
| Synthesis Shop | Craft items from recipes / materials. | Craft · Boards | scenes/2d/shops/crafting_shop.tscn |
| Blackjack | Gambling table. | — | scenes/2d/blackjack/blackjack_table.tscn |
| Storage Counter | The shared bank (GameState.shared_storage), cross-character. | Deposit / Withdraw × Items / Meseta | storage screen |
| Guild Counter | Accept / report quests (not a vendor). | — | guild_counter |
Naming notes. The Photon Collector's scene/script is named photon_shop (file-level drift only — the player-facing name is "Photon Collector"). The Synthesis Shop's code identifier is crafting_shop, but the player-facing name is "Synthesis Shop".
Technique disks are sold in the Item Shop's Disks tab — this is canonical. A separate standalone tech shop is redundant and slated for removal.
Buy affordance
The player MAY select any item on a counter to read its details. For any item they can't afford, can't fit, or don't meet the requirements for, the Buy action MUST be disabled — rendered greyed out with a reason on the row ("No room" / "Lv N req" / "Can't afford"). Because the unaffordable path is gated before confirm, the player MUST NOT be able to reach a rejection dialog at all: there is no "you can't buy that" pop-up to dismiss, only a disabled control with an inline explanation.
This shared check — a single _can_buy(item) -> {ok, reason} predicate plus the disabled-row rendering it drives — is slated to live on a planned ShopBase so every counter renders affordance identically. See docs/shop-dedup.md.
Implemented by
- item_shop.gd weapon_shop.gd tekker.gd photon_shop.gd crafting_shop.gd blackjack_table.gd storage.gd guild_counter.gd — the eight screens (each
extends Controltoday; a sharedShopBaseis planned). - shop_manager.gd (ShopManager) — transactions:
get_shop_inventory(),buy_item(),sell_item(). - shop_registry.gd (ShopRegistry) — shop definitions / stock (
get_shop(),get_all_shops()). - inventory.gd (Inventory) + character_manager.gd (CharacterManager) — the meseta + carried items a transaction reads / writes.