Say the weapon's name once

A first-seen tin announced itself twice after a won duel: the modal that
teaches its rules, and then the delivery card right behind it, same title
same icon. weaponModal now reports whether it spoke, and the card (and the
barrel's flash) only speak when it didn't.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-05 10:07:28 +02:00
1 parent 24e4d23921
commit 1f22d3d5a0
2 files changed
+11 -7

No files matched your search

+8 -4
View File
@@ -594,24 +594,28 @@ export function deliverTin() {
aside('ump_new_balls_dark', 2.0); // "...and a new opponent, apparently."
// THE PRIZE GETS ITS OWN CARD, with the tin's own icon on it. It used to borrow G.flash — the
// same channel as PERFECT and DOUBLE KILL — so the one thing you played the duel FOR arrived as a
// word in the praise slot and read as another compliment. weaponModal still fires the first time
// a tin is seen (it has rules to teach); every time after, this card is the announcement, and it
// word in the praise slot and read as another compliment. The first time a tin is seen the modal
// announces it (and teaches its rules), so the card would be the SAME news twice, back to back —
// it only speaks when the modal doesn't. Every time after, the card is the announcement, and it
// does not want a tap: you have just won a point, not been asked a question.
if (!weaponModal(id))
G.card = { title: WEAPONS[id].label, sub1: 'DELIVERED TO THE RACK',
sub2: (WEAPONS[id].desc && WEAPONS[id].desc[0]) || '',
icon: WEAPONS[id].icon, color: UI.warm, t: TUNE.tinCardT };
weaponModal(id);
}
// The one-per-run "what this thing does" popup, shared by the duel ladder and the barrels.
// THE GATE LIVES HERE, not at the call sites. The barrels gated themselves and the tin ladder did
// not, so the four delivered weapons re-explained themselves every three games for a whole run
// while a barrel weapon explained itself once — the same popup behaving two different ways.
// Returns whether it actually announced, so a caller with its own announcement (the tin card, the
// barrel's flash) can stay quiet rather than say the same thing twice.
export function weaponModal(id) {
if (G.seen['w' + id]) return;
if (G.seen['w' + id]) return false;
G.seen['w' + id] = true;
const w = WEAPONS[id];
showModal({ title: w.label, body: w.desc, icon: w.icon, iconH: 40, color: UI.warm });
return true;
}
// ---- TEST MODE. Triple-tap the scoreboard. A sandbox for trying the new content without playing
+3 -3
View File
@@ -359,9 +359,9 @@ function popBarrel(zb) {
vx: (Math.random() * 2 - 1) * 4, vy: 1.2 + Math.random() * 3.5, vz: (Math.random() * 2 - 1) * 4,
t: 0.35 + Math.random() * 0.5, pink: true });
grantWeapon(zb.wid);
const w = WEAPONS[zb.wid];
G.flash = { text: w.label, t: 1.1 };
weaponModal(zb.wid); // first sight only — the gate lives in weaponModal, for both callers
// first sight only — the gate lives in weaponModal, for both callers — and the flash keeps quiet
// when the modal spoke, so the same weapon isn't named twice in the same beat
if (!weaponModal(zb.wid)) G.flash = { text: WEAPONS[zb.wid].label, t: 1.1 };
}
// dark smoke: one puff, drifting up and spreading. Not gravity-bound like gore (see the parts loop).