A sprung Ward is named as one, not as a punch

Eric grabbed a warded treasure and took the Ward's three points — but
the attack modal showed a bare-knuckled punch, the hint line said the
owner "attacks with a punch", and the cast panel called it a physical
blow with no card behind it. The engine knew better: the stack has
carried sourceName ("warded treasure") since rev 9, and the damage
line used it. The client never read it.

Now every cardless stack with a name shows that name — and, for the
Ward, the Ward card itself — in the modal, the hint line, and the
cast panel, with the damage inbound. In the chronicle, a counteraction
played against it records "warded treasure" rather than "punch", and
an EMPATHY echo of it names the same. Chronicle-only, ungated; all 58
production ledgers replay clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-03 09:41:12 -04:00
co-authored by Claude Fable 5.1
parent 3723b8f211
commit 3f909b485b
2 changed files with 27 additions and 8 deletions
+7 -7
View File
@@ -5779,7 +5779,7 @@ function doCounteract(
}
player.hand.push(attackCard);
const events: GameEvent[] = [
{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? "punch" },
{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? stack.sourceName ?? "punch" },
{ type: "attackAbsorbedIntoHand", player: playerId, attackCard },
{ type: "attackResolved", attacker: stack.attackerId, defender: stack.defenderId, attackCardId: attackCard.cardId, damageDealt: 0, reflectedDamage: 0, fullyStopped: true, redirected: false },
];
@@ -5809,7 +5809,7 @@ function doCounteract(
return {
ok: true,
state,
events: [{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? "punch" }],
events: [{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? stack.sourceName ?? "punch" }],
};
}
@@ -5821,7 +5821,7 @@ function doCounteract(
takeFromHand(player, instanceId);
state.discard.push(card);
const events: GameEvent[] = [
{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? "punch" },
{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? stack.sourceName ?? "punch" },
];
attachSustained(state, events, "invisible", playerId, playerId, duration);
stack.counters.push({ player: playerId, card, nullified: false });
@@ -5838,7 +5838,7 @@ function doCounteract(
takeFromHand(player, instanceId);
state.discard.push(card);
const events: GameEvent[] = [
{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? "punch" },
{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? stack.sourceName ?? "punch" },
];
attachSustained(state, events, "empathy", playerId, playerId, duration);
stack.counters.push({ player: playerId, card, nullified: false });
@@ -5877,7 +5877,7 @@ function doCounteract(
return {
ok: true,
state,
events: [{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? "punch" }],
events: [{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? stack.sourceName ?? "punch" }],
};
}
@@ -5897,7 +5897,7 @@ function doCounteract(
return {
ok: true,
state,
events: [{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? "punch" }],
events: [{ type: "counteractionPlayed", player: playerId, card, cardId: card.cardId, against: stack.attackCard?.cardId ?? stack.sourceName ?? "punch" }],
};
}
@@ -6246,7 +6246,7 @@ function resolveStack(state: GameState, events: GameEvent[]): void {
// EMPATHY: "Any attack done in any form against you acts against both
// you and the caster of the spell."
if (damageDealt > 0 && sustainedOn(state, defender.id, "empathy").length > 0 && attacker.alive) {
applyDamage(state, events, attacker, damageDealt, `${attackId ?? "punch"} (empathy)`, defender.id, pipe.kind);
applyDamage(state, events, attacker, damageDealt, `${attackId ?? stack.sourceName ?? "punch"} (empathy)`, defender.id, pipe.kind);
}
// SHADOWSTONE: physical damage you deal feeds your life total.
if (damageDealt > 0 && pipe.kind === "physical" && displays(attacker, "shadowstone") && attacker.alive) {