5 Commits
Author SHA1 Message Date
slaguru666andClaude Opus 5 ab619f4b73 Remove the dice textures and the whole Dice So Nice path
Deleted: the seven PNGs in dice/, tools/make-dice-textures.mjs, the `npm run
dice` script, the RB_DICE colourset and texture tables, diceSetFor, the
diceSoNiceReady hook, and rbDressDice — which was tagging ten roll sites with
coloursets that no longer existed. 99 lines of module, plus the assets.
README and DEPLOY updated; they still advertised all of it.

Recoverable with `git revert` if it is ever wanted back.

This also explains the 01-that-was-12. The RESULT was never wrong: skillRoll
rolls one 1d100 and grades on roll.total, and the chat card derives the tens and
units it prints from that same total. Checked all 100 values of percentileFaces
and 60 live rolls — the printed faces reconstruct the graded number every time,
with no mismatches.

What disagreed was the ANIMATION. The custom addDicePreset labels registered for
d100 and d10 remapped which physical face means what, so Dice So Nice could land
showing 01 while the roll behind it was 12. Nothing downstream ever read the
animated faces, so no roll was ever adjudicated on the wrong number — but a
table watching the dice had every reason to believe otherwise, which is its own
kind of wrong. Disabling the skins in 1.0.6 already removed it; deleting them
makes it permanent.

Verified in a running Foundry after removal: skill roll, weapon damage, hit
location, major wound and Coherence all resolve and post their cards, no errors,
and game.ringbrp.diceSetFor is gone from the API.

Version 1.0.7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 22:45:52 +01:00
slaguru666andClaude Opus 5 9b6c61ffcb Turn the custom Dice So Nice skins off
Registering them with "preferred" made them the default for everybody in the
world, which overrides whatever dice a player had already chosen — the system
helping itself to a setting that belongs to the user. Off at the author's
request.

One named constant rather than a settings API: this codebase registers no game
settings at all, and adding that surface, its lang keys and its UI to switch one
feature off is more machinery than the job needs. Flip RB_DICE_ENABLED to true
and everything below it still works.

The textures in dice/ and the generator behind `npm run dice` are left alone.
Nothing reads them while this is false, and deleting work in order to turn a
feature off is a poor trade.

Verified in a running Foundry with Dice So Nice active: "custodians" is no
longer among the registered systems, and preferredSystem has gone back to
"standard" rather than ours.

Version 1.0.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 20:34:22 +01:00
slaguru666andClaude Opus 5 0852427586 Fix the pause: it would not hide, it was off centre, and it was too small
Three faults in 1.0.4, and the first was the serious one.

  1. It never went away. Core hides the overlay with `#pause { display: none }`
     and shows it with `#pause.paused { display: flex }`. 1.0.4 styled the BARE
     #pause with display:flex, which wins on specificity, so unpausing removed
     the class and changed nothing — GAME PAUSED sat over the table for the rest
     of the session. Every rule here is now scoped to `.paused` and `display` is
     not set anywhere.

  2. It was off centre because I repositioned it. Core already centres it: a
     full-width band at top calc(50vh - 100px), column flex, centred both ways,
     pointer-events none. That layout was correct and 1.0.4 fought it with
     left/bottom/transform. It is left alone now; only the height changes, and
     the top moves up by exactly half the extra so the centring holds.

  3. It was small: a 322x116 panel in the corner. It is now core's full-width
     band at 300px with a 170px dial — against core's own 100px — and the
     caption at 24px to match core's.

Guarded: check-behaviour now parses the stylesheet and fails any rule that sets
display on an unscoped #pause. Verified it bites. It strips CSS comments first,
because the first version of the guard reported the comment explaining the
guard — which is exactly what the template guard did last time, so that is twice
now and the lesson is written down properly.

Verified by driving the real toggle: running → display none, box 0x0, no class;
paused → display flex, 341x302, centre X exactly on the viewport centre;
unpaused again → display none, box 0x0.

Version 1.0.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 19:31:35 +01:00
slaguru666andClaude Opus 5 ad771ff2b5 A uniselector for the pause
Foundry's pause is a spinning d20 and a caption. This replaces both from CSS
alone, without touching the markup: figure#pause becomes a small navy panel with
a yellow rule along the top, and the <img> becomes the arm of a uniselector.

A uniselector is the stepping switch inside a telephone exchange — an arm that
clicks round one contact at a time, hunting for a free line. It is the right
object for this game. The department's whole business is a machine that says
where things belong, and OPEN DAY is set inside one. Eleven contacts, because
eleven minutes is the interval this setting keeps returning to.

It STEPS rather than sweeps: steps(11) over 7.7s, so a contact every 700ms. A
continuous spin reads as a loading throbber; a discrete click reads as a machine
working through a list, which is what the department is doing while the table is
out of the room. The arm carries a faint trailing sector, because without it a
700ms step is easy to miss and the stepping is the whole idea.

No new text. Foundry's caption is localised and this only restyles it — a string
hardcoded in a stylesheet would be one the lang file could never reach.

Two things the browser had to be asked rather than assumed:

  - Core pins #pause with BOTH top and bottom, so an auto height stretched it to
    180px for a 16px caption. It is pinned here instead and sized to content.
  - The arm is rotated, so getBoundingClientRect returns the diagonal of its own
    square (75px for a 52px element). The layout takes its size from the flex
    basis and never from the measured box.

prefers-reduced-motion stops the movement and keeps the object — a stepping dial
in the corner of the eye is exactly what that preference is asking about.

Version 1.0.4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 19:25:12 +01:00
slaguru666andClaude Opus 5 53481bdfc1 Ship the LAST ADMISSION plates as showable images
A third journal in the adventure — LAST ADMISSION — Show the players — holding
the seven scene plates and the floor plan as eight image pages at player
visibility. Right-click, Show Players, done.

title.show is false and there is no caption, on purpose: the table gets the
picture and nothing else. No heading telling them which room this is, no label
naming the thing on the stairs. The page NAMES exist only for the GM's sidebar
so the right one can be found in a hurry under pressure, and the players never
see them.

Ordered by when each comes up, not by asset number, for the same reason.

The builder throws if a plate is missing from disk, because a missing image is
a blank frame on a projector in front of six people.

Verified in Foundry: eight pages import at OBSERVER, the image loads, and the
rendered page contains no headings, no figcaption and no text at all.

Version 1.0.3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 19:12:35 +01:00
153 changed files with 320 additions and 319 deletions
+8 -8
View File
@@ -28,7 +28,8 @@ 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.
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
@@ -47,7 +48,7 @@ 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
npm run check # the five guards; the build refuses to run if they fail
```
To update a deployed server: `git pull` and restart Foundry. If the pull touches
@@ -152,13 +153,12 @@ 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
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 three guards first and refuses on failure
build-packs.mjs builds packs/ — runs the five 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
@@ -176,13 +176,13 @@ 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:
The build runs all five guards before it writes anything:
<!-- guards:start -->
```
check-rules: OK — 87 rules, 21 files scanned, 3 aliases + 41 constant sets checked, 275 formulas verified
check-rules: OK — 87 rules, 20 files scanned, 3 aliases + 41 constant sets checked, 275 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, 945 keys, no leaf/branch collisions
check-behaviour: OK — 45 behavioural tests
check-behaviour: OK — 46 behavioural tests
```
<!-- guards:end -->
Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 826 B

+1 -2
View File
@@ -33,10 +33,9 @@ Only if you intend to edit the catalogue there:
```bash
npm install # classic-level, for writing LevelDB
npm run check # the three guards
npm run check # the five guards
npm run build # rebuilds packs/
node tools/make-icons.mjs # redraws all icons
node tools/make-dice-textures.mjs # regenerates the Dice So Nice textures
```
`npm run build` runs the guards first and aborts if any fails, so a broken catalogue
+7
View File
@@ -426,6 +426,13 @@ If there is time — and there usually is, because this ends early — she says
## Artwork
**Showing them at the table.** The adventure ships a third journal,
**LAST ADMISSION — Show the players**, holding these as eight image pages at player
visibility. Right-click a page and *Show Players*: the table gets the picture and
nothing else — no heading, no caption, no label naming what they are looking at. The
page names are for the GM's sidebar and the players never see them.
**Style line:** flat editorial vector, deep navy and pale yellow with warm off-white,
1970s British public-information poster, `--style raw --ar 3:2 --v 6`.
-1
View File
@@ -6,7 +6,6 @@
"scripts": {
"build": "node tools/build-packs.mjs && node tools/update-readme.mjs",
"icons": "node tools/make-icons.mjs",
"dice": "node tools/make-dice-textures.mjs",
"check": "node tools/check-rules.mjs && node tools/check-kits.mjs && node tools/check-lang.mjs && node tools/check-templates.mjs && node tools/check-behaviour.mjs",
"test": "npm run check",
"readme": "node tools/update-readme.mjs"
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.231003 174603000 Delete type=3 #1
2026/08/12-22:44:48.920895 172817000 Recovering log #3
2026/08/12-22:44:48.921047 172817000 Level-0 table #5: started
2026/08/12-22:44:48.921223 172817000 Level-0 table #5: 4591 bytes OK
2026/08/12-22:44:48.921517 172817000 Delete type=0 #3
2026/08/12-22:44:48.921554 172817000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.287733 16f5db000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.298648 173df7000 Delete type=3 #1
2026/08/12-22:44:48.946376 17382f000 Recovering log #3
2026/08/12-22:44:48.946637 17382f000 Level-0 table #5: started
2026/08/12-22:44:48.946788 17382f000 Level-0 table #5: 4129 bytes OK
2026/08/12-22:44:48.947029 17382f000 Delete type=0 #3
2026/08/12-22:44:48.947065 17382f000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.362147 16edcf000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.232848 174603000 Delete type=3 #1
2026/08/12-22:44:48.922471 173023000 Recovering log #3
2026/08/12-22:44:48.923346 173023000 Level-0 table #5: started
2026/08/12-22:44:48.923621 173023000 Level-0 table #5: 31614 bytes OK
2026/08/12-22:44:48.923809 173023000 Delete type=0 #3
2026/08/12-22:44:48.923836 173023000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.290003 16f5db000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.282484 173df7000 Delete type=3 #1
2026/08/12-22:44:48.936635 17200b000 Recovering log #3
2026/08/12-22:44:48.937301 17200b000 Level-0 table #5: started
2026/08/12-22:44:48.937794 17200b000 Level-0 table #5: 45532 bytes OK
2026/08/12-22:44:48.938219 17200b000 Delete type=0 #3
2026/08/12-22:44:48.938275 17200b000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.345401 16e5c3000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.266480 174603000 Delete type=3 #1
2026/08/12-22:44:48.907196 173023000 Recovering log #3
2026/08/12-22:44:48.908927 173023000 Level-0 table #5: started
2026/08/12-22:44:48.910392 173023000 Level-0 table #5: 225945 bytes OK
2026/08/12-22:44:48.910874 173023000 Delete type=0 #3
2026/08/12-22:44:48.910934 173023000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.327015 16f5db000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.293373 173df7000 Delete type=3 #1
2026/08/12-22:44:48.917345 172817000 Recovering log #3
2026/08/12-22:44:48.917660 172817000 Level-0 table #5: started
2026/08/12-22:44:48.917794 172817000 Level-0 table #5: 3295 bytes OK
2026/08/12-22:44:48.918046 172817000 Delete type=0 #3
2026/08/12-22:44:48.918081 172817000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.356982 16edcf000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.252536 174603000 Delete type=3 #1
2026/08/12-22:44:48.896053 17200b000 Recovering log #3
2026/08/12-22:44:48.898901 17200b000 Level-0 table #5: started
2026/08/12-22:44:48.902279 17200b000 Level-0 table #5: 545293 bytes OK
2026/08/12-22:44:48.902701 17200b000 Delete type=0 #3
2026/08/12-22:44:48.902787 17200b000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.311753 16e5c3000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.290196 172ddf000 Delete type=3 #1
2026/08/12-22:44:48.925841 17382f000 Recovering log #3
2026/08/12-22:44:48.926073 17382f000 Level-0 table #5: started
2026/08/12-22:44:48.926304 17382f000 Level-0 table #5: 21613 bytes OK
2026/08/12-22:44:48.926557 17382f000 Delete type=0 #3
2026/08/12-22:44:48.926598 17382f000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.353318 16edcf000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.286378 174603000 Delete type=3 #1
2026/08/12-22:44:48.939398 17200b000 Recovering log #3
2026/08/12-22:44:48.940505 17200b000 Level-0 table #5: started
2026/08/12-22:44:48.941454 17200b000 Level-0 table #5: 43953 bytes OK
2026/08/12-22:44:48.942198 17200b000 Delete type=0 #3
2026/08/12-22:44:48.942249 17200b000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.349699 16f5db000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.297168 1735eb000 Delete type=3 #1
2026/08/12-22:44:48.927292 172817000 Recovering log #3
2026/08/12-22:44:48.927647 172817000 Level-0 table #5: started
2026/08/12-22:44:48.928175 172817000 Level-0 table #5: 33484 bytes OK
2026/08/12-22:44:48.928522 172817000 Delete type=0 #3
2026/08/12-22:44:48.928579 172817000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.360431 16e5c3000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000002
MANIFEST-000004
+5 -1
View File
@@ -1 +1,5 @@
2026/08/12-19:01:54.224954 172ddf000 Delete type=3 #1
2026/08/12-22:44:48.913614 172817000 Recovering log #3
2026/08/12-22:44:48.914288 172817000 Level-0 table #5: started
2026/08/12-22:44:48.914458 172817000 Level-0 table #5: 7590 bytes OK
2026/08/12-22:44:48.914739 172817000 Delete type=0 #3
2026/08/12-22:44:48.914773 172817000 Delete type=3 #2
+1
View File
@@ -0,0 +1 @@
2026/08/12-22:44:33.281949 16edcf000 Delete type=3 #1
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More