From 791ac75b145ff1aa9847f7a2a1d1bdaac5e08a3b Mon Sep 17 00:00:00 2001 From: wtclaude Date: Wed, 30 Sep 2026 01:49:48 -0500 Subject: [PATCH] =?UTF-8?q?docs(runicnpc):=20stage=203's=20design,=20D239?= =?UTF-8?q?=E2=80=93D242?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The org lead answered stage 3's four questions on 2026-09-30: - D239: a roamer may stand on a player-built floor (Rust's mesh covers it a moment after it is built, stage 2), with a warning in the answer. §5, §8 and stage 10 now follow it; stage 2's open item is closed. - D240: routes are recorded point by point (record, point, undo, save loop|back, cancel), with nothing drawn on screen. - D241: placements made in game are named -, renamable. - D242: /rnpc place and /rnpc here take key=value options in any order. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY --- README.md | 2 +- modules/rust/PLAN_REDESIGNS.md | 2 +- runicnpc/PLAN.md | 47 ++++++++++++++++++++++------------ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 57465e4..e51a1e7 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ requires it once it releases (D220). | Doc | What it covers | |---|---| -| [PLAN.md](runicnpc/PLAN.md) | **The plan** — what the 2026-09-30 spike found (route A, HumanNPC, NpcSpawn), the org lead's decisions D214–D238, the features, the API, the chat commands, and stages 0–10 with how each is tested and what each found | +| [PLAN.md](runicnpc/PLAN.md) | **The plan** — what the 2026-09-30 spike found (route A, HumanNPC, NpcSpawn), the org lead's decisions D214–D242, the features, the API, the chat commands, and stages 0–10 with how each is tested and what each found | | [API.md](runicnpc/API.md) | **The API** other plugins call (version 2): owners, every `RunicNpc_*` call, the hooks it raises, and the profile, placement and route shapes | ### `android/` diff --git a/modules/rust/PLAN_REDESIGNS.md b/modules/rust/PLAN_REDESIGNS.md index a1219f5..e155ae0 100644 --- a/modules/rust/PLAN_REDESIGNS.md +++ b/modules/rust/PLAN_REDESIGNS.md @@ -8,7 +8,7 @@ they can be read together. **Built so far:** §1, walked 2026-09-28 (§1.9); §5 rig walk still to come (§5.8, D209); §3, built and walked on the rigs and the site 2026-09-29, its in-game rows still to come (§3.4); §4, built 2026-09-29 (§4.1). **§6 was spiked on 2026-09-30, and the org lead chose neither route: Runic Gateway writes its own NPC plugin, RunicNPC, planned in -[`../../runicnpc/PLAN.md`](../../runicnpc/PLAN.md) (D214–D238), and the rest of this plan waits for it.** +[`../../runicnpc/PLAN.md`](../../runicnpc/PLAN.md) (D214–D242), and the rest of this plan waits for it.** This is a companion to [`PLAN_FIXES.md`](PLAN_FIXES.md) and [`PLAN.md`](PLAN.md). Where they disagree, this document is later and wins. Its decisions continue PLAN_FIXES' numbering at **D188**. diff --git a/runicnpc/PLAN.md b/runicnpc/PLAN.md index cd61e54..d9b394d 100644 --- a/runicnpc/PLAN.md +++ b/runicnpc/PLAN.md @@ -4,7 +4,8 @@ **Stage 0 closed 2026-09-30** (runicnpc-rust#1/#2, §9): v0.1.0 released and loaded on both rigs. D229–D230 were decided with it. **Stage 1 measured 2026-09-30** (§9): six answers on both rigs; D231 was decided with it. **Stage 2's design answered 2026-09-30:** D232–D238 (§0), which reshape stage 2 (§9). **Stage 2 built and tested -2026-09-30** on both rigs (§9); its API is [API.md](API.md). +2026-09-30** on both rigs (§9); its API is [API.md](API.md). **Stage 3's design answered 2026-09-30:** D239–D242 +(§0). RunicNPC is Runic Gateway's own NPC plugin for Rust servers, in its own repository, [`RunicGateway/runicnpc-rust`](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust). It runs on Oxide and @@ -52,6 +53,10 @@ architectural or design decision is implemented. | **D236** | **Respawn is chosen per placement:** `each` (the default: every NPC returns its delay after its own death) or `group` (none return until all are dead, then all return together). | One fixed rule. | | **D237** | **A deleted profile leaves its placements waiting.** Their NPCs despawn; the placements are kept and shown as "profile missing" in game and on the site; they spawn again if the profile returns. | Refusing the delete; deleting the placements with it. | | **D238** | **A profile's shape** is §2's, as the org lead approved it: `names`, `kits`, `prefab`, `role`, `movement`, `health`, `damageDealt`, `damageTaken`, `aimCone`, `ranges`, `visionCone`, `sleepDistance`, `healthThresholds`, in `data/RunicNPC/profiles.json` with the `managed` flag. Placements and routes have their own files beside it; the optional caps (D227) are in the plugin's config. Stages 5–7 add their own sections. | A smaller stage-2 profile, combat values deferred to stage 5. | +| **D239** | **A roamer may be placed wherever Rust's navmesh reaches, a player-built floor included, and the answer warns when it is one** ("this spot is on a player-built structure; if it is destroyed, the NPC falls back to the nearest navmesh"). Sentry-only stays the rule for a spot that is truly off the mesh. Stage 10 shrinks to pasted or custom prefabs and moving platforms (stage 2's finding). | Allowing it silently; keeping anything player-built sentry-only even where the mesh covers it. | +| **D240** | **A route is recorded point by point:** `/rnpc path record ` starts it, `/rnpc path point` adds where the admin stands (checked against the navmesh; a bad point is refused with the reason), `/rnpc path undo` drops the last, `/rnpc path save [loop\|back]` writes it, `/rnpc path cancel` discards it. Nothing is drawn on screen (D216). | The same flow with the points drawn on screen; a point dropped every few metres as the admin walks. | +| **D241** | **A placement made in game is named after its profile and a number** (`/rnpc place bandit` answers "Placed bandit-3"), and `/rnpc rename ` renames it. `/rnpc near` lists the names. | Bare numbers; the admin naming every placement. | +| **D242** | **`/rnpc place` and `/rnpc here` take `key=value` options in any order after the profile:** `count=`, `respawn=`, `mode=each\|group`, `move=wander\|monument\|route:`, `radius=`. Anything left out takes the profile's default. | `/rnpc place bandit 3 300 group route:gate`; `/rnpc place` then `/rnpc set`. | **Borrowing, not copying.** NpcSpawn states no licence at all, so its source grants us nothing and is read only as a description of *what* can be done in Rust. HumanNPC is MIT on uMod, which is GPL-compatible, but §1.2 rules out its @@ -290,10 +295,13 @@ permissions reach the site's permission manager through the inventory, like any | Command | Does | Permission | |---|---|---| -| `/rnpc place [count] [respawn]` | Places at the spot you are looking at, persistent | `runicnpc.place` | -| `/rnpc here [count]` | The same, where you stand | `runicnpc.place` | -| `/rnpc remove` | Removes the placement of the NPC you are looking at | `runicnpc.place` | -| `/rnpc near [radius]` | Lists placements and live NPCs near you | `runicnpc.place` | +| `/rnpc place [key=value ...]` | Places at the spot you are looking at, persistent, and answers with its name (D241). Options in any order (D242): `count=`, `respawn=` (seconds), `mode=each\|group`, `move=wander\|monument\|route:`, `radius=` | `runicnpc.place` | +| `/rnpc here [key=value ...]` | The same, where you stand | `runicnpc.place` | +| `/rnpc remove [placement]` | Removes a placement and its NPCs: the one named, or that of the NPC you are looking at | `runicnpc.place` | +| `/rnpc rename ` | Renames a placement (D241) | `runicnpc.place` | +| `/rnpc near [radius]` | Lists placements (by name) and live NPCs near you | `runicnpc.place` | +| `/rnpc path record ` · `point` · `undo` · `save [loop\|back]` · `cancel` | Records a route where you walk, point by point (D240) | `runicnpc.place` | +| `/rnpc path list` · `delete ` | Lists or deletes routes; a placement on a deleted route waits, as for a deleted profile (D237) | `runicnpc.place` | | `/rnpc info` | The NPC you are looking at: profile, owner, health, target, state | `runicnpc.place` | | `/rnpc profiles` | The profiles this server has | `runicnpc.place` | | `rnpc.profile ...` (console) | Edits a profile on a standalone server; refused when the site manages them (D221) | `runicnpc.admin` | @@ -305,8 +313,11 @@ permissions reach the site's permission manager through the inventory, like any cost warning (D227): how many RunicNPC NPCs the server now has and what stage 1 measured that number to cost. On the navmesh, the NPC roams, chases and fights -normally. Off it (a roof, inside a base, a pasted structure), a **stationary** profile is placed and a roaming one -is refused with the reason. An event step gets the same answer, as a blocked RaidableBases spot does (D208). +normally, and that includes a player-built floor, which Rust's mesh covers a moment after it is built (stage 2). +**On a player-built structure the placement is made with a warning** (D239): if the structure is destroyed, the +NPC falls back to the nearest navmesh. Off the mesh (a pasted structure, a custom prefab), a **stationary** profile +is placed and a roaming one is refused with the reason. An event step gets the same answer, as a blocked +RaidableBases spot does (D208). --- @@ -349,7 +360,8 @@ shipped no custom mesh. Where it does not reach, a profile is a sentry (§5). **Stage 10, only if needed:** a point graph recorded in game. An admin walks the route, `/rnpc mesh record ` samples it, and NPCs move between the points directly, as NpcSpawn's custom meshes do, for: -- pasted or player-built bases, and roofs; +- pasted structures, and roofs the mesh does not reach (a player-built floor needs none: Rust's mesh covers it + a moment after it is built, stage 2 and D239); - custom map prefabs Rust's mesh does not cover; - moving platforms, together with parenting. @@ -479,8 +491,8 @@ boots load the saved `proceduralmap....navmesh`. **Placements tha | A player-built floor 4 m up | **not on the mesh** in the frame it spawned; **on it 0.1–0.3 s later** (stage 2) | the same | | One check | 13.6 µs | 8.3 µs | -Monument roofs (Launch Site, Airfield, Trainyard, the warehouses) are mostly walkable. Player-built floors and -roofs never are: that is §5's sentry rule, and stage 10. +Monument roofs (Launch Site, Airfield, Trainyard, the warehouses) are mostly walkable. This stage read +player-built floors and roofs as never walkable; stage 2 corrected that (the row above), and D239 follows from it. **5. The cost (D227's numbers).** Seven 60 s phases on a field 400 m from any monument: a baseline, 1, 10 and 100 of ours idle, the same 100 shooting 20 stand-ins (whose damage the harness zeroes, so none die), a fresh 100 set to @@ -584,7 +596,7 @@ What building it found: - **Rust's navmesh covers a new player-built floor in 0.1–0.3 s** (2–3 frames), on both rigs. Stage 1's "a player-built floor is never on the mesh" (Q4) sampled in the same frame the floor spawned, so it is wrong: a roamer can stand on a player-built floor a moment after it exists. §5's sentry rule, §8 and stage 10 were - written on stage 1's reading. **Open for the org lead.** + written on stage 1's reading; the org lead answered with D239, and those sections now follow it. - **Rust's navmesh sampler reaches further down than across.** A roamer asked to stand on a roof found the ground 4.7 m below. A roamer's spot must now be within 2 m, up or down, of the navmesh it is put on. - **A brain can think before Unity has started it.** For that moment it has no navigator, so RunicNPC leaves that @@ -596,12 +608,15 @@ What building it found: ### Stage 3 — In game -The chat and console commands (§5), their permissions, the navmesh placement check, respawn delays, and recording -routes in game (`/rnpc path record`, then setting points, D234). A placement may name a movement override and a -respawn mode (D233, D236). +The chat and console commands (§5), their permissions, the navmesh placement check with D239's warning on a +player-built structure, respawn delays, and recording routes in game point by point (D234, D240). Placements made +in game are named after their profile and a number, and renamable (D241). `/rnpc place` and `/rnpc here` take +`key=value` options, a movement override and a respawn mode among them (D233, D236, D242). -**Tested by** a written in-game walk: place, remove, look-at info, respawn, record a route and place a patrol on it, -restart. **This is the first stage that needs a player on a rig.** +**Tested by** the harness for everything a console can reach (the commands' parsing, refusals, names, and the +route file a recording writes), then a written in-game walk: place, remove, rename, look-at info, respawn, record a +route and place a patrol on it, place on a player-built floor and destroy it, restart. **This is the first stage +that needs a player on a rig.** ### Stage 4 — Runic Gateway integration -- 2.49.1