diff --git a/runicnpc/PLAN.md b/runicnpc/PLAN.md index 869edf5..4dea4c1 100644 --- a/runicnpc/PLAN.md +++ b/runicnpc/PLAN.md @@ -9,7 +9,8 @@ decided with it. **Stage 1 measured 2026-09-30** (§9): six answers on both rigs design answered 2026-09-30** (D243–D252, §0), **built and walked 2026-09-30** on both rigs (§9). **Stage 5's design answered 2026-09-30 and 2026-10-01** (D253–D266, §0), **its spike measured 2026-10-01** on both rigs (§9), 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. +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). 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 @@ -91,6 +92,16 @@ architectural or design decision is implemented. | **D270** | **An event's Place NPCs step names the escort by a player's Steam id** (typed, or a `{placeholder}` filled from the run's start params), **and the ally by a clan from the site's clan list, or as "the team of player <Steam id>"**. Both are optional (stage 5 build). | One Steam id for both; the ally alone, with escort left to the API. | | **D271** | **A profile's PVE opt-out is two checkboxes: "players can hurt it" and "it can hurt players"**, both on by default. Turning one off is enforced by RunicNPC itself on every server, with a PVE plugin or without one, and TruePVE and NextGenPVE are told the same. Turrets, fire and other NPCs are not affected (stage 5 build, refines D261). | One "follow the PVE rules" switch, with unkillable meaning `damageTaken` 0. | | **D272** | **A zone tether is set on a placement (`tether=`) and on an event step ("inside the zone this event made"), not on a profile**, because a ZoneManager zone belongs to one server and a profile may be pushed to several (stage 5 build, refines §6). | A profile field; a profile default overridden per placement and step. | +| **D273** | **A boss is a box on any profile, not a role.** Ticking "boss" adds a health bar, phases and announcements to a roamer, sentry or guard, which keeps moving and fighting as its role does (stage 6). | A `boss` role with movement of its own, so no boss guard or boss sentry. | +| **D274** | **A boss's health bar is shown to players within 100 m of it (the profile may change the distance), and to every player who has damaged it, wherever they are,** until it dies or despawns (stage 6). | Only players who damaged it; every player on the server. | +| **D275** | **A phase, at one of the profile's health thresholds, may change the boss's stats (damage, aim, speed, ranges), swap its kit, summon a number of NPCs of another profile around it, and say a line.** Each part is optional (stage 6). | Stats and kit only, with adds left to an event's phases; stats only. | +| **D276** | **Rewards for killing a boss come from the site, and only when the boss belongs to an event**, through the event's reward steps. RunicNPC gives no reward itself. A boss outside an event has its own loot table (stage 7) (stage 6; the org lead: "if connected to an event"). | A Kits kit given by RunicNPC to every player who did at least a share of the damage; the killing blow only; the top damager only. | +| **D277** | **RunicNPC says a boss's spawn, phase and death lines in game itself**, in chat, or in a popup where PopupNotifications is loaded, so it works without a site. **The site gets public boss triggers** (spawned, phase, killed) for app push, in-app and email rules. **Discord is reached only through an event's existing announce step**, so website core does not change (stage 6). | A Discord channel in engagement for a boss outside an event (a core change); in game only. | +| **D278** | **Pressing E on a passive NPC does what its profile picks:** a chat line to that player, picked at random from a list, or a window with a site-written title and text and a Close button (stage 6). | Always a window; always a chat line. | +| **D279** | **A passive NPC cannot be hurt by default:** D271's "players can hurt it" is off for a passive profile until an admin ticks it. With it on, the NPC can die and respawns like any placement. It never fights back either way (stage 6). | Always invulnerable, with no setting; hurt like any NPC by default. | +| **D280** | **RunicNPC ships four example profiles, each with a kit that works on a fresh server:** a raider (roamer), a camp guard (guard), a sniper (sentry) and a boss (the "Juggernaut", with phases). Kits has no API that creates a kit, so **RunicNPC writes its example kits into Kits' own data file** and reloads Kits. Warden is not one of them (stage 6). | A profile with no kit wearing its Rust prefab's own gear (relaxing D217); item lists for the examples only; no examples; templates on the site that leave the kits to the admin. | +| **D281** | **NPCs say no greet, hurt or kill lines.** A profile talks only through press E on a passive NPC (D278) and a boss's announcements (D277) (stage 6). | Lines on any profile; on passive NPCs and bosses only. | +| **D282** | **Stage 6 is one stage, opening with a spike on both rigs, walked once end to end**, as stages 4 and 5 were (D248, D253) (stage 6). | 6a (bosses) and 6b (passive NPCs), 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 @@ -271,7 +282,7 @@ Borrowed ideas are marked with their source; everything else is new. Stage numbe | Feature | Stage | |---|---| | Press E to talk: an NPC says a line, or opens a message, when used | 6 | -| Lines on greet, hurt and kill | 6 | +| ~~Lines on greet, hurt and kill~~ — not built (D281) | — | | Walk a recorded path (D234), and follow a player | 2, 3, 5 | ### 3.3 Runic Gateway's own @@ -288,7 +299,7 @@ Borrowed ideas are marked with their source; everything else is new. Stage numbe | **Zone tethering**: an NPC held inside a ZoneManager zone (from redesign §3) | 5 | | **Guard and escort**: hold a point or an entity; follow a convoy or a player | 5 | | **Factions**: profiles hostile or allied to each other; allied to a team or clan, for defend-your-base events | 5 | -| **Bosses**: an on-screen health bar, phases at health thresholds, announcements (popup, chat, Discord and the app through engagement), a reward on the kill | 6 | +| **Bosses**: an on-screen health bar, phases at health thresholds, announcements (in game by RunicNPC; the app through engagement; Discord through an event, D277), a reward on the kill when the boss belongs to an event (D276) | 6 | | **Quest-giver or vendor**: passive, press E for a site-written message | 6 | | **The live map and the app**: markers for event NPCs and bosses, "guards left: 3/8" | 8 | | **Operator-friendly**: shipped in the bundle, no phone-home, no image files, no boot scan; `doctor` reports it; RunicNPC's permissions appear in the site's permission manager like any plugin's | 2, 4 | @@ -366,8 +377,8 @@ Each profile has a **role**, which sets its AI states and defaults: | **Guard** | Holds a point or an entity; chases only to its leash, then returns. | | **Patrol** | A roamer on `route:` (D233): walks a route recorded in game (`/rnpc path record`); fights, then returns to the point it was heading to (D262, stage 5). | | **Escort** | Follows an entity or player; defends it. Its target comes from an event step, the API, or `/rnpc follow` (D258). | -| **Boss** | Any of the above, plus a health bar, phases and announcements (§3.3). | -| **Passive** | Never fights; press E to talk. Quest-givers and vendors. | +| **Boss** | Not a role: a box on any roamer, sentry or guard profile (D273), adding a health bar (D274), phases (D275) and announcements (D277). | +| **Passive** | Never fights; press E for a chat line or a window (D278). Cannot be hurt unless its profile allows it (D279). Quest-givers and vendors. | **Factions** are named (D254): each profile names one, and a table says how factions treat each other, *hostile*, *neutral* or *allied*. Rust's scientists and animals are two built-in factions. A profile may list exceptions, @@ -1076,11 +1087,38 @@ the first runs mistook for "no fight". ### Stage 6 — Roles -Bosses (a health bar drawn with CUI, phases at thresholds that swap profile values, announcements through the bridge -to engagement, a reward on the kill through the existing reward verbs) and passive NPCs (press E, site-written lines). +Bosses, passive NPCs, and the example profiles RunicNPC ships. -**Tested by** an in-game walk (the bar, a phase change, the announcement arriving on Discord and in the app), and -the site's trigger firing at the threshold. +The org lead's answers on 2026-10-05 are D273–D282. **It is one stage, opening with a spike, walked once end to end +(D282)**, as stages 4 and 5 were. Its wire changes join protocol 13 while it is unreleased. + +- **The spike first (D282).** A harness answers what the rest depends on, on both rigs: + - pressing E on our NPC: which hook, if any, Oxide and Carbon raise for a `ScientistNPC` subclass, and what Rust + does with a use input aimed at an NPC (D278); + - the health bar: what redrawing a CUI bar costs for many players during a fight, how often it can redraw, and that + it is cleared on death, despawn, disconnect and unload (D274); + - a phase's kit swap mid-fight: strip and give a kit while the NPC is fighting, and whether its brain keeps its + target and uses the new weapon (D275); + - summoned adds: placing NPCs of another profile around a fighting boss, on the navmesh (D275); + - Kits' data file on both frameworks: where it lives, its format in Kits 4.4.9, and whether a reload picks up an + added kit without losing players' usage and cooldowns (D280). +- **RunicNPC (API 5):** + - the boss box on any profile (D273): the bar and its distance (D274), phases at thresholds (D275), spawn, phase + and death lines and how they are said (D277); + - hooks for a boss's spawn, phase and death, the death carrying the killer and every player who damaged it; + - the passive role: never fights, press E (D278), "players can hurt it" off by default (D279); + - the four example profiles, and their kits written into Kits' data file (D280). +- **Rust-Plugins (the bridge):** the boss block pushed with the profiles; frames for a boss's spawn, phase and + death for the site. +- **Module-Rust:** the profile form's boss box and passive settings; public boss triggers (spawned, phase, killed) + for engagement rules (D277); an event's reward steps reaching the players who killed its boss (D276). + +**Not in this stage:** a Discord post for a boss outside an event (D277), RunicNPC's own kill rewards (D276), and +greet, hurt or kill lines (D281). A boss's loot table is stage 7's. + +**Tested by** the harness on both rigs, and an in-game walk: the bar, a phase change with its adds and kit swap, +the announcement in game and in the app, an event's reward reaching the boss's killers, the site's triggers firing, +press E on a passive NPC, and the example profiles working on a server with no kits of its own. ### Stage 7 — Loot