A cut is not a stride
The wraith reel still ended in a wall, and the ledger showed why: its final step CUTS home from the cutaway at the summon site — a nine-cell leap — and the camera read that leap as a walk, faced along it into the masonry, and counted itself aimed, which silenced the closing-shot rescue. Leaps no longer set facing: any step that will cut computes willCut first, strides only turn the eyes within a stride's reach, and a cut that lands with nothing aimed always re-picks its view from the new position. The wraith turn now closes down a corridor with the wraith itself in frame. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
59c25f42f0
commit
a94ab5c6f5
@@ -253,12 +253,13 @@
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
})();
|
})();
|
||||||
|
// A leap the legs cannot explain (first frame, teleport, the return
|
||||||
|
// from a cutaway) is a CUT, and a cut is not a stride: the direction
|
||||||
|
// of travel means nothing at the far end.
|
||||||
|
const willCut = !camReady || (dist > 1.6 && !hurled);
|
||||||
let targetFacing = camF;
|
let targetFacing = camF;
|
||||||
let aimed = false;
|
let aimed = false;
|
||||||
// A stride turns the eyes along it — but only a REAL stride: on the
|
if (camReady && !willCut && dist > 0.05 && !hurled) { targetFacing = Math.atan2(dy, dx); aimed = true; }
|
||||||
// reel's first run the camera sits at its uninitialized origin, and
|
|
||||||
// that phantom distance must not pick the opening shot's direction.
|
|
||||||
if (camReady && dist > 0.05 && !hurled) { targetFacing = Math.atan2(dy, dx); aimed = true; }
|
|
||||||
else if (aim) {
|
else if (aim) {
|
||||||
const ax = aim.x + 0.5, ay = aim.y + 0.5;
|
const ax = aim.x + 0.5, ay = aim.y + 0.5;
|
||||||
const toAim = Math.hypot(ax - tx, ay - ty);
|
const toAim = Math.hypot(ax - tx, ay - ty);
|
||||||
@@ -316,7 +317,10 @@
|
|||||||
for (const t of v.treasures) if (t.position && !t.carriedBy) score += bonus(t.position, 3);
|
for (const t of v.treasures) if (t.position && !t.carriedBy) score += bonus(t.position, 3);
|
||||||
return score;
|
return score;
|
||||||
};
|
};
|
||||||
const staring = castRay(v, tx, ty, targetFacing).dist < (atEnd ? 1.2 : 0.8);
|
// A cut lands with whatever stale facing it carried, so a cut with
|
||||||
|
// nothing aimed always re-picks its view from the new position.
|
||||||
|
const staring = willCut ||
|
||||||
|
castRay(v, tx, ty, targetFacing).dist < (atEnd ? 1.2 : 0.8);
|
||||||
if (staring) {
|
if (staring) {
|
||||||
const current = viewScore(targetFacing);
|
const current = viewScore(targetFacing);
|
||||||
let bestA = targetFacing, bestScore = current;
|
let bestA = targetFacing, bestScore = current;
|
||||||
@@ -329,7 +333,7 @@
|
|||||||
targetFacing = bestA;
|
targetFacing = bestA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!camReady || (dist > 1.6 && !hurled)) {
|
if (willCut) {
|
||||||
// First frame, or a leap the legs cannot explain: cut.
|
// First frame, or a leap the legs cannot explain: cut.
|
||||||
cam.x = tx; cam.y = ty; cam.facing = targetFacing;
|
cam.x = tx; cam.y = ty; cam.facing = targetFacing;
|
||||||
camReady = true;
|
camReady = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user