ADR-0014 — NPC framework: AI and pathing approach¶
Status: Proposed Date: 2026-07-31 Supersedes: — Superseded by: —
Context¶
Legacy left this almost entirely unbuilt: items/base/npc.lua exists as a stub base class with
no AI (Legacy/01_FEATURE_INVENTORY.md).
There is nothing to port and nothing to preserve — this is the largest single piece of new
design work named anywhere in ROADMAP.md's Milestones 12–18, which is why it is sequenced
last (Milestone 18) and why it gets its own ADR before any code, per
00_CONSTITUTION.md §4.
Why this is riskier than everything else in Milestones 12–18. Every other new module in this
batch composes existing, already-proven mechanisms (Ownership, Economy, Interaction,
Needs). An NPC framework needs pathing/navmesh, which no part of this codebase has ever
touched, and which is a genuinely unverified S&box engine surface — the same category of risk
ROADMAP.md's Verification Debt section already tracks for Applejack.sbproj's other
untested-in-editor assumptions.
What already exists to build on. PawnComponent/IPawnLocator
(22_PLAYER_PRESENCE_AND_ADMIN_TOOLS.md §1)
is the only precedent in this codebase for binding any entity to a world Transform. Whether
an NPC reuses PawnComponent directly or needs its own non-player variant is itself part of
this decision.
Decision¶
Not yet decided — open to resolve, and deliberately not attempted without an editor spike first (see Notes):
- Pathing mechanism. S&box's native navmesh/pathfinding support (if any) versus a simpler
waypoint-graph authored per map, closer to legacy's
prisonpoints/spawnpointsprecedent (Legacy/13_DEPENDENCY_GRAPH.md §1) of map-authored point data. The waypoint approach is lower-risk and matches an existing authoring pattern in this codebase; native navmesh is more capable but entirely unverified here. - Does an NPC reuse
PawnComponent, or is aPawnComponentfundamentally player-shaped (tied to aConnection) such that NPCs need their own component implementing a shared locomotion interface instead? This determines whether Milestone 18 is additive toMovementor introduces a parallel system. - Behaviour model. A minimal state machine (idle/patrol/react) versus something more general (behaviour trees). Given this project's stated preference for the simplest thing that covers the real cases (00_CONSTITUTION.md), a state machine is the likely starting point, but the real gameplay consumer (see Decision point 4) should drive this, not the other way around.
- The first real consumer.
ROADMAP.md's Milestone 18 build item names two candidates: a patrol NPC, or upgrading Milestone 14's static Vendor to be NPC-driven. Whichever is chosen should be the only thing built first — this ADR should not be read as licence to build a general NPC framework speculatively ahead of a real consumer, the same discipline every other module in this codebase has held itself to.
Alternatives considered¶
Skip pathing entirely — stationary NPCs only (dialogue/vendor-style), no movement¶
Would let Milestone 14's Vendor upgrade happen without touching pathing at all, and defers the actual "NPC framework" (something that patrols, reacts, moves) indefinitely. Not rejected — genuinely worth considering as a smaller Milestone 18 if the pathing risk turns out to be as large as expected. Recorded here so it is chosen deliberately if it's chosen, not backed into.
Use a third-party pathing library/package¶
Would sidestep verifying S&box's native support. Rejected as a default: this project has no established pattern for third-party dependencies of this kind, and ADR-worthy dependencies need their own justification per the ADR README's own "introduces a third-party dependency" trigger — a separate decision, not bundled into this one.
Consequences¶
Positive¶
- Closes the last row in
Legacy/01_FEATURE_INVENTORY.md's "Not present at all" table. - Forced to attach to a real consumer (per Decision point 4), which keeps this from becoming speculative infrastructure with no exercised behaviour — the same trap the Plugin System plan explicitly called out for its own extension points before Phase 1 hardened them.
Negative¶
- Be honest: this ADR cannot be moved to Accepted, and Milestone 18 cannot start for real, without an editor spike to confirm what S&box's pathing surface actually offers. That spike is real, unbudgeted work with an unknown outcome — the most honest thing this ADR can say is "we don't yet know how expensive this is."
- Whichever pathing mechanism is chosen becomes a second locomotion concept alongside
PawnComponent's player-driven one unless Decision point 2 resolves toward reuse — real ongoing maintenance cost either way.
Neutral¶
- Nothing else in Milestones 12–17 depends on this landing, by design — see
ROADMAP.md's Milestone 18 sequencing note.
Compliance¶
- No implementation starts before the editor spike named in Notes below has actually run and its findings are recorded in this ADR's Notes section.
- Any
[Rpc.Host]surface an NPC framework adds (e.g., an admin "spawn NPC" command, followingDevMenuPanel's existing item/job spawn precedent) is walked against the exploit checklist.
Notes¶
Must happen before this ADR can move to Accepted: an S&box editor spike answering, at
minimum — does the engine expose native pathfinding, and if so, does it work against this
project's actual map geometry; can a non-Connection-bound GameObject be given a
PawnComponent-equivalent, or does one need to be built from scratch. Record the findings here,
not in a separate scratch document, so a future reader sees the reasoning in one place.
Revisit sequencing entirely if the editor spike shows pathing is significantly cheaper or more expensive than expected — this milestone's position as "last, because it's riskiest" is a judgement call made without that information, and should update once real information exists.