Files
runicnpc-rust/plugin.toml
wtclaude f9ebc5f25b
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in 8s
feat: API 6, loot tables, crates and the corpse's start and time (stage 7)
A profile's `loot` block (D290-D301):

- the corpse's start: Rust's scientist loot (the default), the kit it
  carried, or nothing at all, clothes included (D290, D300);
- a table of rows that always roll, each with its chance and amount,
  and a pool that draws at most `pick` rows by weight, with a "nothing"
  weight, so a kill never pays out more than the cap (D291);
- the table into Rust's wooden box, military crate, elite crate or
  hackable locked crate instead of the corpse, with Rust's loot and
  refresh off; it stays until emptied (D292, D301);
- a locked crate's hack time, through its starting count (D297);
- the corpse's time: Rust's own, seconds, or none (D294);
- `dropTable`, for an event step that switches the table off (D296).

The corpse is filled in OnCorpsePopulate, which answers with the corpse
for a kit or empty start so Rust's ApplyLoot is skipped: ApplyLoot is
protected on Oxide and public on Carbon, so no one override fits both.
A kit start takes the items as the NPC dies, because Rust has emptied
its inventory by the time the corpse is filled.

The harness's s7 group (25 checks): refusals, about 100 kills read back
against the always-rows, the chance, the pool's weights and its cap,
each start, both crates and the locked crate's timer, the corpse's time
and the event switch. 25/25 on both rigs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-05 22:35:42 -05:00

58 lines
3.4 KiB
TOML

# Release metadata for RunicNPC.
#
# Consumed by the release workflow, which folds these values into the
# manifest.json shipped inside the release tarball. The Runic Gateway installer
# and the Pterodactyl egg read that manifest to decide what they are placing
# (docs/runicnpc/PLAN.md D224), and the bridge will read the same `api` at hello
# (stage 4).
#
# There is deliberately NO version key here. The release version is derived from
# git tags and conventional commits by the release workflow, so there is no bump
# commit to keep in sync and no way for this file to disagree with the tag.
# ── The API version other plugins call ───────────────────────────────────────
#
# The number a caller of `RunicNpc_*` relies on (PLAN.md §4). It MUST equal
# `ApiVersion` in plugin/RunicNPC.cs; `node scripts/checkPlugin.js` holds the two
# equal on every pull request. It moves when a call or a raised hook changes
# shape, not on every release.
#
# The plugin answers this at run time through `RunicNpc_ApiVersion()`, but only
# once a server has booted with it loaded — too late for an installer to refuse
# a RunicNPC too old for the bridge it is pairing with. Declaring it here is what
# lets a bundle check the pair BEFORE an operator installs it.
#
# 1 was stage 0's: `RunicNpc_ApiVersion()` and nothing else.
# 2 was stage 2's whole API, PLAN.md §4.
# 3 was stage 4 (D249): RunicNpc_AddPlacement, _RenamePlacement, _RespawnPlacement and the
# OnRunicNpcPlacementChanged hook.
# 4 was stage 5: RunicNpc_Factions, _SetFactions, _Escort, _Ally, _Tether, the profile's stage 5
# fields, a placement's tether, and the OnRunicNpcEscortEnded hook.
# 5 was stage 6: the profile's `boss` and `use` blocks and the passive role, the hooks
# OnRunicNpcBossSpawned, _BossPhase, _BossDied and OnRunicNpcUsed, and `role` and `boss` in RunicNpc_List.
# Current: 6 — stage 7: the profile's `loot` block (the corpse's start, a table of always-rows and a capped
# pool, a crate, a locked crate's hack time, the corpse's time, and `dropTable` for one spawn's override),
# documented in docs/runicnpc/API.md.
api = 6
# ── Framework floors ─────────────────────────────────────────────────────────
#
# The same file runs on Oxide and Carbon; the installer and the egg decide
# whether it lands in `oxide/plugins/` or `carbon/plugins/`. These are the builds
# it is known good on — the two rigs it was loaded on — not a measured minimum.
# (The bridge's Oxide floor is older, 2.0.7585; RunicNPC has never run on that.)
min_oxide_version = "2.0.7726"
min_carbon_version = "2.0.259"
# ── Plugins it cannot load without ───────────────────────────────────────────
#
# Kits is how every RunicNPC NPC is equipped, and it is required (D217). The
# plugin says so itself with `// Requires: Kits`, which stops either framework
# loading it without Kits; this list is the same fact for the installer's
# `doctor`, which reports a missing one rather than installing it. The PR check
# holds this list and the plugin's `// Requires:` lines equal.
#
# ZoneManager is NOT listed: a zone tether is optional (PLAN.md §6). A placement
# or an event step that asks for one on a server without it is refused (D272).
requires_plugins = ["Kits"]