# Installing RunicNPC RunicNPC is Runic Gateway's own NPC plugin for Rust, on Oxide and Carbon. On a Runic Gateway server it is **required**: every NPC an event places is RunicNPC's, Rust's own scientists included (D310). It also runs on any Rust server on its own, driven by its `/rnpc` commands and by other plugins through its API. Every command is in [COMMANDS.md](COMMANDS.md), the API is in [API.md](API.md), and the design of record is [PLAN.md](PLAN.md). ## What it needs | | | |---|---| | **Oxide 2.0.7726 or Carbon 2.0.259**, or newer | The builds it was tested on. Its release manifest states them, and the installer checks them. | | **[Kits](https://umod.org/plugins/kits)** | **Required.** A profile equips its NPCs with Kits kits, and RunicNPC declares `// Requires: Kits`, so neither framework loads it without Kits. | | **[ZoneManager](https://umod.org/plugins/zone-manager)** | Optional. Only a tether (`tether=` on a placement, or an event's "keep inside the zone") uses it. | **Kits and ZoneManager are reported, never installed.** The installer and `doctor` say when either is missing, and you install them from uMod. Runic Gateway does not fetch third-party plugins. **Do not reload Kits while an event runs.** RunicNPC requires Kits, so both frameworks reload RunicNPC with it, and every NPC it had spawned is gone. Placements come back on their own; an event's NPCs do not (D283). ## On a Runic Gateway server There is nothing to do by hand. RunicNPC is part of the Rust **bundle**, the exact set of releases CI has checked together, beside the bridge plugin and the sidecar: - **The installer** (`install --game rust`, `update --game rust`) places `RunicNPC.cs` beside the bridge, checked against the bundle's checksum. It refuses a bundle without RunicNPC. `doctor --game rust` fails when RunicNPC is missing or was never installed, and warns when the file was edited by hand. `uninstall` removes `RunicNPC.cs` and keeps `data/RunicNPC/`. The installer's own guide is [../rust-link/INSTALL.md](../rust-link/INSTALL.md). - **The Pterodactyl egg** places it the same way on every install and reinstall. Once the server has started, **Admin → Rust → Servers** shows the server as complete. A server without RunicNPC, or with a RunicNPC older than the bridge needs, reads "Incomplete" with the reason, and every Place NPCs step on it is refused with "needs RunicNPC". **Admin → Rust → NPC profiles** shows each server's RunicNPC version and API. On such a server the website owns the NPC profiles and the faction table. It pushes them to RunicNPC, and the console commands that would edit them are refused. Placements stay on the server: they can be made in game with `/rnpc place` or from the site's map, and both see the same list. ## Without Runic Gateway 1. Download `runicnpc-.tar.gz` and `SHA256SUMS` from the [releases](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust/releases), and check the tarball: `sha256sum -c SHA256SUMS`. 2. Install Kits from uMod if the server does not have it. 3. Copy `runicnpc/RunicNPC.cs` from the tarball into `oxide/plugins/` or `carbon/plugins/`. The framework compiles and loads it at once. 4. In the server console: `rnpc.status`. It should say `navmesh=ready` (a fresh map builds it for several minutes after the first boot) and `swap fields: ... missing=- added=-`. On its first load RunicNPC writes four example profiles (a raider, a camp guard, a sniper and the Juggernaut boss) and their kits into Kits' data file, so a fresh server has something to place at once. Grant `runicnpc.place` or `runicnpc.admin` to whoever places NPCs, then `/rnpc place raider` where you look. **Do not create `data/RunicNPC/` yourself.** RunicNPC makes it on first load. A directory made from outside the game, for example in a panel's file manager, is not writable by the game. ## Its files | File | What it holds | Who writes it | |---|---|---| | `plugins/RunicNPC.cs` | The plugin. | The installer, the egg or you. | | `config/RunicNPC.json` | Caps (below) and the spawn budget. | You. | | `data/RunicNPC/profiles.json` | The profiles and the faction table. | The website on a Runic Gateway server (`"managed": true`); otherwise `rnpc.profile` and `rnpc.faction`. | | `data/RunicNPC/placements.json` | The placements. | `/rnpc`, the API, and the website's map. | | `data/RunicNPC/routes.json` | The recorded routes. | `/rnpc path`. | | `data/RunicNPC/state.json` | Its own bookkeeping. | RunicNPC. | After editing `profiles.json` or `routes.json` by hand, run `rnpc.reload`. ## The cost warning, and caps **RunicNPC has no caps by default** (D227). Instead, every placement and every event step answers with what the server's RunicNPC NPCs cost, and `rnpc.status` ends with the same lines: ``` RunicNPC: 100 NPC(s) on this server. Measured on a test server, they add about 3 ms to every server frame while idle with a player near enough to wake them, and about 0.5 ms once they sleep with nobody near. If all fight at once they add about 9 ms, and Rust's shared 2 ms AI budget then lets each react only every 3 s. ... ``` What it means: - **Idle NPCs are cheap, and sleeping ones cheaper.** NPCs that stand, wander or patrol with nobody to fight add a little to a frame. One with no player within its sleep distance (160 m by default) walks home and sleeps, and then costs about a sixth of what it did awake. - **Fighting NPCs hit Rust's AI budget before the frame rate.** All of Rust's human NPCs, its own scientists included, share `aithinkmanager.framebudgetms` (2 ms a frame). With many fighting at once, each one reacts less often. The server stays smooth, and the NPCs get slower to react. - **The figures are measured, not guessed.** Stage 9 measured the released NPC on both frameworks, on a 6000 map, as what 100 add to the median server frame of the same session's empty server. Beside it is Rust's own scientist, unchanged but for RunicNPC's swap, measured the same day: fighting costs what Rust's own AI costs. | 100 NPCs, over an empty server | RunicNPC on Oxide | RunicNPC on Carbon | Rust's scientist (Oxide / Carbon) | |---|---|---|---| | Idle, a player near enough to keep them awake | +2.7 to +2.9 ms | +1.5 ms | +1.0 / +1.0 ms | | Idle, asleep with nobody within 160 m | — | +0.5 ms | — | | Fighting 20 players | +7.2 ms | +9.0 ms | +7.5 / +8.0 ms | The warning uses the worst of these, rounded up: 3 ms awake, 0.5 ms asleep and 9 ms fighting per 100. The awake figure on Oxide is higher than it should be and is being worked on ([runicnpc-rust#13](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust/issues/13)). Your server's own figures depend on its CPU, its map and its players. To cap them anyway, set any of these in `config/RunicNPC.json` and reload RunicNPC (0 means none): | Key | Caps | |---|---| | `caps.total` | RunicNPC's NPCs on the server. | | `caps.perOwner` | NPCs of one owner: one placement, one event run, or one other plugin. | | `caps.perProfile` | NPCs of one profile. | | `caps.spawnsPerSecond` | How fast NPCs are spawned. | | `spawnBudgetMs` | Milliseconds of a frame the spawn queue may use (8 by default). One NPC takes about 5 ms to spawn, so a large placement is spread over frames instead of stalling one. | A step or placement over a cap is refused with the cap named. ## After a Rust update Rust's monthly update can change the scientist RunicNPC is built on. After the update: 1. **Wait for the navmesh.** `rnpc.status` says `navmesh=building` while Rust rebuilds it (about ten minutes on a large map). Placements wait for it and spawn when it is ready. 2. **Check the swap.** `rnpc.status`'s `swap fields` line should end `missing=- added=-`. Anything else means Rust's scientist has changed since this RunicNPC was released: update RunicNPC (on a Runic Gateway server, `update --game rust` or an egg reinstall takes the current bundle). 3. **Check the hooks.** A hook listed as `silent` long after the server has been played on may have been renamed. Runic Gateway checks every new Rust staging build before it reaches the public branch (PLAN.md stage 9, the staging drill), so a RunicNPC release that needs fixing is usually out before the update is.