docs(runicnpc): stage 7 decisions D290-D299

Loot: the corpse's start is the profile's (Rust's scientist loot, the kit,
or nothing) with its table on top; a table is always-rows plus a pool
capped at N picks; an optional crate, the locked one included, with the
profile's hack timer; anyone loots; the corpse's time is the profile's;
one table per profile, edited in the data file without a site; an
event's Place NPCs step switches table loot; one stage, spike first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-05 19:43:36 -05:00
parent 4910802367
commit 0fbfbed41f

View File

@@ -11,7 +11,7 @@ design answered 2026-09-30 and 2026-10-01** (D253–D266, §0), **its spike meas
and **its build's own questions answered 2026-10-01** (D267–D272). **Stage 5 built and tested 2026-10-01, walked on the
site 2026-10-05** on both rigs (§9); its API is [API.md](API.md) version 4. **Stage 6's design answered
2026-10-05** (D273–D282, §0), **its spike measured 2026-10-05** on both rigs, and **its two questions answered the
same day** (D283, D284, §9). **Its build's own questions were answered the same day too** (D285–D289), and **stage 6 was built and walked on the site 2026-10-05** on both rigs (§9); its API is [API.md](API.md) version 5.
same day** (D283, D284, §9). **Its build's own questions were answered the same day too** (D285–D289), and **stage 6 was built and walked on the site 2026-10-05** on both rigs (§9); its API is [API.md](API.md) version 5. **Stage 7's design answered 2026-10-05** (D290–D299, §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
@@ -110,6 +110,16 @@ architectural or design decision is implemented.
| **D287** | **A boss's adds fight on after it dies**, until they are killed. They belong to whoever owns the boss, so an event's teardown removes them with it (stage 6). | Adds die with the boss; adds stop fighting and despawn after 60 s. |
| **D288** | **A passive NPC moves as its profile says**: it can stand, wander or walk a route like a roamer, and it never fights (stage 6). | Always standing at its spot, like a sentry. |
| **D289** | **The four example profiles (D280, D284):** a raider (roamer, wanders 40 m, 150 hp, semi-auto rifle); a camp guard (guard, chases 30 m, 200 hp, Thompson, metal facemask and chest plate); a sniper (sentry, sees 120 m, 120 hp, bolt-action rifle); and the Juggernaut (roamer and boss, wanders 30 m, 2,500 hp, M249, heavy plate). The Juggernaut has a phase at 50% (summons 3 raiders: "The Juggernaut calls for help!") and one at 25% (damage ×1.5, speed ×1.3: "The Juggernaut is enraged!"). Its spawn line is "The Juggernaut has risen!", its death line "The Juggernaut has fallen.", and its bar shows within 100 m. Item names are checked on the rig; one Rust does not know is replaced by its nearest match (stage 6). | Weaker starters (revolver, Thompson, hunting bow; a 1,500 hp boss). |
| **D290** | **What a corpse starts with is the profile's choice:** Rust's own scientist loot (the default, as today), the kit the NPC wore, or nothing. **Its loot table is added on top** (stage 7). Today a RunicNPC corpse holds only Rust's scientist loot, from the prefab's loot slots; a scientist never copies its inventory, so the kit never drops. | The table only; always the kit plus the table. |
| **D291** | **A loot table has two parts:** rows that always roll, each with its own chance and an amount range, and **a pool that picks at most N rows by weight**, with an optional "nothing" weight. The pool is the cap: however lucky the roll, it never pays out more than N, so a kill cannot drop every rare item at once (stage 7; the org lead asked for loot "not too generous but still fair"). | Independent chances only; a weighted pool only. |
| **D292** | **A profile may put its loot table into a crate instead of the corpse:** Rust's wooden box, military crate, elite crate, or the hackable locked crate (stage 7). | Those crates without the locked one; no crates this stage. |
| **D293** | **Anyone may loot**, as in Rust: whoever reaches the corpse or crate first (stage 7). | The players who damaged it first, for a time; the killer first, for a time. |
| **D294** | **How long the corpse stays is the profile's:** Rust's default, a number of seconds, or none at all (sensible when the loot goes into a crate) (stage 7). | Always Rust's default. |
| **D295** | **Each profile carries its own loot table.** The site edits it with the profile, but **RunicNPC is a first-class plugin and does not depend on the website** (stage 7, the org lead). | Named tables shared between profiles. |
| **D296** | **An event's "Place NPCs" step decides whether its NPCs drop their loot table**, with a switch that is on by default (stage 7). An event's own reward steps are separate (D285). | Event NPCs drop loot as anywhere; event NPCs never drop table loot. |
| **D297** | **The locked crate's hack timer is the profile's**, Rust's own 15 minutes by default (stage 7). | Always Rust's 15 minutes. |
| **D298** | **On a server with no website, a loot table is edited in the data file** (`data/RunicNPC/profiles.json`) and read again with `rnpc.reload`. No new in-game commands (stage 7). | `rnpc.loot` verbs; JSON through `rnpc.profile set`. |
| **D299** | **Stage 7 is one stage, opening with a spike on both rigs, walked once end to end**, as stages 5 and 6 were (D253, D282) (stage 7). | 7a (the table and corpse) and 7b (the crates), each walked and merged before the next. |
**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
@@ -404,9 +414,11 @@ have, is refused when it is set.
## 7. Loot (D218)
A profile's loot table: items with chances and amounts, optionally clearing the corpse's default loot, dropping a
crate, or removing the corpse. Tables are authored on the site with the profile. Adapters to AlphaLoot and the
others are a later stage and not planned in detail here.
A profile's loot table (D290–D298): rows that always roll, each with a chance and an amount, and a pool that picks
at most N rows by weight. The table is added to what the corpse starts with (Rust's scientist loot, the kit, or
nothing), or goes into a crate instead, the hackable locked crate included. The profile also says how long the
corpse stays. Each profile carries its own table; the site edits it with the profile, and a server with no site
edits the data file. Adapters to AlphaLoot and the others are a later stage and not planned in detail here.
---
@@ -1324,7 +1336,25 @@ server's own boot.
Loot tables authored on the site, the corpse's default loot cleared or kept, a crate on death, corpse removal.
**Tested by** harness kills whose corpses are read back, 100 times each, against the table's chances.
The org lead's answers on 2026-10-05 are D290–D299. **It is one stage, opening with a spike, walked once end to end
(D299).** Its wire changes join protocol 13 while it is unreleased.
- **The spike first (D299).** A harness answers what the rest depends on, on both rigs:
- where a corpse's loot is decided: which hook Oxide and Carbon raise for an NPC corpse being filled, and whether
our subclass can fill it itself (`ApplyLoot`, `CopyInventoryToCorpse`) for D290's three starts;
- the crates (D292): spawning each of Rust's crates at a death spot, emptying it and filling it, and that it
behaves as Rust's own (lootable, despawns);
- the locked crate (D297): whether its hack timer can be set per crate, since Rust's is one server-wide setting;
- removing a corpse after a set time, or at once (D294).
- **RunicNPC (API 6):**
- the profile's `loot` block: the corpse's start (D290), the table (D291), the crate and its timer (D292, D297)
and the corpse's time (D294);
- an override for one spawn that switches the table off, for an event step (D296).
- **Rust-Plugins (the bridge):** `world.place` with a profile takes the step's "drop loot" switch (D296).
- **Module-Rust:** the profile form's loot section (D295) and the Place NPCs step's switch (D296).
**Tested by** harness kills whose corpses and crates are read back, 100 times each, against the table's chances
and the pool's cap; and a walk on both rigs.
### Stage 8 — On the map and in the app