Walls you know are lies stand as ghosts
A wizard who has seen through an illusion no longer walks toward empty air where the board shows a dashed ghost: the ray records the first known-illusion edge it crosses without stopping, and the renderer stands a wall there at one-fifth opacity, violet ripple running through it, drawn over the sprites so bodies show through its breath. Untested illusions get the same tell the board gives — a faint shimmer on their solid face, maybe stone, maybe not — while a believed illusion stays honest brick. The workshop rehearses it with ?illusion=H:2,8. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
b3bc4d079b
commit
727b9144d0
@@ -21,10 +21,14 @@ export interface Hit {
|
||||
/** The un-wrapped along-face coordinate: u plus the world cell it lies
|
||||
* in, so multi-cell surfaces (a long wall of fire) can read as one. */
|
||||
worldU: number;
|
||||
/** The edge struck, for state the renderer dresses (jammed locks). */
|
||||
/** The edge struck, for state the renderer dresses (jammed locks,
|
||||
* untested illusions). */
|
||||
edge?: string;
|
||||
/** The eye reached this through a warp: haze it other-worldly. */
|
||||
warped?: boolean;
|
||||
/** The first known-illusion edge the ray crossed before its solid hit:
|
||||
* the eye passes, but a translucent ghost of a wall stands there. */
|
||||
ghost?: { dist: number; u: number; worldU: number; axis: "x" | "y" };
|
||||
}
|
||||
|
||||
export const SIDE_ANGLE: Record<Side, number> = { E: 0, S: Math.PI / 2, W: Math.PI, N: -Math.PI / 2 };
|
||||
@@ -80,6 +84,7 @@ export function castRay(
|
||||
// a mouth re-enters at the paired mouth and marches on, its hits hazed.
|
||||
let baseDist = 0;
|
||||
let warped = false;
|
||||
let ghost: Hit["ghost"];
|
||||
for (let traversal = 0; traversal < 3; traversal++) {
|
||||
const dx = Math.cos(angle);
|
||||
const dy = Math.sin(angle);
|
||||
@@ -129,7 +134,7 @@ export function castRay(
|
||||
// A sliding door carries its texture with it: sample past the gap.
|
||||
return {
|
||||
dist: baseDist + b.t, kind: b.kind, u: Math.max(0, u - b.slide),
|
||||
axis: b.axis, worldU: along, edge: b.edge, warped,
|
||||
axis: b.axis, worldU: along, edge: b.edge, warped, ghost,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -144,13 +149,17 @@ export function castRay(
|
||||
const u0 = along % 1;
|
||||
const texU = u0 < 0 ? u0 + 1 : u0;
|
||||
|
||||
const crossSide: Side = crossingX ? (stepX > 0 ? "E" : "W") : (stepY > 0 ? "S" : "N");
|
||||
if (!ghost && view.knownIllusionEdges.includes(edgeKey({ x: cx, y: cy }, crossSide))) {
|
||||
ghost = { dist: baseDist + dist, u: texU, worldU: along, axis };
|
||||
}
|
||||
const offBoard = !view.board.cells[cellKey({ x: nx, y: ny })];
|
||||
if (offBoard) {
|
||||
const side: Side = crossingX ? (stepX > 0 ? "E" : "W") : (stepY > 0 ? "S" : "N");
|
||||
const side: Side = crossSide;
|
||||
const warp = view.board.warps.find(
|
||||
(w) => cellKey(w.from.cell) === cellKey({ x: cx, y: cy }) && w.from.side === side,
|
||||
);
|
||||
if (!warp) return { dist: baseDist + dist, kind: "rim", u: texU, axis, worldU: along, warped };
|
||||
if (!warp) return { dist: baseDist + dist, kind: "rim", u: texU, axis, worldU: along, warped, ghost };
|
||||
// Step through: re-enter at the paired mouth, heading inward, the
|
||||
// offset along the edge preserved (a wraparound keeps its lane).
|
||||
const exitHeading = SIDE_ANGLE[OPPOSITE[warp.to.side]];
|
||||
@@ -167,14 +176,14 @@ export function castRay(
|
||||
break;
|
||||
}
|
||||
if (view.squareContents[cellKey({ x: nx, y: ny })]?.kind === "stone") {
|
||||
return { dist: baseDist + dist, kind: "stone", u: texU, axis, worldU: along, warped };
|
||||
return { dist: baseDist + dist, kind: "stone", u: texU, axis, worldU: along, warped, ghost };
|
||||
}
|
||||
cx = nx;
|
||||
cy = ny;
|
||||
}
|
||||
if (!warped || traversal === 2) break;
|
||||
}
|
||||
return { dist: baseDist + 64, kind: "rim", u: 0, axis: "x", worldU: 0, warped };
|
||||
return { dist: baseDist + 64, kind: "rim", u: 0, axis: "x", worldU: 0, warped, ghost };
|
||||
}
|
||||
|
||||
/** Can a wizard's body (not just their eye) cross this edge? Workshop
|
||||
|
||||
Reference in New Issue
Block a user