docs(runicnpc): stage 7 built and walked; API 6 and the dropLoot switch

- runicnpc/API.md: version 6, the profile's loot block and a spawn's
  loot.dropTable override.
- rust-link/PROTOCOL.md: §19.15, world.place's dropLoot.
- runicnpc/PLAN.md: stage 7's "Built" section. It covers the builds it
  was tested on (Rust 25681086, Oxide 2.0.7801, Carbon 2.0.262), the
  harness (s7 25/25, all 270/270, both rigs) and the walk on both rigs
  through the site. It also lists what building it found: Rust's
  ApplyLoot after the hook, and the inventory already emptied when the
  hook runs.

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-06 01:43:15 -05:00
parent 192eddb4b1
commit 846119220e
3 changed files with 90 additions and 5 deletions

View File

@@ -1414,6 +1414,52 @@ without a client, so the walk checks it. An unhacked locked crate is removed aft
1. **A "nothing" corpse and the clothes it wore. → D300:** truly empty, clothes too.
2. **How long an unopened crate lasts. → D301:** until it is emptied, as Rust's crates do.
**Built (2026-10-06), three branches and this one.** RunicNPC API 6 (`runicnpc-rust` `feat/stage-7`), the bridge
(`Rust-Plugins` `feat/runicnpc-stage7`) and the site (`Module-Rust` `feat/runicnpc-stage7`). The API is
[API.md](API.md) version 6; the wire is [`PROTOCOL.md`](../rust-link/PROTOCOL.md) §19.15.
| Piece | What it does |
|---|---|
| RunicNPC API 6 | The profile's `loot` block: the corpse's start (`rust`, `kit`, `none`), the always-rows, the pool with its picks and "nothing" weight, the crate and a locked crate's hack time, the corpse's time and `dropTable`; checked on load (items that exist, at most 30 rows, the table fits its crate or the corpse). The corpse is filled in `OnCorpsePopulate`; a spawn's overrides can set `loot.dropTable` false |
| The bridge | `world.place` with a profile reads the step's `dropLoot`; off, it spawns with `{"loot":{"dropTable":false}}`. `runicnpc_api = 6` |
| The site | The profile form's Loot section (D295), checked in RunicNPC's words, whether an item exists left to RunicNPC on the push; the Place NPCs step's `dropLoot` switch (D296), on by default and sent only when off; "own loot" in the profile list |
**The builds it was tested on (checked against the latest, 2026-10-06):** Rust 2634.289.1 (buildid 25681086, the
latest public build), Oxide 2.0.7801 and Carbon 2.0.262 (both the latest releases).
**Tested.** The harness's `s7` group passed 25 of 25 on both rigs: each start, the always-rows over 100 kills against
their chances, the pool's cap and its "nothing" weight (bounds at 3.5σ), each crate, the locked crate's timer, the
corpse's time and the event override. `rnt.run all`: 270 of 270 on both rigs. Module-Rust: 494 server and 67 client
tests, and every `check:*` script.
**Walked, 2026-10-06, through a walk site, signed in to the admin panel in the browser.** No player was on the rigs,
so a probe plugin killed the NPCs as a stand-in player and read back what they left.
| Row | Oxide | Carbon |
|---|---|---|
| A loot profile made on the form (a kit start; scrap 25–50 and a sewing kit 1–2 always; a pool of one pick from a tarp and a propane tank; the corpse for 120 s), saved and pushed; the rig holds the block as typed, 100% stored as chance 1 | pass | pass |
| Placed by clicking the live map; the kill's corpse: the kit's revolver and its ammunition, the clothes it wore, scrap and a sewing kit in range, one pool item, none of Rust's scientist loot | pass | pass |
| The corpse there at 60 s and gone at 125 s | pass | pass |
| Edited to start with nothing and a military crate: the corpse truly empty, clothes too (D300), the table in the crate | pass | pass |
| Edited to a locked crate of 17 minutes (1,020 s, longer than Rust's 15): the count started at −120 and the crate was hacked at 901 of 900, on time | pass | pass |
| The military crate still there unopened 25 minutes later (D301) | pass | pass |
| An event's Place NPCs step with "drop loot" off: its NPC's corpse empty and no crate, where the placement's NPCs of the same profile dropped one | pass | — |
**Not walked:** what a player's screen shows for a locked crate set longer than 15 minutes, while its count is below
zero; it waits for the in-game walk with a player. The server's side of it is walked above.
**What building it found:**
- **Rust fills the corpse again after `OnCorpsePopulate`.** `CreateCorpse` raises the hook and then calls
`ApplyLoot` unless the hook answered with a corpse. A kit or empty start answers with the corpse; a `rust` start
answers nothing, so Rust's loot goes in as before and the table is added to it.
- **The NPC's inventory is already empty when the hook runs.** A kit start therefore takes the kit's belt and main
items in our NPC's `OnDied`, before Rust empties them, and moves them into the corpse in the hook.
- **A destroyed corpse compares equal to null in Unity.** The harness checks the corpse's removal with
`ReferenceEquals` and the entity's own destroyed flag.
- **The profile list did not say a profile had its own loot**, where a boss says "boss". Found on the walk and fixed
on the same branch.
### Stage 8 — On the map and in the app
Event NPCs and bosses on the live map (protocol 11's `map.live`), a live "left: 3/8" on the event page, and the same