Stop the dead for the changeover instead of letting the player wander
Oliver vetoed the free movement between points on sight: he never walks freely during play, so being able to only between points reads as the game breaking, not as a fix. Reverted to 'rally' only, and the rule is written into the settled-feel list so it doesn't get re-invented. The frozen changeover is answered his other way instead — the dead wait too. `held` in updateZombies stops their advance, their steering and the eat check for the breather; they still bleed and burn, they just stand there, because the umpire called time and it is still a tennis match. The path where this actually bit: losing a duel scheduled on a changeover beat spawns five fresh shamblers and THEN starts five seconds you have no agency in. The stuck pose was never about movement — 'run' is the one pose expirePose doesn't expire, and runT stops advancing outside the block, so a beat that began mid-stride welded him to a single frame. Reset it and it's fixed for every phase. And he could walk off the screen in ordinary play, not just during the beat I had added: P_BOUNDS.x is 6.5 m, portrait shows about ±4 m at the baseline. The xVis clamp already existed but only applied during auto-fire; it now always applies, floored at the sideline so every legal ball stays catchable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e00886f57e
commit
79fb43f60d
4 files changed
+68
-23
No files matched your search
+10
-3
@@ -269,23 +269,30 @@ export function updateZombies(dt) {
|
||||
// the only bodies left to catch were the ones it had already removed.
|
||||
if (ball.active && ball.flame && ball.y < 2.6) ignite(ball.x, ball.z, TUNE.burnBallR);
|
||||
|
||||
// The umpire called time. The changeover is a MANDATORY breather for the player — no serving, no
|
||||
// walking — so it is one for the dead too, which is the joke: they wait, because it's still a
|
||||
// tennis match. They stand where they are, still bleeding, still burning, still lit by anything
|
||||
// in the air, but nothing advances and nothing can eat you. (The alternative — letting the player
|
||||
// walk freely during the beat — was tried and vetoed: he never walks freely during play either.)
|
||||
const held = !!G.changeover;
|
||||
|
||||
for (let i = zombies.length - 1; i >= 0; i--) {
|
||||
const zb = zombies[i];
|
||||
if (!zb) continue; // a bomb detonation splices several out mid-loop and can gut the array under us
|
||||
zb.walkT += dt;
|
||||
if (zb.burnT > 0 && burnTick(zb, i, dt)) continue; // the fire finished it — the array moved under us
|
||||
zb.z += zb.v * (zb.burnT > 0 ? TUNE.burnPanic : 1) * dt;
|
||||
if (!held) zb.z += zb.v * (zb.burnT > 0 ? TUNE.burnPanic : 1) * dt;
|
||||
bleed(zb); // open wounds bleed every frame they're standing
|
||||
|
||||
if (zb.shieldT > 0) zb.shieldT -= dt; // staggered chair comes back up when this runs out
|
||||
if (zb.variant === 'r') { /* the racket boss holds station — its AI owns its x */ }
|
||||
if (held || zb.variant === 'r') { /* the racket boss holds station — its AI owns its x */ }
|
||||
else if (G.mode === 'splatter' && zb.z > COURT.netZ) { // on YOUR half they close in — each on its own lane, not a column
|
||||
const tx = P.x + zb.homeOff;
|
||||
zb.x += Math.sign(tx - zb.x) * Math.min(Math.abs(tx - zb.x), zb.v * 0.7 * dt)
|
||||
+ Math.sin(zb.walkT * 2.3) * 0.25 * dt; // shamble wobble — the approach reads organic, not tracked
|
||||
} else
|
||||
zb.x += Math.sin(zb.walkT * 1.7) * 0.15 * dt; // far half: aimless shamble
|
||||
if (G.mode === 'splatter' && Math.hypot(zb.x - P.x, (zb.z - P.z) * 0.75) < TUNE.eatenR + (zb.variant === 'g' ? 0.2 : 0)) { // z weighted down: depth is foreshortened, so a head-on shambler eats you when it LOOKS on top of you
|
||||
if (!held && G.mode === 'splatter' && Math.hypot(zb.x - P.x, (zb.z - P.z) * 0.75) < TUNE.eatenR + (zb.variant === 'g' ? 0.2 : 0)) { // z weighted down: depth is foreshortened, so a head-on shambler eats you when it LOOKS on top of you
|
||||
gore.push({ x: P.x, z: P.z, r: 0.9, a: 0.9 });
|
||||
for (let k = 0; k < 30; k++) parts.push({
|
||||
x: P.x, y: 1.1, z: P.z,
|
||||
|
||||
Reference in new issue
Block a user