2 npc services
forgejo-actions edited this page 2026-07-11 10:33:50 +00:00

NPC Services

What This System Is

NPC services turn an NPC interaction into an overlay of shop, crafting, or direct service actions. They are authored in assets/npc/npc_service_catalog.json and linked from NPC interaction slots through service event IDs.

Every service ID uses this shape:

npc_service:<npc>|<service>

Examples:

  • npc_service:merchant|shop
  • npc_service:blacksmith|forge
  • npc_service:healer|heal
  • npc_service:innkeeper|inn
  • npc_service:toolsmith|shop

How Authors Use It

The NPC part must match the owning NPC interaction. Validation rejects malformed IDs, empty parts, and non-quest NPC interactions that point at missing service definitions.

Authoring Schema

Each service definition has:

  • event_id: the full npc_service:<npc>|<service> ID.
  • title: overlay title.
  • summary: short overlay description.
  • kind: shop, service, or quest.
  • vendor_stock_id: optional vendor stock source.
  • crafting_recipe_ids: optional crafting recipe sources.
  • entries: optional direct service entries.

Direct entries have:

  • id
  • label
  • description
  • availability_conditions
  • cost_items
  • effects
  • unlock_ids
  • event_ids
  • relationship_delta

Entry IDs are resolved case-insensitively when a player selects an overlay action.

Overlay Entry Sources

A service overlay can gather entries from three sources:

  • Direct entries from the service definition.
  • Vendor stock entries from vendor_stock_id.
  • Crafting recipes listed in crafting_recipe_ids.

The projection path resolves those sources into one overlay list. Prepared service catalogs index the same three entry kinds so repeated overlay builds and selected-entry lookups can reuse the prepared data when the catalog sources still match.

Rules And Invariants

Costs come from the selected entry source:

  • Direct entries use cost_items.
  • Vendor entries use their stock entry cost_items.
  • Crafting entries use recipe input_items.

Availability conditions use NPC-state condition tokens. If the condition parser cannot evaluate the condition or the NPC context is missing, the option is treated as unavailable rather than accepted optimistically.

Effects are projected into gameplay operations, including scene variables, quest flags, party tags, inventory deltas, reputation deltas, unlocks, runtime events, and relationship deltas. Cost items are applied as negative inventory deltas as part of the selected entry transaction.

Shipped Services

The current service catalog includes:

  • merchant|shop: Traveling Wares, a shop backed by vendor stock merchant_shop_core.
  • blacksmith|forge: Forge Services, a service backed by recipes temper_blade and reforge_edge.
  • healer|heal: Healing Services, direct entries bind_wounds and restore_spirit.
  • innkeeper|inn: Inn Services, direct entries rent_room and home_cooked_meal.
  • toolsmith|shop: Starter Tool Shop, a shop backed by vendor stock vendor.tools.starter.

Use the full npc_service:<npc>|<service> form in NPC interactions; the shortened forms above are only for compact documentation.

NPC catalog interaction slots link to services by setting their interaction event_id to the service ID. For example, the merchant shop interaction points at npc_service:merchant|shop, while the blacksmith forge interaction points at npc_service:blacksmith|forge.

Validation enforces two important ownership rules:

  • The service must exist for non-quest service interactions.
  • The service owner NPC in the ID must match the NPC that exposes the interaction.

This keeps overlay actions from silently opening another NPC's shop or applying service effects under the wrong relationship context.

Local Vs Server Ownership

Local preview and offline flows may call the local service authority helper directly. That helper exists for editor and preview simulation.

Authoritative runtime paths must submit gameplay action requests instead. The client queues service overlay and entry requests when realtime is available, and only falls back to local preview behavior when that mode is allowed. The game server resolves the selected NpcServiceOverlay or NpcServiceEntry, loads authoritative inventory and currency state, checks availability and duplicate-output rules, then commits costs and effects through gameplay authority.

In practice: authors can preview services locally, but player-owned inventory, currency, quest, and service outcomes belong to the server.

Validation And Debugging

Run the shared bake diagnostics after editing assets/npc/npc_service_catalog.json or the NPC interactions that reference it:

cargo run --bin aether-bake -- --fail-on-diagnostics

If an overlay does not open, check the service ID shape, the owning NPC id, referenced vendor stock or recipe ids, and availability conditions before investigating runtime transport.

Examples

  • Use the full npc_service:<npc>|<service> ID in both the service catalog and NPC interaction.
  • Keep the NPC ID portion equal to the owning NPC.
  • Choose shop for vendor-stock overlays, service for direct or crafting service overlays, and quest only for quest-owned service flow.
  • For vendor services, verify the vendor_stock_id exists in game data.
  • For crafting services, verify every recipe ID exists in game data.
  • For direct entries, keep id stable because it is the selected overlay action key.
  • Express costs in cost_items for direct entries, or let vendor stock and recipe definitions provide their own costs.
  • Add availability conditions only when they can be evaluated from NPC/service context.