Flourishes second wave: reflections, warps, claws, and ongoing looks
The reflected spell turns in the air and flies home wearing its own colors, striking its caster with the hit it meant for someone else. Warp travel glows green at both mouths. Punches land as a proper burst star; creature blows rake three red gashes; an absorbed spell is a little card swallowed into the absorber, spinning as it shrinks. And ongoing spells now wear their look between events: firewalls lick and glow, the invisible and misted breathe at a fraction of opacity, Medusa's victims gray to stone, and the webbed wear their webs. The pulses stop under reduced motion; the informative looks stay. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
70d7b4babb
commit
6da350fd46
+46
-5
@@ -9,7 +9,8 @@ type Side = "N" | "E" | "S" | "W";
|
||||
|
||||
type FxShape =
|
||||
| { kind: "fireball" | "bolt" | "waterbolt"; from: Cell; to: Cell }
|
||||
| { kind: "burst" | "splash" | "shimmer" | "shield" | "sparkle" | "whiff" | "hit"; at: Cell }
|
||||
| { kind: "burst" | "splash" | "shimmer" | "shield" | "sparkle" | "whiff" | "hit"
|
||||
| "pow" | "claw" | "absorb" | "warp-glow"; at: Cell }
|
||||
| { kind: "edge-dust"; cell: Cell; side: Side };
|
||||
export type BoardFx = FxShape & { id: number };
|
||||
|
||||
@@ -65,9 +66,29 @@ export function fxForEvents(
|
||||
break;
|
||||
}
|
||||
case "punched":
|
||||
push({ kind: "hit", at: e.at });
|
||||
push({ kind: "pow", at: e.at });
|
||||
beat++;
|
||||
break;
|
||||
case "creatureAttacked": {
|
||||
// The target may be a wizard or a fellow creature.
|
||||
const at = posOf(typeof e.target === "string" ? e.target : null) ??
|
||||
(() => {
|
||||
const c = view.creatures.find((c) => c.id === e.target);
|
||||
return c ? { ...c.position } : null;
|
||||
})();
|
||||
if (at) { push({ kind: "claw", at }); beat++; }
|
||||
break;
|
||||
}
|
||||
case "creatureTouched": {
|
||||
const at = posOf(e.player);
|
||||
if (at) { push({ kind: "claw", at }); beat++; }
|
||||
break;
|
||||
}
|
||||
case "attackAbsorbedIntoHand": {
|
||||
const at = posOf(e.player);
|
||||
if (at) { push({ kind: "absorb", at }); beat++; }
|
||||
break;
|
||||
}
|
||||
case "damaged": {
|
||||
const at = posOf(e.player);
|
||||
if (at) { push({ kind: "hit", at }); beat++; }
|
||||
@@ -79,9 +100,17 @@ export function fxForEvents(
|
||||
break;
|
||||
}
|
||||
case "attackResolved": {
|
||||
if (e.fullyStopped) {
|
||||
const at = posOf(e.defender);
|
||||
if (at) { push({ kind: "shield", at }); beat++; }
|
||||
const back = posOf(e.attacker);
|
||||
const stand = posOf(e.defender);
|
||||
if ((e.redirected || e.reflectedDamage > 0) && back && stand) {
|
||||
// The spell turns in the air and goes home.
|
||||
const kind = (e.attackCardId && PROJECTILES[e.attackCardId]) || "bolt";
|
||||
push({ kind, from: stand, to: back });
|
||||
push({ kind: "hit", at: back }, 380);
|
||||
beat++;
|
||||
} else if (e.fullyStopped && stand) {
|
||||
push({ kind: "shield", at: stand });
|
||||
beat++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -90,6 +119,18 @@ export function fxForEvents(
|
||||
push({ kind: "shimmer", at: e.to }, 200);
|
||||
beat++;
|
||||
break;
|
||||
case "moved":
|
||||
if (e.via === "warp") {
|
||||
push({ kind: "warp-glow", at: e.from });
|
||||
push({ kind: "warp-glow", at: e.to }, 150);
|
||||
beat++;
|
||||
}
|
||||
break;
|
||||
case "warpStepped":
|
||||
push({ kind: "warp-glow", at: e.from });
|
||||
push({ kind: "warp-glow", at: e.to }, 150);
|
||||
beat++;
|
||||
break;
|
||||
case "wallCreated":
|
||||
case "wallDestroyed":
|
||||
push({ kind: "edge-dust", cell: e.edge.cell, side: e.edge.side });
|
||||
|
||||
Reference in New Issue
Block a user