Shields: armour you raise, and the only armour you can defend with
A shield is the one piece of armour you hold, and it protects you exactly as much as you are currently holding it up. Raised, its points apply to what it covers and it can parry on a new Shield skill. Lowered, it is weight. The price of keeping it up is that it occupies a hand and you are shooting around it: -20% to your own ranged attacks, printed on the card like everything else. Only one shield goes up at a time. Seven of them, 2-point buckler to 6-point ballistic shield; the pavise and barrier plate cover legs too because they are walls you carry. `degradation` finally does something — it has been on every armour item since the packs were first built and was read by nothing. A blow costs the shield a point of wear for every step it stood above an ordinary success, so an ordinary hit costs nothing, a special 1 and a critical 2. At its limit it comes apart, drops, and will not be raised again. Two defects found by driving the real functions rather than reading the diff, both introduced by this change: - Every shield defence quietly rolled DODGE. "shield" passed through defenceTypeAllowed unchanged, so neither parry branch matched and it fell through. Invisible in the card; it showed up as eight rolls at a supposed 85% returning six failures. Taking a blow on the shield IS a parry, so it is now a flag on a parry rather than a defence type of its own. - The wear rule was unreachable: it fired only on a clean stop, but under graded defences only a critical fully stops a critical, so a shield would never have taken a scratch. Wear is for what the shield ABSORBED — dragging a critical down to a special is exactly when shields splinter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@@ -4521,3 +4521,52 @@ on the first attempt and landed on the second, staunched the bleeding, healed 3,
|
||||
`reviveIfHealed` took Plated out of the dying state without being asked. My harness
|
||||
then called `tickDying` on a revived character and read `.state` off the null it
|
||||
correctly returned — the rule was right and the probe was wrong.
|
||||
|
||||
## Shields — armour with a switch
|
||||
|
||||
A shield is the one piece of armour you *hold*, and it protects you exactly as much as
|
||||
you are currently holding it up. Everything interesting follows from that switch
|
||||
having a cost, so the design is: raised it is armour and a defence, lowered it is
|
||||
weight, and the price of keeping it up is that it occupies a hand and you are shooting
|
||||
around it.
|
||||
|
||||
* **Raised** — its points apply to what it covers, and it is the only armour you can
|
||||
also defend with, on a new **Shield** skill.
|
||||
* **Lowered** — nothing. Verified: heater shield slung reads 0 on every location,
|
||||
raised reads 4 on torso and both arms and 0 on legs and head.
|
||||
* **The cost** — −20% to your own ranged attacks while it is up, printed on
|
||||
the card as plainly as anything else: *"Heater shield −20%"*. That is what stops
|
||||
"always raised" being the only answer; it is obviously right for a containment
|
||||
officer and obviously wrong for a marksman.
|
||||
* **Only one goes up.** Raising a second lowers the first. Two shields is not a stance.
|
||||
|
||||
Seven of them, from a 2-point buckler to a 6-point ballistic shield, with the pavise
|
||||
and the barrier plate covering legs as well because they are walls you carry.
|
||||
|
||||
**`degradation` finally does something.** It has been on every armour item since the
|
||||
packs were first built and was read by nothing. Shields wear: a blow costs the shield a
|
||||
point for every step the attack stood above an ordinary success, so an ordinary hit
|
||||
costs it nothing, a special costs 1 and a critical costs 2. At its limit it comes apart
|
||||
— no points, nothing to parry with, and it drops out of your hand and refuses to be
|
||||
raised again.
|
||||
|
||||
### Two defects found by testing it rather than reading it
|
||||
|
||||
**R-244. Every shield defence quietly rolled Dodge.** I added `"shield"` as a third
|
||||
defence type and passed it through `defenceTypeAllowed`, which returned it unchanged —
|
||||
so `kind` was `"shield"`, neither of the `kind === "parry"` branches matched, and the
|
||||
function fell through to the dodge branch. It was invisible in the chat card and only
|
||||
showed up as a statistical smell: eight rolls at a supposed 85% produced six failures.
|
||||
Taking a blow on the shield **is** a parry — it locks with parries and is not a dodge —
|
||||
so the shield is a flag on a parry rather than a type of its own.
|
||||
|
||||
**R-245. The wear rule was unreachable.** I first wrote it to fire only when the shield
|
||||
turned a blow aside *completely*. But under graded defences only a critical fully stops
|
||||
a critical, so a shield would have gone its entire service life without a scratch. Wear
|
||||
is for what the shield **absorbed**: a shield that drags a critical down to a special
|
||||
has very much taken that blow, and that is exactly when shields splinter. Ten forced
|
||||
criticals produced zero wear under the first rule; under the corrected one the shield
|
||||
went 0 → 2 → 4 → broken in three absorbed blows.
|
||||
|
||||
Both were mine, both were introduced in this change, and both were found by driving the
|
||||
real functions rather than by reading the diff.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(197 62% 34%)"/>
|
||||
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(197 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 14l38 12v34c0 30-16 48-38 58-22-10-38-28-38-58V26z" fill="hsl(197 90% 88%)" stroke="none"/>
|
||||
<path d="M64 14v104 M30 52h68" fill="none" stroke="hsl(197 70% 46%)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 510 B |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(249 62% 34%)"/>
|
||||
<path d="M96 0H128v32z" fill="hsl(249 80% 64%)" opacity="0.55"/>
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(249 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 14l38 12v34c0 30-16 48-38 58-22-10-38-28-38-58V26z" fill="hsl(249 90% 88%)" stroke="none"/>
|
||||
<path d="M64 14v104 M30 52h68" fill="none" stroke="hsl(249 70% 46%)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
<path d="M12 102h104" stroke="hsl(249 80% 64%)" stroke-width="2" opacity="0.7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 654 B |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(227 38% 30%)"/>
|
||||
<path d="M0 0h30L0 30z" fill="hsl(227 44% 22%)"/>
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(227 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 20a44 44 0 1 1 0 88 44 44 0 0 1 0-88z" fill="hsl(227 55% 82%)" stroke="none"/>
|
||||
<path d="M64 50a14 14 0 1 1 0 28 14 14 0 0 1 0-28z" fill="hsl(227 40% 52%)" stroke="none"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 503 B |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(211 38% 30%)"/>
|
||||
<path d="M0 0h30L0 30z" fill="hsl(211 44% 22%)"/>
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(211 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 14l38 12v34c0 30-16 48-38 58-22-10-38-28-38-58V26z" fill="hsl(211 55% 82%)" stroke="none"/>
|
||||
<path d="M64 14v104 M30 52h68" fill="none" stroke="hsl(211 40% 52%)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 559 B |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(179 38% 30%)"/>
|
||||
<path d="M0 0h30L0 30z" fill="hsl(179 44% 22%)"/>
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(179 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 14l38 12v34c0 30-16 48-38 58-22-10-38-28-38-58V26z" fill="hsl(179 55% 82%)" stroke="none"/>
|
||||
<path d="M64 14v104 M30 52h68" fill="none" stroke="hsl(179 40% 52%)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 559 B |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(235 62% 34%)"/>
|
||||
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(235 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 14l38 12v34c0 30-16 48-38 58-22-10-38-28-38-58V26z" fill="hsl(235 90% 88%)" stroke="none"/>
|
||||
<path d="M64 14v104 M30 52h68" fill="none" stroke="hsl(235 70% 46%)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 510 B |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
||||
<rect width="128" height="128" rx="20" fill="hsl(191 38% 30%)"/>
|
||||
<path d="M0 0h30L0 30z" fill="hsl(191 44% 22%)"/>
|
||||
<rect x="5" y="5" width="118" height="118" rx="16" fill="none" stroke="hsl(191 80% 64%)" stroke-width="4"/>
|
||||
<path d="M64 20a44 44 0 1 1 0 88 44 44 0 0 1 0-88z" fill="hsl(191 55% 82%)" stroke="none"/>
|
||||
<path d="M64 50a14 14 0 1 1 0 28 14 14 0 0 1 0-28z" fill="hsl(191 40% 52%)" stroke="none"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 503 B |
@@ -893,5 +893,19 @@
|
||||
"RINGBRP.Coverage.head": "head",
|
||||
"RINGBRP.Sheet.Unarmoured": "bare",
|
||||
"RINGBRP.Sheet.ByLocation": "by location",
|
||||
"RINGBRP.Item.Coverage": "Covers"
|
||||
"RINGBRP.Item.Coverage": "Covers",
|
||||
"RINGBRP.Shield.Raised": "raised — {n} points where it covers",
|
||||
"RINGBRP.Shield.InTheWay": "raised — you are shooting around it ({mod}%)",
|
||||
"RINGBRP.Shield.Wear": "{name} takes the blow — {n}/{max}",
|
||||
"RINGBRP.Shield.Broken": "{name} comes apart. {n}/{max} — it is firewood.",
|
||||
"RINGBRP.Sheet.RaiseHint": "Raise or lower this shield. Raised it protects what it covers and you can defend with it; lowered it is weight.",
|
||||
"RINGBRP.Sheet.ShieldUp": "raised",
|
||||
"RINGBRP.Sheet.ShieldDown": "slung",
|
||||
"RINGBRP.Sheet.ShieldBroken": "broken",
|
||||
"RINGBRP.Sheet.ShieldHint": "Take the blow on the shield. It wears against anything better than an ordinary hit.",
|
||||
"RINGBRP.Notify.ShieldBroken": "{name} is broken. It cannot be raised.",
|
||||
"RINGBRP.Item.IsShield": "Is a shield",
|
||||
"RINGBRP.Item.Raised": "Raised",
|
||||
"RINGBRP.Item.Wear": "Wear",
|
||||
"RINGBRP.Item.WearMax": "Breaks at"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.815927 175f73000 Recovering log #3
|
||||
2026/08/11-10:31:15.816054 175f73000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.816169 175f73000 Level-0 table #5: 3399 bytes OK
|
||||
2026/08/11-10:31:15.816387 175f73000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.816415 175f73000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.919810 17373b000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.321526 1714a3000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.827053 176f8b000 Recovering log #3
|
||||
2026/08/11-10:31:15.827202 176f8b000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.827356 176f8b000 Level-0 table #5: 4129 bytes OK
|
||||
2026/08/11-10:31:15.827638 176f8b000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.827685 176f8b000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.954955 173f47000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.359914 170c97000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.817069 177797000 Recovering log #3
|
||||
2026/08/11-10:31:15.817858 177797000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.818239 177797000 Level-0 table #5: 31614 bytes OK
|
||||
2026/08/11-10:31:15.818545 177797000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.818601 177797000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.921916 172723000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.323743 171caf000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.803065 177797000 Recovering log #3
|
||||
2026/08/11-10:31:15.804714 177797000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.806503 177797000 Level-0 table #5: 223539 bytes OK
|
||||
2026/08/11-10:31:15.806843 177797000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.806889 177797000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.938436 172723000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.341619 170c97000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.812365 175f73000 Recovering log #3
|
||||
2026/08/11-10:31:15.812699 175f73000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.812860 175f73000 Level-0 table #5: 3295 bytes OK
|
||||
2026/08/11-10:31:15.813123 175f73000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.813163 175f73000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.946701 172723000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.352685 170c97000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.799594 177797000 Recovering log #3
|
||||
2026/08/11-10:31:15.800464 177797000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.800988 177797000 Level-0 table #5: 58133 bytes OK
|
||||
2026/08/11-10:31:15.801383 177797000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.801428 177797000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.928648 172723000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.331121 1724bb000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.822560 176f8b000 Recovering log #3
|
||||
2026/08/11-10:31:15.823036 176f8b000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.823351 176f8b000 Level-0 table #5: 30975 bytes OK
|
||||
2026/08/11-10:31:15.823593 176f8b000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.823625 176f8b000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.951456 172f2f000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.357907 170c97000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.809540 175f73000 Recovering log #3
|
||||
2026/08/11-10:31:15.809752 175f73000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.809950 175f73000 Level-0 table #5: 7486 bytes OK
|
||||
2026/08/11-10:31:15.810216 175f73000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.810251 175f73000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.912459 172f2f000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.314145 1724bb000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.824364 17677f000 Recovering log #3
|
||||
2026/08/11-10:31:15.824536 17677f000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.824835 17677f000 Level-0 table #5: 16892 bytes OK
|
||||
2026/08/11-10:31:15.825060 17677f000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.825097 17677f000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.945043 17373b000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.350616 1714a3000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.825859 175f73000 Recovering log #3
|
||||
2026/08/11-10:31:15.825973 175f73000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.826082 175f73000 Level-0 table #5: 3739 bytes OK
|
||||
2026/08/11-10:31:15.826284 175f73000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.826314 175f73000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.943087 17373b000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.347262 1714a3000 Delete type=3 #1
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000004
|
||||
MANIFEST-000002
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
2026/08/11-10:31:15.810995 177797000 Recovering log #3
|
||||
2026/08/11-10:31:15.811100 177797000 Level-0 table #5: started
|
||||
2026/08/11-10:31:15.811254 177797000 Level-0 table #5: 5770 bytes OK
|
||||
2026/08/11-10:31:15.811516 177797000 Delete type=0 #3
|
||||
2026/08/11-10:31:15.811553 177797000 Delete type=3 #2
|
||||
2026/08/11-18:22:31.915613 173f47000 Delete type=3 #1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2026/08/11-10:29:47.318325 1724bb000 Delete type=3 #1
|
||||