diff --git a/docs/REVIEW_LOG.md b/docs/REVIEW_LOG.md index 25a41a2..893c4bb 100644 --- a/docs/REVIEW_LOG.md +++ b/docs/REVIEW_LOG.md @@ -4361,3 +4361,33 @@ result instead of trusting it, which is the only reason this log is accurate. **A content wart:** the barghest bites with something called "Vesh grasp limb" — the generic `grasp` weapon still carrying a Ringworld-era display name. Every creature in the bestiary that uses `grasp` inherits it. + +## R-240. A lamp lights the people standing in it + +The goods yard fight made the case: three agents inside the same pool of light shot at +−50% while the fourth, four metres away, shot at −10%. Nobody would run that at a +table, and the rule was wrong rather than merely coarse. + +A lamp now has a **reach**, and it is per item rather than global, because a weapon +lamp and a vehicle searchlight are not the same offer — 6 m, 10 m for the issue field +lamp, 4 m for cold light strips, 30 m for a roof searchlight. Anyone inside the reach +is in the light, and the card names whose lamp it is: *"MODE: Tomas's, 4 m away — you +are in it."* Both halves of the rule travel together, so the pool is one position and +the whole group is standing in it. + +Measured from the tokens, because the canvas already knows who is standing where. The +same shot that started this — Rakhi, no lamp of her own, four metres from Tomas's, in +pitch dark — went from **20% to 60%**, and Ceyla twenty-five metres out still ate the +full −50%. + +**The interesting part was the unknown.** `Number(null)` is 0, so an unmeasured +distance read as *standing on top of the lamp* and would have lit any scene with no +tokens placed. My own spot-check caught it before it ever ran: an unknown distance is +now explicitly not lit, and the dialog carries a tick that arrives pre-set when the +canvas could measure it and is the GM's answer when there is nothing to measure. That +keeps it automatic where it can be and honest where it cannot, rather than quietly +lighting the world. + +Note for deployment: `template.json` is read when Foundry loads the system, so the new +`lightReachM` field did not exist on items until the server was restarted — the +migration then stamped it. A remote server needs the restart, not just a pull. diff --git a/lang/en.json b/lang/en.json index f5aeb7b..38edb88 100644 --- a/lang/en.json +++ b/lang/en.json @@ -861,7 +861,6 @@ "RINGBRP.Sight.reflex": "Reflex sight", "RINGBRP.Sight.telescopic": "Telescopic sight", "RINGBRP.Sight.thermal": "Thermal sight", - "RINGBRP.Sight.LampEffect": "lit, and visible", "RINGBRP.Sight.Revealed": "{name} shows them exactly where you are", "RINGBRP.Lighting.lit": "Lit", "RINGBRP.Lighting.dim": "Dim", @@ -876,5 +875,10 @@ "RINGBRP.Chat.Damage": "damage", "RINGBRP.Chat.Sustained": "sustained", "RINGBRP.Chat.DamageMod": "damage mod", - "RINGBRP.Notify.GearFitted": "Fitted {n} item(s) that were carried before sights and lamps did anything." + "RINGBRP.Notify.GearFitted": "Fitted {n} item(s) that were carried before sights and lamps did anything.", + "RINGBRP.Sight.LampOwn": "yours, {reach} m of it", + "RINGBRP.Sight.LampNear": "{holder}'s, {m} m away — you are in it", + "RINGBRP.Sight.SomeLamp": "The light you are standing in", + "RINGBRP.Dialog.InLight": "I am in the light", + "RINGBRP.Dialog.InLightHint": "Ticked already if a lit lamp is within reach of your token. Tick it yourself when there are no tokens to measure." } diff --git a/packs/armour/000003.log b/packs/armour/000003.log deleted file mode 100644 index 5b23416..0000000 Binary files a/packs/armour/000003.log and /dev/null differ diff --git a/packs/armour/000005.ldb b/packs/armour/000005.ldb new file mode 100644 index 0000000..b406921 Binary files /dev/null and b/packs/armour/000005.ldb differ diff --git a/packs/armour/000006.log b/packs/armour/000006.log new file mode 100644 index 0000000..9d3f468 Binary files /dev/null and b/packs/armour/000006.log differ diff --git a/packs/armour/CURRENT b/packs/armour/CURRENT index 1a84852..cacca75 100644 --- a/packs/armour/CURRENT +++ b/packs/armour/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/armour/LOG b/packs/armour/LOG index 481972f..2c0939d 100644 --- a/packs/armour/LOG +++ b/packs/armour/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.947107 16e763000 Delete type=3 #1 +2026/08/11-09:44:12.196312 1737fb000 Recovering log #3 +2026/08/11-09:44:12.196429 1737fb000 Level-0 table #5: started +2026/08/11-09:44:12.196537 1737fb000 Level-0 table #5: 3269 bytes OK +2026/08/11-09:44:12.196738 1737fb000 Delete type=0 #3 +2026/08/11-09:44:12.196764 1737fb000 Delete type=3 #2 diff --git a/packs/armour/LOG.old b/packs/armour/LOG.old new file mode 100644 index 0000000..088c89c --- /dev/null +++ b/packs/armour/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.979643 172267000 Delete type=3 #1 diff --git a/packs/armour/MANIFEST-000002 b/packs/armour/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/armour/MANIFEST-000002 and /dev/null differ diff --git a/packs/armour/MANIFEST-000004 b/packs/armour/MANIFEST-000004 new file mode 100644 index 0000000..1faa5e9 Binary files /dev/null and b/packs/armour/MANIFEST-000004 differ diff --git a/packs/expedition/000003.log b/packs/expedition/000003.log deleted file mode 100644 index 263295b..0000000 Binary files a/packs/expedition/000003.log and /dev/null differ diff --git a/packs/expedition/000005.ldb b/packs/expedition/000005.ldb new file mode 100644 index 0000000..4ff460d Binary files /dev/null and b/packs/expedition/000005.ldb differ diff --git a/packs/expedition/000006.log b/packs/expedition/000006.log new file mode 100644 index 0000000..268b187 Binary files /dev/null and b/packs/expedition/000006.log differ diff --git a/packs/expedition/CURRENT b/packs/expedition/CURRENT index 1a84852..cacca75 100644 --- a/packs/expedition/CURRENT +++ b/packs/expedition/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/expedition/LOG b/packs/expedition/LOG index a59eb01..58e611b 100644 --- a/packs/expedition/LOG +++ b/packs/expedition/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.980151 16f77b000 Delete type=3 #1 +2026/08/11-09:44:12.205237 172fef000 Recovering log #3 +2026/08/11-09:44:12.205611 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.205721 172fef000 Level-0 table #5: 4129 bytes OK +2026/08/11-09:44:12.205945 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.205992 172fef000 Delete type=3 #2 diff --git a/packs/expedition/LOG.old b/packs/expedition/LOG.old new file mode 100644 index 0000000..231e892 --- /dev/null +++ b/packs/expedition/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:10.009129 17327f000 Delete type=3 #1 diff --git a/packs/expedition/MANIFEST-000002 b/packs/expedition/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/expedition/MANIFEST-000002 and /dev/null differ diff --git a/packs/expedition/MANIFEST-000004 b/packs/expedition/MANIFEST-000004 new file mode 100644 index 0000000..47fbcd4 Binary files /dev/null and b/packs/expedition/MANIFEST-000004 differ diff --git a/packs/gear/000003.log b/packs/gear/000003.log deleted file mode 100644 index 349523a..0000000 Binary files a/packs/gear/000003.log and /dev/null differ diff --git a/packs/gear/000005.ldb b/packs/gear/000005.ldb new file mode 100644 index 0000000..d9bac03 Binary files /dev/null and b/packs/gear/000005.ldb differ diff --git a/packs/gear/000006.log b/packs/gear/000006.log new file mode 100644 index 0000000..d1deb9b Binary files /dev/null and b/packs/gear/000006.log differ diff --git a/packs/gear/CURRENT b/packs/gear/CURRENT index 1a84852..cacca75 100644 --- a/packs/gear/CURRENT +++ b/packs/gear/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/gear/LOG b/packs/gear/LOG index 7a5bd92..04e48ba 100644 --- a/packs/gear/LOG +++ b/packs/gear/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.949621 16f77b000 Delete type=3 #1 +2026/08/11-09:44:12.197435 172fef000 Recovering log #3 +2026/08/11-09:44:12.198040 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.198321 172fef000 Level-0 table #5: 31614 bytes OK +2026/08/11-09:44:12.198514 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.198552 172fef000 Delete type=3 #2 diff --git a/packs/gear/LOG.old b/packs/gear/LOG.old new file mode 100644 index 0000000..194c71f --- /dev/null +++ b/packs/gear/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.981180 17327f000 Delete type=3 #1 diff --git a/packs/gear/MANIFEST-000002 b/packs/gear/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/gear/MANIFEST-000002 and /dev/null differ diff --git a/packs/gear/MANIFEST-000004 b/packs/gear/MANIFEST-000004 new file mode 100644 index 0000000..f7cd73c Binary files /dev/null and b/packs/gear/MANIFEST-000004 differ diff --git a/packs/npcs/000003.log b/packs/npcs/000003.log deleted file mode 100644 index c13442d..0000000 Binary files a/packs/npcs/000003.log and /dev/null differ diff --git a/packs/npcs/000005.ldb b/packs/npcs/000005.ldb new file mode 100644 index 0000000..434f292 Binary files /dev/null and b/packs/npcs/000005.ldb differ diff --git a/packs/npcs/000006.log b/packs/npcs/000006.log new file mode 100644 index 0000000..a8f297d Binary files /dev/null and b/packs/npcs/000006.log differ diff --git a/packs/npcs/CURRENT b/packs/npcs/CURRENT index 1a84852..cacca75 100644 --- a/packs/npcs/CURRENT +++ b/packs/npcs/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/npcs/LOG b/packs/npcs/LOG index 28f4fea..abb479c 100644 --- a/packs/npcs/LOG +++ b/packs/npcs/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.966944 16ef6f000 Delete type=3 #1 +2026/08/11-09:44:12.184168 172fef000 Recovering log #3 +2026/08/11-09:44:12.185997 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.187435 172fef000 Level-0 table #5: 223489 bytes OK +2026/08/11-09:44:12.187693 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.187728 172fef000 Delete type=3 #2 diff --git a/packs/npcs/LOG.old b/packs/npcs/LOG.old new file mode 100644 index 0000000..0809fd4 --- /dev/null +++ b/packs/npcs/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.996017 172a73000 Delete type=3 #1 diff --git a/packs/npcs/MANIFEST-000002 b/packs/npcs/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/npcs/MANIFEST-000002 and /dev/null differ diff --git a/packs/npcs/MANIFEST-000004 b/packs/npcs/MANIFEST-000004 new file mode 100644 index 0000000..c64c94d Binary files /dev/null and b/packs/npcs/MANIFEST-000004 differ diff --git a/packs/powers/000003.log b/packs/powers/000003.log deleted file mode 100644 index d723043..0000000 Binary files a/packs/powers/000003.log and /dev/null differ diff --git a/packs/powers/000005.ldb b/packs/powers/000005.ldb new file mode 100644 index 0000000..7f540c6 Binary files /dev/null and b/packs/powers/000005.ldb differ diff --git a/packs/powers/000006.log b/packs/powers/000006.log new file mode 100644 index 0000000..43e306f Binary files /dev/null and b/packs/powers/000006.log differ diff --git a/packs/powers/CURRENT b/packs/powers/CURRENT index 1a84852..cacca75 100644 --- a/packs/powers/CURRENT +++ b/packs/powers/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/powers/LOG b/packs/powers/LOG index 208cfc8..58a312f 100644 --- a/packs/powers/LOG +++ b/packs/powers/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.974409 16e763000 Delete type=3 #1 +2026/08/11-09:44:12.193256 1737fb000 Recovering log #3 +2026/08/11-09:44:12.193611 1737fb000 Level-0 table #5: started +2026/08/11-09:44:12.193707 1737fb000 Level-0 table #5: 3295 bytes OK +2026/08/11-09:44:12.193908 1737fb000 Delete type=0 #3 +2026/08/11-09:44:12.193951 1737fb000 Delete type=3 #2 diff --git a/packs/powers/LOG.old b/packs/powers/LOG.old new file mode 100644 index 0000000..037904d --- /dev/null +++ b/packs/powers/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:10.003815 172267000 Delete type=3 #1 diff --git a/packs/powers/MANIFEST-000002 b/packs/powers/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/powers/MANIFEST-000002 and /dev/null differ diff --git a/packs/powers/MANIFEST-000004 b/packs/powers/MANIFEST-000004 new file mode 100644 index 0000000..20de082 Binary files /dev/null and b/packs/powers/MANIFEST-000004 differ diff --git a/packs/pregens/000003.log b/packs/pregens/000003.log deleted file mode 100644 index 5ed9a47..0000000 Binary files a/packs/pregens/000003.log and /dev/null differ diff --git a/packs/pregens/000005.ldb b/packs/pregens/000005.ldb new file mode 100644 index 0000000..fe8672f Binary files /dev/null and b/packs/pregens/000005.ldb differ diff --git a/packs/pregens/000006.log b/packs/pregens/000006.log new file mode 100644 index 0000000..8d9abc2 Binary files /dev/null and b/packs/pregens/000006.log differ diff --git a/packs/pregens/CURRENT b/packs/pregens/CURRENT index 1a84852..cacca75 100644 --- a/packs/pregens/CURRENT +++ b/packs/pregens/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/pregens/LOG b/packs/pregens/LOG index 0888ece..8788efa 100644 --- a/packs/pregens/LOG +++ b/packs/pregens/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.956900 16ff87000 Delete type=3 #1 +2026/08/11-09:44:12.181257 172fef000 Recovering log #3 +2026/08/11-09:44:12.182096 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.182622 172fef000 Level-0 table #5: 58065 bytes OK +2026/08/11-09:44:12.182900 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.182935 172fef000 Delete type=3 #2 diff --git a/packs/pregens/LOG.old b/packs/pregens/LOG.old new file mode 100644 index 0000000..c0f91ce --- /dev/null +++ b/packs/pregens/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.987323 173a8b000 Delete type=3 #1 diff --git a/packs/pregens/MANIFEST-000002 b/packs/pregens/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/pregens/MANIFEST-000002 and /dev/null differ diff --git a/packs/pregens/MANIFEST-000004 b/packs/pregens/MANIFEST-000004 new file mode 100644 index 0000000..d892f88 Binary files /dev/null and b/packs/pregens/MANIFEST-000004 differ diff --git a/packs/rules/000003.log b/packs/rules/000003.log deleted file mode 100644 index 347e0ec..0000000 Binary files a/packs/rules/000003.log and /dev/null differ diff --git a/packs/rules/000005.ldb b/packs/rules/000005.ldb new file mode 100644 index 0000000..1147e24 Binary files /dev/null and b/packs/rules/000005.ldb differ diff --git a/packs/rules/000006.log b/packs/rules/000006.log new file mode 100644 index 0000000..5e876ff Binary files /dev/null and b/packs/rules/000006.log differ diff --git a/packs/rules/CURRENT b/packs/rules/CURRENT index 1a84852..cacca75 100644 --- a/packs/rules/CURRENT +++ b/packs/rules/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/rules/LOG b/packs/rules/LOG index d9c2440..ac28fdd 100644 --- a/packs/rules/LOG +++ b/packs/rules/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.978547 16ff87000 Delete type=3 #1 +2026/08/11-09:44:12.200848 172fef000 Recovering log #3 +2026/08/11-09:44:12.201122 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.201397 172fef000 Level-0 table #5: 30975 bytes OK +2026/08/11-09:44:12.201635 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.201675 172fef000 Delete type=3 #2 diff --git a/packs/rules/LOG.old b/packs/rules/LOG.old new file mode 100644 index 0000000..150c839 --- /dev/null +++ b/packs/rules/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:10.007699 172267000 Delete type=3 #1 diff --git a/packs/rules/MANIFEST-000002 b/packs/rules/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/rules/MANIFEST-000002 and /dev/null differ diff --git a/packs/rules/MANIFEST-000004 b/packs/rules/MANIFEST-000004 new file mode 100644 index 0000000..e2e1bf1 Binary files /dev/null and b/packs/rules/MANIFEST-000004 differ diff --git a/packs/skills/000003.log b/packs/skills/000003.log deleted file mode 100644 index e23ff19..0000000 Binary files a/packs/skills/000003.log and /dev/null differ diff --git a/packs/skills/000005.ldb b/packs/skills/000005.ldb new file mode 100644 index 0000000..d613d26 Binary files /dev/null and b/packs/skills/000005.ldb differ diff --git a/packs/skills/000006.log b/packs/skills/000006.log new file mode 100644 index 0000000..aa7dd7d Binary files /dev/null and b/packs/skills/000006.log differ diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT index 1a84852..cacca75 100644 --- a/packs/skills/CURRENT +++ b/packs/skills/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/skills/LOG b/packs/skills/LOG index 6e545bf..9dd2e32 100644 --- a/packs/skills/LOG +++ b/packs/skills/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.938794 16e763000 Delete type=3 #1 +2026/08/11-09:44:12.190287 1737fb000 Recovering log #3 +2026/08/11-09:44:12.190653 1737fb000 Level-0 table #5: started +2026/08/11-09:44:12.190822 1737fb000 Level-0 table #5: 7486 bytes OK +2026/08/11-09:44:12.191038 1737fb000 Delete type=0 #3 +2026/08/11-09:44:12.191067 1737fb000 Delete type=3 #2 diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old new file mode 100644 index 0000000..c5b52aa --- /dev/null +++ b/packs/skills/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.973842 172a73000 Delete type=3 #1 diff --git a/packs/skills/MANIFEST-000002 b/packs/skills/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/skills/MANIFEST-000002 and /dev/null differ diff --git a/packs/skills/MANIFEST-000004 b/packs/skills/MANIFEST-000004 new file mode 100644 index 0000000..792e8a1 Binary files /dev/null and b/packs/skills/MANIFEST-000004 differ diff --git a/packs/slice/000003.log b/packs/slice/000003.log deleted file mode 100644 index 4a86fe9..0000000 Binary files a/packs/slice/000003.log and /dev/null differ diff --git a/packs/slice/000005.ldb b/packs/slice/000005.ldb new file mode 100644 index 0000000..4851c77 Binary files /dev/null and b/packs/slice/000005.ldb differ diff --git a/packs/slice/000006.log b/packs/slice/000006.log new file mode 100644 index 0000000..c7d9b16 Binary files /dev/null and b/packs/slice/000006.log differ diff --git a/packs/slice/CURRENT b/packs/slice/CURRENT index 1a84852..cacca75 100644 --- a/packs/slice/CURRENT +++ b/packs/slice/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/slice/LOG b/packs/slice/LOG index f3f0f86..c683f39 100644 --- a/packs/slice/LOG +++ b/packs/slice/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.972924 16ef6f000 Delete type=3 #1 +2026/08/11-09:44:12.202502 171fd7000 Recovering log #3 +2026/08/11-09:44:12.202661 171fd7000 Level-0 table #5: started +2026/08/11-09:44:12.202854 171fd7000 Level-0 table #5: 16892 bytes OK +2026/08/11-09:44:12.203092 171fd7000 Delete type=0 #3 +2026/08/11-09:44:12.203146 171fd7000 Delete type=3 #2 diff --git a/packs/slice/LOG.old b/packs/slice/LOG.old new file mode 100644 index 0000000..39b83ea --- /dev/null +++ b/packs/slice/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:10.002176 173a8b000 Delete type=3 #1 diff --git a/packs/slice/MANIFEST-000002 b/packs/slice/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/slice/MANIFEST-000002 and /dev/null differ diff --git a/packs/slice/MANIFEST-000004 b/packs/slice/MANIFEST-000004 new file mode 100644 index 0000000..0552c3a Binary files /dev/null and b/packs/slice/MANIFEST-000004 differ diff --git a/packs/tables/000003.log b/packs/tables/000003.log deleted file mode 100644 index f125b7d..0000000 Binary files a/packs/tables/000003.log and /dev/null differ diff --git a/packs/tables/000005.ldb b/packs/tables/000005.ldb new file mode 100644 index 0000000..64baa1c Binary files /dev/null and b/packs/tables/000005.ldb differ diff --git a/packs/tables/000006.log b/packs/tables/000006.log new file mode 100644 index 0000000..d5e06f3 Binary files /dev/null and b/packs/tables/000006.log differ diff --git a/packs/tables/CURRENT b/packs/tables/CURRENT index 1a84852..cacca75 100644 --- a/packs/tables/CURRENT +++ b/packs/tables/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/tables/LOG b/packs/tables/LOG index 31ac16d..925bb72 100644 --- a/packs/tables/LOG +++ b/packs/tables/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.971218 16e763000 Delete type=3 #1 +2026/08/11-09:44:12.203885 1737fb000 Recovering log #3 +2026/08/11-09:44:12.204195 1737fb000 Level-0 table #5: started +2026/08/11-09:44:12.204288 1737fb000 Level-0 table #5: 3739 bytes OK +2026/08/11-09:44:12.204494 1737fb000 Delete type=0 #3 +2026/08/11-09:44:12.204520 1737fb000 Delete type=3 #2 diff --git a/packs/tables/LOG.old b/packs/tables/LOG.old new file mode 100644 index 0000000..c707369 --- /dev/null +++ b/packs/tables/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:10.000153 172267000 Delete type=3 #1 diff --git a/packs/tables/MANIFEST-000002 b/packs/tables/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/tables/MANIFEST-000002 and /dev/null differ diff --git a/packs/tables/MANIFEST-000004 b/packs/tables/MANIFEST-000004 new file mode 100644 index 0000000..004ff30 Binary files /dev/null and b/packs/tables/MANIFEST-000004 differ diff --git a/packs/talents/000003.log b/packs/talents/000003.log deleted file mode 100644 index 443b7ea..0000000 Binary files a/packs/talents/000003.log and /dev/null differ diff --git a/packs/talents/000005.ldb b/packs/talents/000005.ldb new file mode 100644 index 0000000..fb653de Binary files /dev/null and b/packs/talents/000005.ldb differ diff --git a/packs/talents/000006.log b/packs/talents/000006.log new file mode 100644 index 0000000..29003f7 Binary files /dev/null and b/packs/talents/000006.log differ diff --git a/packs/talents/CURRENT b/packs/talents/CURRENT index 1a84852..cacca75 100644 --- a/packs/talents/CURRENT +++ b/packs/talents/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/talents/LOG b/packs/talents/LOG index 730ff0a..7c30526 100644 --- a/packs/talents/LOG +++ b/packs/talents/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.942298 16ff87000 Delete type=3 #1 +2026/08/11-09:44:12.191930 172fef000 Recovering log #3 +2026/08/11-09:44:12.192079 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.192222 172fef000 Level-0 table #5: 5770 bytes OK +2026/08/11-09:44:12.192448 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.192478 172fef000 Delete type=3 #2 diff --git a/packs/talents/LOG.old b/packs/talents/LOG.old new file mode 100644 index 0000000..f94ab50 --- /dev/null +++ b/packs/talents/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.976561 172267000 Delete type=3 #1 diff --git a/packs/talents/MANIFEST-000002 b/packs/talents/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/talents/MANIFEST-000002 and /dev/null differ diff --git a/packs/talents/MANIFEST-000004 b/packs/talents/MANIFEST-000004 new file mode 100644 index 0000000..f8c6b47 Binary files /dev/null and b/packs/talents/MANIFEST-000004 differ diff --git a/packs/vehicles/000003.log b/packs/vehicles/000003.log deleted file mode 100644 index 9950ce5..0000000 Binary files a/packs/vehicles/000003.log and /dev/null differ diff --git a/packs/vehicles/000005.ldb b/packs/vehicles/000005.ldb new file mode 100644 index 0000000..f6b2cd4 Binary files /dev/null and b/packs/vehicles/000005.ldb differ diff --git a/packs/vehicles/000006.log b/packs/vehicles/000006.log new file mode 100644 index 0000000..47800e2 Binary files /dev/null and b/packs/vehicles/000006.log differ diff --git a/packs/vehicles/CURRENT b/packs/vehicles/CURRENT index 1a84852..cacca75 100644 --- a/packs/vehicles/CURRENT +++ b/packs/vehicles/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/vehicles/LOG b/packs/vehicles/LOG index 3c3d6b6..659986e 100644 --- a/packs/vehicles/LOG +++ b/packs/vehicles/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.951942 16e763000 Delete type=3 #1 +2026/08/11-09:44:12.199441 1737fb000 Recovering log #3 +2026/08/11-09:44:12.199690 1737fb000 Level-0 table #5: started +2026/08/11-09:44:12.199821 1737fb000 Level-0 table #5: 6939 bytes OK +2026/08/11-09:44:12.200021 1737fb000 Delete type=0 #3 +2026/08/11-09:44:12.200051 1737fb000 Delete type=3 #2 diff --git a/packs/vehicles/LOG.old b/packs/vehicles/LOG.old new file mode 100644 index 0000000..9adb7a1 --- /dev/null +++ b/packs/vehicles/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.983507 172267000 Delete type=3 #1 diff --git a/packs/vehicles/MANIFEST-000002 b/packs/vehicles/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/vehicles/MANIFEST-000002 and /dev/null differ diff --git a/packs/vehicles/MANIFEST-000004 b/packs/vehicles/MANIFEST-000004 new file mode 100644 index 0000000..d4d73b7 Binary files /dev/null and b/packs/vehicles/MANIFEST-000004 differ diff --git a/packs/weapons/000003.log b/packs/weapons/000003.log deleted file mode 100644 index e1488ed..0000000 Binary files a/packs/weapons/000003.log and /dev/null differ diff --git a/packs/weapons/000005.ldb b/packs/weapons/000005.ldb new file mode 100644 index 0000000..742beba Binary files /dev/null and b/packs/weapons/000005.ldb differ diff --git a/packs/weapons/000006.log b/packs/weapons/000006.log new file mode 100644 index 0000000..4d427a6 Binary files /dev/null and b/packs/weapons/000006.log differ diff --git a/packs/weapons/CURRENT b/packs/weapons/CURRENT index 1a84852..cacca75 100644 --- a/packs/weapons/CURRENT +++ b/packs/weapons/CURRENT @@ -1 +1 @@ -MANIFEST-000002 +MANIFEST-000004 diff --git a/packs/weapons/LOG b/packs/weapons/LOG index 7d206d0..0f6fdea 100644 --- a/packs/weapons/LOG +++ b/packs/weapons/LOG @@ -1 +1,5 @@ -2026/08/11-08:56:03.945178 16ef6f000 Delete type=3 #1 +2026/08/11-09:44:12.194742 172fef000 Recovering log #3 +2026/08/11-09:44:12.195028 172fef000 Level-0 table #5: started +2026/08/11-09:44:12.195244 172fef000 Level-0 table #5: 14767 bytes OK +2026/08/11-09:44:12.195470 172fef000 Delete type=0 #3 +2026/08/11-09:44:12.195499 172fef000 Delete type=3 #2 diff --git a/packs/weapons/LOG.old b/packs/weapons/LOG.old new file mode 100644 index 0000000..33e5276 --- /dev/null +++ b/packs/weapons/LOG.old @@ -0,0 +1 @@ +2026/08/11-09:43:09.978238 17327f000 Delete type=3 #1 diff --git a/packs/weapons/MANIFEST-000002 b/packs/weapons/MANIFEST-000002 deleted file mode 100644 index bbbc585..0000000 Binary files a/packs/weapons/MANIFEST-000002 and /dev/null differ diff --git a/packs/weapons/MANIFEST-000004 b/packs/weapons/MANIFEST-000004 new file mode 100644 index 0000000..6a582af Binary files /dev/null and b/packs/weapons/MANIFEST-000004 differ diff --git a/ringbrp.mjs b/ringbrp.mjs index 4528d02..42082b4 100644 --- a/ringbrp.mjs +++ b/ringbrp.mjs @@ -32,7 +32,7 @@ import { FALL, fallDamageFor, ASPHYXIA, breathRoundsFor, FIRE, fireBandFor, BLAST, blastBandFor, blastShareFor, BLAST_COVER, blastAfterCover, BURST, burstHitsFor, burstRoundsSpent, BURST_FUMBLE, BURST_ONE_MAJOR_WOUND, - BURST_HITS, + BURST_HITS, LAMP, lampReachFor, lampCovers, FIRE_MODE, fireModeFor, burstSizesFor, fireModeAttackFor, secondShotPenaltyFor, SUSTAIN, sustainDamageFor, sustainChargeFor, SIGHT, sightFor, sightBonusFor, sightSeesInDark, @@ -887,11 +887,62 @@ export function sightForWeapon(actor, weapon) { /** Is this agent carrying something lit? Lamps are gear, not a checkbox. */ export function carriedLight(actor) { + let best = { on: false, source: "", reachM: 0 }; for (const it of actor?.items ?? []) { if (it.system?.carried === false) continue; - if (it.system?.lightSource) return { on: true, source: it.name }; + if (!it.system?.lightSource) continue; + const reachM = lampReachFor(it.system.lightReachM); + // Two lamps is not twice the light, but the longer one is the one you are using. + if (reachM > best.reachM) best = { on: true, source: it.name, reachM }; } - return { on: false, source: "" }; + return best; +} + +/** Metres between two tokens, in the scene's own units. Null when it cannot be known. */ +function metresBetween(a, b) { + if (!a || !b || !canvas?.ready || !canvas.grid?.size) return null; + const dx = a.center.x - b.center.x, dy = a.center.y - b.center.y; + const px = Math.hypot(dx, dy); + const d = (px / canvas.grid.size) * (canvas.grid.distance || 1); + return Number.isFinite(d) ? d : null; +} + +function tokenFor(actor) { + if (!actor) return null; + const t = actor.getActiveTokens?.(true, false) ?? []; + return t[0] ?? actor.token?.object ?? null; +} + +/** + * The light this agent is actually standing in — theirs or somebody else's. + * + * A lamp used to light exactly one person, and played out that put three agents + * inside the same pool shooting at −50% while the fourth, an arm's length away, shot + * at −10%. A lamp has a reach now, and anyone inside it is in the light. + * + * Measured from the tokens, because the canvas already knows who is standing where. + * When there are no tokens the distance is genuinely unknown, and an unknown distance + * is NOT lit — the dialog offers the GM the tick instead, rather than this quietly + * lighting a whole scene that nobody has placed. + */ +export function lightOn(actor) { + const own = carriedLight(actor); + if (own.on) return { ...own, own: true, distanceM: 0 }; + const me = tokenFor(actor); + if (!me) return { on: false, source: "", reachM: 0, own: false, distanceM: null }; + let best = null; + for (const t of canvas.tokens?.placeables ?? []) { + if (t === me || !t.actor) continue; + const lamp = carriedLight(t.actor); + if (!lamp.on) continue; + const d = metresBetween(me, t); + if (!lampCovers(d, lamp.reachM)) continue; + if (!best || d < best.distanceM) { + best = { on: true, source: lamp.name ?? lamp.source, reachM: lamp.reachM, + own: false, distanceM: d, holder: t.actor.name }; + } + } + return best ?? { on: false, source: "", reachM: 0, own: false, distanceM: null }; } /** @@ -5611,7 +5662,7 @@ async function promptAttackOptions({ weapon, actor }) { // and the lamp by whether anything carried is lit — neither is a thing the player // selects, because both are facts about the pack rather than about the shot. const sight = sightForWeapon(actor, weapon); - const lamp = carriedLight(actor); + const lamp = lightOn(actor); const kit = []; if (sight.id !== "none") { const bands = sightFor(sight.id).bands; @@ -5621,12 +5672,14 @@ async function promptAttackOptions({ weapon, actor }) { .join(" · ") }); } if (lamp.on) { - kit.push({ name: lamp.source, effect: game.i18n.localize("RINGBRP.Sight.LampEffect") }); + kit.push({ name: lamp.source, effect: game.i18n.format( + lamp.own ? "RINGBRP.Sight.LampOwn" : "RINGBRP.Sight.LampNear", + { holder: lamp.holder ?? "", m: Math.round(lamp.distanceM ?? 0), reach: lamp.reachM }) }); } const content = await rbRenderTemplate("systems/ringbrp/templates/dialog-attack.hbs", { RINGBRP, weapon, isRanged: weapon.system.isRanged, ranges: weapon.system.ranges, - bandOptions, fire, kit }); + bandOptions, fire, kit, inLight: lamp.on, lampReach: lamp.reachM || LAMP.reachM }); return new Promise(resolve => { new (rbDialogClass())({ title: weapon.name, @@ -5691,13 +5744,17 @@ async function promptAttackOptions({ weapon, actor }) { } } // The dark, after the lamp and after a sight that does not need one. - const lit = lightingModFor(light, { lightSource: lamp.on, + // The tick is authoritative: it arrives already set when the canvas could + // measure it, and is the GM's answer when there are no tokens to measure. + const inLight = el.querySelector("[name=inlight]")?.checked ?? lamp.on; + const lit = lightingModFor(light, { lightSource: inLight, seesInDark: sightSeesInDark(sight.id) }); if (lit.mod) { mod += lit.mod; lines.push(`${game.i18n.localize(LIGHTING[lit.effective].label)} ${lit.mod}%`); } - if (lit.revealed) lines.push(game.i18n.format("RINGBRP.Sight.Revealed", { name: lamp.source })); + if (lit.revealed) lines.push(game.i18n.format("RINGBRP.Sight.Revealed", + { name: lamp.source || game.i18n.localize("RINGBRP.Sight.SomeLamp") })); const cv = RINGBRP.cover[cover]?.mod ?? 0; if (cv) { mod += cv; lines.push(`${game.i18n.localize(RINGBRP.cover[cover].label)} ${cv}%`); } @@ -6061,7 +6118,7 @@ Hooks.once("init", () => { addDossierItem, useAuthority, widenScope, rehabilitate, tickDying, died, stabilise, reviveIfHealed, conditionFor, dyingLimitFor, fall, asphyxiate, burn, detonate, burstAttack, twoWeaponAttack, - sightForWeapon, carriedLight, fireModeFor, burstSizesFor, sustainDamageFor, + sightForWeapon, carriedLight, lightOn, fireModeFor, burstSizesFor, sustainDamageFor, manStation, bestStationFor, STATIONS, SPACE_BANDS, heatEffectsFor, craftConditionFor, spaceBandAfter, fallDamageFor, breathRoundsFor, fireBandFor, blastBandFor, burstHitsFor, @@ -6104,7 +6161,8 @@ async function migrateFittedGear() { const key = doc.flags?.ringbrp?.key; if (!key) continue; if (doc.system?.optic?.kind || doc.system?.lightSource) { - canon.set(key, { optic: doc.system.optic, lightSource: !!doc.system.lightSource }); + canon.set(key, { optic: doc.system.optic, lightSource: !!doc.system.lightSource, + lightReachM: Number(doc.system.lightReachM) || 0 }); } } if (!canon.size) return 0; @@ -6118,9 +6176,11 @@ async function migrateFittedGear() { const want = canon.get(it.flags?.ringbrp?.key); if (!want) continue; const stale = (it.system.optic?.kind ?? "") !== (want.optic?.kind ?? "") - || !!it.system.lightSource !== want.lightSource; + || !!it.system.lightSource !== want.lightSource + || (Number(it.system.lightReachM) || 0) !== want.lightReachM; if (stale) updates.push({ _id: it.id, "system.optic": want.optic, - "system.lightSource": want.lightSource }); + "system.lightSource": want.lightSource, + "system.lightReachM": want.lightReachM }); } if (updates.length) { await actor.updateEmbeddedDocuments("Item", updates); diff --git a/rules.mjs b/rules.mjs index fcfc9cd..4254bd5 100644 --- a/rules.mjs +++ b/rules.mjs @@ -730,6 +730,39 @@ export const LIGHTING = { /** A lamp never makes it daylight. This is the best it gets you. */ export const LIGHT_FLOOR = "dim"; +/** + * HOW FAR A LAMP THROWS. + * + * A lamp used to light exactly one person: the one holding it. Played out, that put + * three agents standing inside the same pool of light shooting at −50% while the + * fourth, an arm's length away, shot at −10%. Nobody would run that at a table. + * + * So a lamp has a REACH, and anyone inside it is in the light — including the people + * it is showing to whatever is out there, which is the half of the rule that costs + * something. The reach is per item, because a weapon lamp and a roof searchlight are + * not the same offer. + */ +export const LAMP = { reachM: 10 }; + +export function lampReachFor(reachM) { + const r = Number(reachM); + return r > 0 ? r : LAMP.reachM; +} + +/** + * Is this person inside that lamp's pool? Distance in metres, as everything else is. + * + * An UNKNOWN distance is not "in the light". `Number(null)` is 0, so a missing + * measurement would otherwise read as standing on top of the lamp and light the whole + * scene for free — which is precisely the failure this rule exists to correct. + */ +export function lampCovers(distanceM, reachM) { + if (distanceM === null || distanceM === undefined || distanceM === "") return false; + const d = Number(distanceM); + if (!Number.isFinite(d) || d < 0) return false; + return d <= lampReachFor(reachM); +} + export function lightingFor(id) { return LIGHTING[id] || LIGHTING.lit; } diff --git a/template.json b/template.json index 27741fc..5547c9f 100644 --- a/template.json +++ b/template.json @@ -256,7 +256,8 @@ "kind": "", "fits": "any" }, - "lightSource": false + "lightSource": false, + "lightReachM": 0 }, "device": { "templates": [ diff --git a/templates/dialog-attack.hbs b/templates/dialog-attack.hbs index 2a8845f..0bb4684 100644 --- a/templates/dialog-attack.hbs +++ b/templates/dialog-attack.hbs @@ -38,6 +38,10 @@ {{/each}} +
+ +

{{localize "RINGBRP.Dialog.InLightHint"}}

+
diff --git a/tools/build-packs.mjs b/tools/build-packs.mjs index ea4c8da..c7f40cd 100644 --- a/tools/build-packs.mjs +++ b/tools/build-packs.mjs @@ -122,6 +122,7 @@ function gearItem(g) { // facts about what is in the pack rather than choices made at the trigger. optic: { kind: g.optic ?? "", fits: g.fits ?? "any" }, lightSource: !!g.lit, + lightReachM: g.lit ? (g.reach ?? 10) : 0, isAnchor: /anchor/i.test(g.name) }, effects: [], ...BASE(), diff --git a/tools/check-rules.mjs b/tools/check-rules.mjs index 182f63a..c5213c9 100644 --- a/tools/check-rules.mjs +++ b/tools/check-rules.mjs @@ -284,6 +284,14 @@ const checks = [ ["sightFor(nonsense) is none", RULES.sightFor("wat").id, "none"], ["sightSeesInDark(thermal)", RULES.sightSeesInDark("thermal"), true], ["sightSeesInDark(telescopic)", RULES.sightSeesInDark("telescopic"), false], + // A lamp lights the people NEXT to you, not only the one holding it. + ["lampReachFor(default)", RULES.lampReachFor(), 10], + ["lampReachFor(30) searchlight", RULES.lampReachFor(30), 30], + ["lampReachFor(0) falls to default", RULES.lampReachFor(0), 10], + ["lampCovers(4, reach 6)", RULES.lampCovers(4, 6), true], + ["lampCovers(9, reach 6)", RULES.lampCovers(9, 6), false], + ["lampCovers(10, reach 10) inclusive", RULES.lampCovers(10, 10), true], + ["lampCovers(unknown distance)", RULES.lampCovers(null, 10), false], // A lamp buys the dark back to dim, never to daylight, and it shows you. ["lightingFor(pitch).mod", RULES.lightingFor("pitch").mod, -50], ["lightingModFor(pitch, no lamp)", RULES.lightingModFor("pitch").mod, -50], diff --git a/tools/content.mjs b/tools/content.mjs index c9501bc..4d793f8 100644 --- a/tools/content.mjs +++ b/tools/content.mjs @@ -316,7 +316,7 @@ export const GEAR = [ { key: "anchor", name: "Personal anchor", mass: 0.1, desc: "Something that remembers you as you were. Restores 1 Coherence per period of downtime spent with it." }, { key: "key", name: "Crossing key", mass: 0.4, trad: "tradition_transposed", coherence: 1, desc: "Opens a path without a scheduled window. Costs 1 Coherence each time it is used." }, /* --- standard agency issue: what every case draws from stores --- */ - { key: "torch", name: "Field lamp", mass: 0.5, lit: true, desc: "Sealed, sixty hours. Nothing on the far side is reliably lit. Buys the dark back to dim, and tells the dark where you are." }, + { key: "torch", name: "Field lamp", mass: 0.5, lit: true, reach: 10, desc: "Sealed, sixty hours. Lights ten metres of whatever this is — you and anyone standing in it with you. Buys the dark back to dim, and tells the dark exactly where all of you are." }, { key: "rope", name: "Line and harness", mass: 3.5, bonus: { fam: "athletics", value: 20 }, desc: "+20% Athletics for any climb or descent." }, { key: "rations", name: "Ration pack (3 days)", mass: 2.4, desc: "Restores 1 Resource to the case when shared by the whole team." }, { key: "water", name: "Filter flask", mass: 0.9, desc: "Makes almost anything drinkable. Almost." }, @@ -393,7 +393,7 @@ export const GEAR = [ desc: "-10% short, +5% medium, +15% long, +20% extreme. Rifles only. The penalty up close is the whole point of it." }, { key: "sight_thermal", name: "Thermal sight", mass: 1.1, optic: "thermal", fits: "rifle", era: "future", desc: "+5% out to long range, and the dark stops mattering — without a lamp to announce you. Rifles only." }, - { key: "weapon_lamp", name: "Weapon lamp", mass: 0.2, lit: true, + { key: "weapon_lamp", name: "Weapon lamp", mass: 0.2, lit: true, reach: 6, desc: "Clamps under the barrel. Buys the dark back to dim, and points at whatever you are pointing at." }, /* --- looking at things --- */ @@ -433,7 +433,7 @@ export const GEAR = [ /* --- FUTURE: brought back from somewhere ahead --- */ { key: "wound_foam", name: "Wound foam", mass: 0.4, era: "future", desc: "Seals and packs a wound in four seconds. Getting it out again is a hospital's problem." }, - { key: "cold_light", name: "Cold light strips", mass: 0.3, era: "future", desc: "Twelve strips, forty hours each, no heat and no battery. Mark your route in." }, + { key: "cold_light", name: "Cold light strips", mass: 0.3, era: "future", lit: true, reach: 4, desc: "Twelve strips, forty hours each, no heat and no battery. Four metres — your own hands and whoever is beside you. Mark your route in." }, { key: "field_slate", name: "Field slate", mass: 0.5, era: "future", desc: "Reads, writes and files. Will not connect to anything here, which Registry considers a feature." }, { key: "locator_tags", name: "Locator tags", mass: 0.2, era: "future", desc: "Twenty. Tag a person, a door, or a thing you intend to find again." }, { key: "density_scanner", name: "Handheld density scanner", mass: 1.1, era: "future", desc: "Reads through two metres of brick. Reads nothing at all through a crossing." }, @@ -456,7 +456,7 @@ export const GEAR = [ { key: "vehicle_spares", name: "Vehicle spares roll", mass: 5.1, desc: "Belts, hose, fuses, wire and tape. A Repair (Mechanical) roll has something to work with." }, { key: "wheel_clamps", name: "Wheel clamps", mass: 7.0, desc: "Stops a vehicle leaving. Occasionally stops one that was not going to be driven." }, { key: "vehicle_log", name: "Vehicle log book", mass: 0.3, desc: "Mileage, driver, and purpose of journey. The single most audited document in the department." }, - { key: "roof_lamp", name: "Roof searchlight", mass: 4.5, desc: "Clamps to a roof rail and runs off the vehicle. Lights a field, and tells the field where you are." }, + { key: "roof_lamp", name: "Roof searchlight", mass: 4.5, lit: true, reach: 30, desc: "Clamps to a roof rail and runs off the vehicle. Thirty metres, and everyone standing in it — and it tells the field where all of you are." }, { key: "recovery_strop", name: "Recovery strop", mass: 3.2, desc: "Webbing, not steel — it does not whip when it parts. The department learned this the expensive way." }, /* ------------------------------------------------------------------ diff --git a/tools/rules-text.mjs b/tools/rules-text.mjs index c0dd5c2..a2c0d74 100644 --- a/tools/rules-text.mjs +++ b/tools/rules-text.mjs @@ -22,7 +22,7 @@ import { DYING, dyingLimitFor, LAST_ENTRY, FALL, fallDamageFor, ASPHYXIA, breathRoundsFor, FIRE, BLAST, BLAST_COVER, BURST, burstHitsFor, TWO_WEAPON, twoWeaponPenaltyFor, - FIRE_MODE, SECOND_SHOT, SUSTAIN, SIGHT, LIGHTING, LIGHT_FLOOR, + FIRE_MODE, SECOND_SHOT, SUSTAIN, SIGHT, LIGHTING, LIGHT_FLOOR, LAMP, STATIONS, SPACE_BANDS, SPACE_RANGE_MOD, HEAT, heatEffectsFor, spaceHitFor, powerStartingRating, brawlFallbackFor, bleedStoppedBy, crossingArtPoolFor, crossingGrantsArt, crossingCostFor, @@ -371,10 +371,16 @@ bolted to a service pistol.

The dark

Most crossings do not come with the lights on.

${table(["", "To hit"], Object.values(LIGHTING).map(l => [L(l.label), pc(l.mod)]))} -

A carried lamp buys the dark back to ${L(LIGHTING[LIGHT_FLOOR].label)} -and never better — and it is a position. The card will say so. A thermal sight removes -the dark outright and does not announce you, which is most of what you are -paying its weight for.

+

A lamp buys the dark back to ${L(LIGHTING[LIGHT_FLOOR].label)} and +never better — and it is a position. The card will say so.

+

A lamp lights everyone standing in it, not only the person holding +it. Each one has a reach: ${LAMP.reachM} metres for the issue field lamp, less for a +weapon lamp, a great deal more for a vehicle searchlight. Anyone inside that reach is +in the light, with everything that means in both directions — the pool is one position +and the whole group is standing in it. If your tokens are on the map the game works +this out for you; if they are not, the attack dialog asks.

+

A thermal sight removes the dark outright and does not announce you, which +is most of what you are paying its weight for.

Automatic fire

One roll, not four. The success level says how much of the burst