diff --git a/docs/REVIEW_LOG.md b/docs/REVIEW_LOG.md index 9792145..25a41a2 100644 --- a/docs/REVIEW_LOG.md +++ b/docs/REVIEW_LOG.md @@ -4290,3 +4290,74 @@ measuring the wrong box. Also noted, not fixed: fourteen rules are imported into `ringbrp.mjs` and read nowhere in it. They are live rules with real readers in the rulebook generator and the guards, so this is dead *imports* rather than dead rules — but it is the same smell. + +## THE GOODS YARD — the four fire modes, side by side + +One agent per mode, all four trained to exactly 60%, so the fight reads the mode and +not the shooter. A barghest in a coal yard at 02:40, pitch dark, one lamp between +four of them. Four rounds. The dog left at 4 hit points of 16 and nobody caught it. + +**The modes separated cleanly, and not in the way I expected.** + +**Slow was the best weapon in the fight.** Dunn's Baker rifle hit on both the shots it +got, and the +10% is what bought them: round one at 35% he rolled 33, and at the 25% +he would have had without it that is a miss. The reload is a real cost — he was out of +the fight for rounds two and three and the dog reached him — but a mode that turns a +33 into a hit twice is not the weak option. + +**Fast is not two chances to hit. It is a second defence at a penalty.** Rakhi's two +Webley shots in round two both landed at 20%, and the first was dodged clean. The +second one hurt precisely because the barghest had already spent its free defence and +had to dodge again at −30%. That is the mode's actual function and it is better than +the tooltip suggests. + +**Rapid was the worst thing in the yard.** Ceyla fired 20 of 30 rounds across four +rounds of combat and hit nothing at all. A full magazine at −30%, in the dark at −30%, +is a 1% roll that still spends ten rounds — and the rules charge her honestly for +every one. This is not obviously wrong; automatic fire into a dark coal yard at +seventy metres *should* be futile. But it means **the burst options are close to +unselectable in any fight where the light is bad**, and the light is bad in most of +this game. Flagged rather than tuned: I would rather see it in a second fight before +touching the numbers. + +**Beam did the damage.** The locked beam landed for 10 — 1d4+6 with its 2d6 riding on +the standing blow exactly as designed — and took the barghest from 11 to 4 through +armour 3. It cost 6 charge a shot and, because the lance is transposed materiel, **1 +Coherence every time Tomas pulled the trigger**. He ended the fight Loose at 6, with 2 +charge left. That is the most interesting economy in the fight and nothing needed +changing to produce it. + +**The sight graded itself the way it was meant to.** Ceyla's telescopic sight was +5% +at seventy metres and **−10% once the thing was inside twenty-five**, and she felt it +both times. Nobody had to remember it. + +**The lamp is the finding.** Tomas's Field lamp turned pitch dark into dim for him — a +40-point swing, the largest single modifier in the fight — and the card told him each +time that it showed the barghest exactly where he was. Which it did: the dog went for +the lamp in round two. But **a lamp only lights its carrier**. Three agents stood +inside the same pool of light at −50% while the fourth shot at −10%. That is wrong at +the table, and it is the one design change this fight actually argues for. + +### Defects the fight surfaced + +**R-238. A fast action fired twice and paid for one round.** The Webley put two shots +out and the cylinder went down by one. Ammunition was charged once before the shot +loop instead of once per shot — the exact dishonesty the burst rules were written to +avoid, and the mode that ought to cost the most was the only one getting a free shot. +Charged per shot now, and the loop stops when the weapon runs dry mid-action. + +**R-239. `morale.downThreshold` is written by the pack builder and the template and +read by nothing.** Every NPC in the game carries a morale field and there is no morale +rule. Whether the barghest broke off was mine to decide with no support from the +system, which is fine as a GM call and not fine as a shipped field. Not fixed — it +needs a rule, not a patch. + +**Two of my own, worth recording because the pattern keeps repeating.** I did +arithmetic on `system.coherence` (an object) instead of `.value` and reported a +Coherence loss that never happened; and I read `system.hitPoints`, which does not +exist — the field is `system.hp`. Both were caught inside a minute by printing the +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. diff --git a/ringbrp.mjs b/ringbrp.mjs index 25d4e49..4528d02 100644 --- a/ringbrp.mjs +++ b/ringbrp.mjs @@ -5077,20 +5077,6 @@ class RingBRPCharacterSheet extends ActorSheet { situational: opts.situational, sizeModApplied: true, flavourLines: opts.lines }); } - // Ammunition (spec §4.5) - if (weapon.system.ammo?.capacity > 0) { - if ((weapon.system.ammo.loaded ?? 0) <= 0) { - ui.notifications.warn(game.i18n.localize("RINGBRP.Notify.Empty")); - return; - } - const cost = opts.sustain ? sustainChargeFor(opts.sustain) : 1; - if ((weapon.system.ammo.loaded ?? 0) < cost) { - ui.notifications.warn(game.i18n.localize("RINGBRP.Notify.NotEnoughCharge")); - return; - } - await weapon.update({ "system.ammo.loaded": weapon.system.ammo.loaded - cost }); - } - // The second shot a fast action gives you. Both shots are worse, which is the // whole cost, and it is once per round — which is what `secondAttackUsed` was // reset for every round without anything ever setting it. @@ -5103,8 +5089,29 @@ class RingBRPCharacterSheet extends ActorSheet { await this.actor.update({ "system.combat.secondAttackUsed": true }); } + // Ammunition (spec §4.5). Charged PER SHOT, inside the loop — a fast action that + // fires twice and pays once is the exact dishonesty the burst rules were written + // to avoid, and a Webley firing two rounds off one chamber was what it looked + // like at the table. + const perShot = opts.sustain ? sustainChargeFor(opts.sustain) : 1; + const spend = async () => { + if (!(weapon.system.ammo?.capacity > 0)) return true; + const loaded = weapon.system.ammo.loaded ?? 0; + if (loaded <= 0) { + ui.notifications.warn(game.i18n.localize("RINGBRP.Notify.Empty")); + return false; + } + if (loaded < perShot) { + ui.notifications.warn(game.i18n.localize("RINGBRP.Notify.NotEnoughCharge")); + return false; + } + await weapon.update({ "system.ammo.loaded": loaded - perShot }); + return true; + }; + let res = null; for (let i = 0; i < shots; i++) { + if (!await spend()) break; res = await skillRoll({ actor: this.actor, label: shots > 1 ? `${weapon.name} (${i + 1}/${shots})` : weapon.name,