CREATURE_FORGE_PLAN Part 5. A third button on the Actors sidebar, beside New agent and New NPC. Pick what it does, how big it is and how bad it is; the card underneath describes what those settings will actually produce, because the argument for a derivation over a form is that it can be interrogated, and choosing between "brute" and "sentinel" from two nouns is not interrogating anything. The card is itself forged rather than written, so it cannot describe a creature the derivation would not make. generateCreature reads the catalogues out of the packs and calls the same forgeCreature the CLI calls. Natural attacks carry their body-plan declarations into flags.ringbrp.plans so the engine can read them. The plan asks that the panel and the CLI cannot diverge, and importing one derivation was most of that guarantee but not all of it: the two feed it from DIFFERENT catalogues — content.mjs on one side, the built compendium on the other. check-forge now builds the engine's view straight out of packs/weapons and requires both to forge the same creature. It found a divergence on its first run, in 40 of 90 pairs. The fallback took the first usable natural attack from the caller's list, and that list arrives in declaration order from content.mjs and in id order from the pack, so a tiny vesh brute was punching for the CLI and constricting at the table. The derivation may not depend on its caller's iteration order; it imposes its own now. Not yet verified in a running Foundry. The pure derivation is covered by 450 guarded combinations and the catalogue seam by the agreement check above, but Actor.create, the pack reads and the dialog itself are the part check-behaviour says outright it cannot reach. They need a world open, and that has not happened yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
211 lines
11 KiB
Markdown
211 lines
11 KiB
Markdown
# THE CUSTODIANS
|
||
|
||
*A Basic Roleplaying game of crossings, as a Foundry VTT system.*
|
||
|
||
A drab British government agency deals with **crossings**. Reality keeps a record of
|
||
what belongs where, and it can be made to get it wrong. Agents are civil servants:
|
||
they carry warrant cards and cordon tape, they file in triplicate, and the thing that
|
||
makes them dangerous is that they know how the record works.
|
||
|
||
The tone is bureaucratic horror. Most cases close with an arrangement rather than a
|
||
fight, and the supernatural is a filing error somebody committed on purpose.
|
||
|
||
---
|
||
|
||
## Installing
|
||
|
||
**In Foundry:** *Game Systems → Install System → Manifest URL*
|
||
|
||
```
|
||
https://gitea.timevans.uk/slaguru666/RingBRP/raw/branch/main/system.json
|
||
```
|
||
|
||
**Or by hand:** clone this repository into your Foundry data directory as
|
||
`Data/systems/ringbrp`, then restart Foundry.
|
||
|
||
```bash
|
||
git clone https://gitea.timevans.uk/slaguru666/RingBRP.git ringbrp
|
||
```
|
||
|
||
Requires **Foundry v13+** (verified against v14.364). No modules are required. Dice So
|
||
Nice works if you have it, using your own dice — the system ships no dice skins and does
|
||
not touch anybody's dice settings.
|
||
|
||
### Deploying to a remote Foundry server
|
||
|
||
The built compendia in `packs/` **are committed on purpose**, so a remote server needs
|
||
nothing but the files:
|
||
|
||
```bash
|
||
cd /path/to/foundrydata/Data/systems
|
||
git clone https://gitea.timevans.uk/slaguru666/RingBRP.git ringbrp
|
||
# restart Foundry
|
||
```
|
||
|
||
`node_modules/` is *not* committed. You only need it if you intend to rebuild the
|
||
packs or regenerate art on that machine:
|
||
|
||
```bash
|
||
npm install # pulls classic-level, used to write the LevelDB packs
|
||
npm run build # rebuilds packs/ from tools/content.mjs
|
||
npm run check # the twenty-four guards; the build refuses to run if they fail
|
||
```
|
||
|
||
To update a deployed server: `git pull` and restart Foundry. If the pull touches
|
||
`packs/`, Foundry must be **stopped** first — LevelDB will not tolerate its files
|
||
changing underneath a running server.
|
||
|
||
---
|
||
|
||
## What is in the box
|
||
|
||
<!-- box:start -->
|
||
| | |
|
||
|---|---|
|
||
| **Postings** | 25, each with a key characteristic, trained skills, talents and its own kit |
|
||
| **Trades** | 10 ordinary jobs the department recruits from, plus induction |
|
||
| **Catalogue** | 244 items — 123 gear, 70 weapons, 32 armour, 19 vehicles |
|
||
| **Skills / talents** | 62 skills, 19 talents |
|
||
| **Bestiary** | 184 statblocks across folklore, horror and the far side |
|
||
| **Eras** | modern, antique, future, anomalous — the agency is old and never abolishes anything |
|
||
| **Icons** | 292, all generated from `tools/icons.mjs`; no external art |
|
||
| **Starter scenario** | **BLACK PLATFORM**, a six-player action starter, importable as a single Adventure |
|
||
| **Compendia** | pregens, NPCs, skills, weapons, armour, gear, vehicles, powers, tables, rules, the starter |
|
||
| **Rules journal** | 13 pages, generated from `rules.mjs` so the book cannot drift from the code |
|
||
<!-- box:end -->
|
||
|
||
---
|
||
|
||
## The rules, in brief
|
||
|
||
**d100 roll-under**, banding into critical / special / success / failure / fumble.
|
||
96–99 always fail, 00 always fumbles, and every skill has a 1% floor.
|
||
|
||
**Reaction Lanes** replace Strike Rank. Initiative is
|
||
`3 × max(⌈DEX/3⌉, ⌈readiness/10⌉)` less carried load, plus a d6, **re-rolled every
|
||
round** — including the first, so the opening round is ordered like every other.
|
||
|
||
**Coherence** runs 10 → 0 and measures how well-filed an agent is in reality. It bands
|
||
into Anchored / Loose / Adrift / Unmoored / Displaced, and spending it is how the
|
||
supernatural works.
|
||
|
||
**The Quiet Arts** are deliberate misfilings, not spells. They cost Coherence, and
|
||
they **only ever arrive from a crossing that goes wrong**.
|
||
|
||
**Defences are graded.** A defence stops a blow of its own quality or worse outright;
|
||
against something better it only reduces it by as many steps as it was outclassed by.
|
||
Only a critical stops a critical.
|
||
|
||
**Access is a record.** There is no hacking skill and nothing to break into — see
|
||
below.
|
||
|
||
**A weapon's fire mode is a decision.** Slow weapons shoot better and then make you
|
||
work; fast ones offer a second shot at the cost of both; rapid ones fire bursts; beams
|
||
can be held on the target for damage instead of hits. A weapon that cannot fire a
|
||
burst cannot be made to.
|
||
|
||
**Sights and lamps apply themselves.** A sight is graded by range band — a telescopic
|
||
sight is a penalty inside ten metres — and a carried lamp buys the dark back to dim,
|
||
never to daylight, and tells everyone where you are. Neither is a thing the player
|
||
selects: both are facts about what is in the pack.
|
||
|
||
---
|
||
|
||
## Borrowed Authority — the access subsystem
|
||
|
||
Deliberately not cyberpunk. Nobody jacks into anything.
|
||
|
||
What an agent has is a **named credential** belonging to somebody real, with a
|
||
**scope** of things that person could plausibly do, a **Trust** that erodes as it is
|
||
used, and **red flags** describing how the real owner behaves.
|
||
|
||
- **Inside its scope there is no roll.** A facilities contractor opening a plant room
|
||
is not intrusion, it is Tuesday. It costs 1 Trust and it works.
|
||
- **One tier beyond is a stretch** — roll, at −20 for each red flag you break. The
|
||
system is not testing whether you are clever. It is testing whether you are
|
||
behaving like the person whose name is on the record.
|
||
- **Two tiers beyond is impossible at any skill.** No percentage on any sheet gets a
|
||
contractor issuing accounts.
|
||
- A **fumble burns** the credential, and somebody real is going to be asked about it.
|
||
|
||
A credential is assembled, not found: up to **three dossier items, each a separate
|
||
scene using a different skill, at most one of them at a keyboard**. Items make the
|
||
credential better, never the roll easier.
|
||
|
||
**AI** is a posture on the target rather than an opponent — a *gatekeeper* raises what
|
||
counts as routine, an *analyst* writes a new red flag every time you stretch, an
|
||
*asset* stands in for a dossier item.
|
||
|
||
And you may spend **Coherence** to widen a scope, because reality can be made to
|
||
remember that the person always held that duty. It works. It always works. Push a
|
||
credential past what its Trust will carry and your file and theirs converge one step,
|
||
and nothing in this game spends anything to converge them back.
|
||
|
||
---
|
||
|
||
## Repository layout
|
||
|
||
```
|
||
ringbrp.mjs the system: sheets, engine, hooks (~5,500 lines)
|
||
rules.mjs THE SINGLE AUTHORITY for every rule formula
|
||
system.json Foundry manifest
|
||
template.json data model for every Actor and Item type
|
||
templates/ Handlebars sheets
|
||
styles/ one stylesheet
|
||
lang/en.json all user-facing text
|
||
icons/ fonts/ art/ generated art
|
||
packs/ built LevelDB compendia (committed — see Deploying)
|
||
tools/
|
||
content.mjs the catalogue: skills, weapons, armour, gear, vehicles, NPCs
|
||
build-packs.mjs builds packs/ — runs the twenty-four guards first and refuses on failure
|
||
make-icons.mjs draws all 231 icons
|
||
rules-text.mjs generates the rules journal FROM rules.mjs
|
||
mission.mjs the case generator
|
||
mission-tables.mjs its content tables
|
||
check-rules.mjs guard: no rule may be defined twice
|
||
check-kits.mjs guard: every posting's kit must exist and be usable
|
||
check-lang.mjs guard: no localisation key may be both a value and a branch
|
||
check-lethality.mjs guard: no creature may quietly change what it does to a party
|
||
check-rollable.mjs guard: no clue may hide behind a roll nobody present can make
|
||
docs/REVIEW_LOG.md the design and defect log, R-1 onward
|
||
```
|
||
|
||
### The one rule this codebase enforces on itself
|
||
|
||
**No rule formula may exist in more than one place.** Everything lives in `rules.mjs`,
|
||
and `tools/check-rules.mjs` fails the build if a formula is restated, if an alias
|
||
stops being identity-equal to what it aliases, if a constant is re-declared as a
|
||
literal, or if an exported rule has no spot-check. The packs used to be built under
|
||
one set of numbers and played under another; this makes that impossible to ship.
|
||
|
||
The build runs all twenty-four guards before it writes anything:
|
||
|
||
<!-- guards:start -->
|
||
```
|
||
check-seam: OK — 74 modules scanned, only all-specs.mjs reads NPCS/PREGENS from content.mjs
|
||
check-generator: OK — 210 posting × tier pairs draw from their own stores, 129 weapons issued, each with the skill it names
|
||
check-forge: OK — 450 creatures derived across 6 roles × 5 sizes × 5 tiers × 3 species, every one valid, armed with something its body can use, and reproducible from its seed; 90 of them forged identically from the built pack and from content.mjs
|
||
check-rules: OK — 113 rules, 72 files scanned, 3 aliases + 46 constant sets checked, 417 formulas verified
|
||
check-kits: OK — 25 roles, 10 trades, 226 catalogue items, every kit key resolves, every posting can use what it carries, every loadout distinct
|
||
check-lang: OK — en.json, 1044 keys, no leaf/branch collisions
|
||
check-templates: OK — 19 templates compile
|
||
check-behaviour: OK — 108 behavioural tests
|
||
check-scenarios: OK — 30 scenario files, 111 mechanic tags, every skill named resolves against 62 catalogue entries
|
||
check-rollable: OK — 101 rolls across 10 playable scenarios (records and art sheets are not rolls), every one reachable at 25% or better by somebody present
|
||
check-outcomes: OK — 21 beats, 18 state a failure, 6 a fumble, 8 a special; 81.3% of sessions hit a special with nothing written, down from 83.7% recorded
|
||
check-creatures: OK — 204 actor specs across 13 sources, every characteristic, skill, kit key, talent, species and style resolves, no duplicate keys
|
||
check-powers: OK — 142 powers classified, 2 wired and each one measurably changes its fight and is accounted for in the bestiary, 78 recorded as beyond the harness with a reason, 62 not fight rules
|
||
check-anatomy: OK — 5 body plans, 36 locations, d20 complete in both modes, every location drawn, every kind handled and destructible, 20 plan changes carried 432 wounds with their severity intact, 1 flyer(s) with a survivable landing
|
||
check-lethality: OK — 184 creatures, every one fighting exactly as recorded against the frozen party
|
||
check-focus: OK — focus fire measured against 138 packs, helps in 137 of them, 130 by more than their own noise; no measurable help against The dun cow, named in BESTIARY.md
|
||
check-firstblood: OK — the first disabling blow is worth 40 points of wipe rate in the four-player cut, 15.4 in the six-a-side line
|
||
check-attackers: OK — three of the four-player cut disable on 11.1% of their attacks or better, and one of them on 0.1%
|
||
check-fight-tail: OK — a fight past 15 rounds wipes the party 1.4x as often in the four-player cut and 2.4x at six a side, and nothing was truncated
|
||
check-packs: OK — 17 pack fights, 2000 runs each at seed 11, nothing truncated at 400 rounds, every figure matching the record
|
||
check-cited: OK — 187 cited figures across 30 scenario files resolve against 8 baselines
|
||
check-figures: 6 figure(s) waived, each on the record:
|
||
check-handouts: OK — 4 handouts, the two almanac pages identical in structure and columns, every line 41 miles from clean ground, nothing under 11pt
|
||
check-bestiary: OK — 184 creatures, the document matches the game
|
||
```
|
||
<!-- guards:end -->
|