Warps preserve your heading, not your bearing
Stepping through a rim warp spun the live camera 180: the director aimed along the displacement vector, and a top-to-bottom wrap's vector points exactly opposite the walk. The exit facing now comes from the warp's own geometry — the far mouth's inward direction — so travel carries straight through plain wraps and rotates correctly where boards were laid rotated; a dimensional token step keeps the facing it entered with. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
770e79d063
commit
5f91e30eb4
@@ -12,7 +12,7 @@
|
||||
import { tokenArt } from "./art";
|
||||
import { objectArt } from "./art";
|
||||
import { fpFxForEvents, type FpFx } from "./fpv/fx3d";
|
||||
import { castRay } from "./fpv/raycast";
|
||||
import { castRay, SIDE_ANGLE, OPPOSITE } from "./fpv/raycast";
|
||||
import { aimOfEvents, gatherGlides, hurledIn, shortestArc } from "./fpv/director";
|
||||
import { untrack } from "svelte";
|
||||
import type { GameEvent, GameView, Side } from "@wizwar/engine";
|
||||
@@ -175,6 +175,22 @@
|
||||
const events = b && b.n !== directedBatch ? b.events : [];
|
||||
if (b) directedBatch = b.n;
|
||||
const hurled = hurledIn(events, povId);
|
||||
// Stepping through a warp keeps your HEADING, not your bearing to a
|
||||
// point: you emerge walking out of the far mouth, so the exit facing
|
||||
// is the far mouth's inward direction — travel preserved through a
|
||||
// plain wrap, properly rotated where the boards were laid rotated.
|
||||
// (A dimensional token has no mouths: facing simply carries over.)
|
||||
let warpFacing: number | null = null;
|
||||
for (const e of events) {
|
||||
if (e.type === "moved" && e.player === povId && e.via === "warp") {
|
||||
const w = v.board.warps.find((wp) =>
|
||||
wp.from.cell.x === e.from.x && wp.from.cell.y === e.from.y &&
|
||||
wp.to.cell.x === e.to.x && wp.to.cell.y === e.to.y);
|
||||
if (w) warpFacing = SIDE_ANGLE[OPPOSITE[w.to.side]];
|
||||
} else if (e.type === "warpStepped" && e.player === povId) {
|
||||
warpFacing = camF;
|
||||
}
|
||||
}
|
||||
const willCut = !camReady || (dist > 1.6 && !hurled);
|
||||
cutawayShot = false;
|
||||
const takeCutaway = (ax: number, ay: number) => {
|
||||
@@ -194,7 +210,10 @@
|
||||
const aim = aimOfEvents(events, v, povId, m.position, actor);
|
||||
let targetFacing = camF;
|
||||
let aimed = false;
|
||||
if (camReady && !willCut && dist > 0.05 && !hurled) {
|
||||
if (warpFacing !== null) {
|
||||
targetFacing = warpFacing;
|
||||
aimed = true;
|
||||
} else if (camReady && !willCut && dist > 0.05 && !hurled) {
|
||||
targetFacing = Math.atan2(dy, dx);
|
||||
aimed = true;
|
||||
} else if (aim?.self) {
|
||||
|
||||
Reference in New Issue
Block a user