THE DEFECT. locationFor had ONE caller in the engine, hitLocationRoll, and hitLocationRoll was called from fall, burn, detonate and burstAttack. Falling, fire, explosions and automatic fire. Nothing else. rollWeaponDamage rolled dice, printed a number and returned it, so the chat Damage button, the character sheet's damage button and the item sheet's all stopped there. A grenade knew which arm it took off. A sword did not. Every individual piece was already correct - the tables, per-location armour and coverage, disable and destroy thresholds, Major Wound, dying, death, the figure on the sheet. They simply were not joined up, which is why this reads as a wiring change rather than a new subsystem. - rollWeaponDamage now carries through to hitLocationRoll: it rolls the location, applies that location's armour, applies the wound, and handles the rest through the machinery that already owned it. Nothing here re-implements any of that - locationModeFor picks the melee or ranged column from the weapon's class. The two columns have always differed and nothing was choosing between them - with no target it does exactly what it did before and SAYS SO on a card, rather than failing quietly - burstAttack opts out with locate:false - it rolls its own location per round, and letting both fire would have applied every round of a burst twice BODY PLANS. Two new tables: quadruped (four legs, fore/hindquarters, neck, a head that is hard to reach) and winged (that, plus wings). Forequarters are the vital. DISABLE EITHER WING AND IT CANNOT FLY, which is the fight a party can win. Barghest, Kelpie and Church grim were all species "baseline" - a black dog, a horse and a grave-hound, each hit-located with two arms and a chest. Fixed. Added "The supporter", a winged heraldic beast, so the new table is exercised by real content instead of existing unused. Body plan is a NEW FIELD, not a species. A bear is not a playable people with characteristic dice and talents, so creature specs take bodyPlan and the playable species list is untouched. THE NPC SHEET had no hit locations at all - 102 lines against the character sheet's 627 - while every NPC in the game had them derived and wired to consequences. It now carries the body-plan selector, the figure, the per-location table, the condition and a GROUNDED flag. The sheet class already extended the character sheet, so it already HAD the context; the template never used it. FOUND IN PASSING, by the new guard: kind "body" - the abdomen, the trunk, the hindquarters - did nothing whatever. Its printed effect has always promised "-30% to all Physical actions and bleeding 1 hit point per round until First Aid" and the code delivered none of it, on every body plan including the humanoid default. It now bleeds 1, or 2 destroyed, exactly as bodyX says. NEW GUARD: check-anatomy. Every body plan must cover 1-20 exactly once in BOTH modes, every location must be drawn and every drawn shape must be a location, and every kind must be one locationEffectsFor acts on, has effect text for, and has a destruction outcome. Verified it fails on a d20 gap, a shapeless limb and an unhandled kind before wiring it in. Ninth guard. VERIFIED IN A RUNNING FOUNDRY, not just unit-tested: melee bar reads the Melee column and the rifle reads Ranged on the same creature; forequarters graded as a vital hit; a maxed wing set flightLost and the sheet said GROUNDED; the real chat Damage button rolled 1D20 15, found the right foreleg, applied 12 through armour, disabled the leg and took the dog from 16 to 4; and with nothing targeted nothing was touched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
194 lines
8.6 KiB
Markdown
194 lines
8.6 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 eight 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** | 236 items — 123 gear, 62 weapons, 32 armour, 19 vehicles |
|
||
| **Skills / talents** | 62 skills, 19 talents |
|
||
| **Bestiary** | 47 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 eight 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
|
||
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 eight guards before it writes anything:
|
||
|
||
<!-- guards:start -->
|
||
```
|
||
check-rules: OK — 103 rules, 34 files scanned, 3 aliases + 46 constant sets checked, 358 formulas verified
|
||
check-kits: OK — 25 roles, 10 trades, 218 catalogue items, every kit key resolves, every posting can use what it carries, every loadout distinct
|
||
check-lang: OK — en.json, 1015 keys, no leaf/branch collisions
|
||
check-templates: OK — 19 templates compile
|
||
check-behaviour: OK — 75 behavioural tests
|
||
check-scenarios: OK — 10 scenario files, 78 mechanic tags, every skill named resolves against 62 catalogue entries
|
||
check-creatures: OK — 102 actor specs across 8 sources, every characteristic, skill, kit key, talent, species and style resolves, no duplicate keys
|
||
check-lethality: OK — 47 creatures, none drifted more than 6 points of wipe rate against the frozen party, 1 new
|
||
```
|
||
<!-- guards:end -->
|