A Foundry VTT game system: Basic Roleplaying d100 in a drab British agency that deals with crossings, where reality keeps a record of what belongs where and can be made to get it wrong. Contents: - rules.mjs as the single authority for every rule formula, with 40 rules and 132 spot-checked values. Nothing may restate a formula it defines. - 25 postings, each with a key characteristic, trained skills, talents and its own kit; a 175-item catalogue across four eras; 231 generated icons. - Reaction Lanes initiative, re-rolled every round including the first. - Coherence, and the Quiet Arts, which only ever arrive from a crossing gone wrong. - Graded defences: only a critical stops a critical. - Borrowed Authority — access as a record rather than a hacking roll. - A case generator, and a rules journal generated from rules.mjs so the book cannot drift from the code. Built compendia are committed so a remote Foundry needs only the files. node_modules is not; `npm install` restores it for rebuilding content. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
170 lines
7.0 KiB
Markdown
170 lines
7.0 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 is supported but optional — the system registers four of its own dice textures.
|
||
|
||
### 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 three 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
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Roles** | 25 postings, each with a key characteristic, trained skills, talents and its own kit |
|
||
| **Catalogue** | 175 items — 118 gear, 30 weapons, 13 armour, 14 vehicles |
|
||
| **Eras** | modern, antique, future, anomalous — the agency is old and never abolishes anything |
|
||
| **Icons** | 231, all generated from `tools/icons.mjs`; no external art |
|
||
| **Compendia** | pregens, NPCs, skills, weapons, armour, gear, vehicles, powers, tables, rules, a starter case |
|
||
| **Rules journal** | 8 pages, generated from `rules.mjs` so the book cannot drift from the code |
|
||
|
||
---
|
||
|
||
## 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.
|
||
|
||
---
|
||
|
||
## 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 (~4,900 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/ dice/ fonts/ 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 three guards first and refuses on failure
|
||
make-icons.mjs draws all 231 icons
|
||
make-dice-textures.mjs
|
||
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
|
||
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 three guards before it writes anything:
|
||
|
||
```
|
||
check-rules: 40 rules, 12 files scanned, 132 formulas verified
|
||
check-kits: 25 roles, 162 catalogue items, every kit key resolves
|
||
check-lang: 738 keys, no leaf/branch collisions
|
||
```
|