A perfect serve is a cut ball: it hooks from kill to kill

Slice is not a tin and not a rack slot. It is what a perfect serve DOES —
the toss ritual's 45 ms window, or a pull that stops inside perfectBand.
Every other weapon is handed to you; this one is a technique, and it hands
the plain ball a real route to the DOUBLE/TRIPLE KILL ladder that until now
only a bomb or a lucky line-up could reach. Banking your specials stops
meaning playing worse in the meantime.

Only a kill hooks, so a wound ends the chain and no brute, steward or boss
ever extends one. It is a crowd skill shot, which is the half of the arsenal
the tins do not cover.

The pull had to learn a third state to say this. Quality SATURATES at
pullFull, so an overpull and a perfect pull drew an identical band: the game
was asking you to hit a window it never showed you. The band now goes chalk
white inside it and the mark on the target grows a second ring — the fill
says where the ball lands, the ring says it will not stop there.

The chain path is deliberately NOT previewed. It is a scallop laid over the
exact patch of court you need to read, it solves the shot before you take
it, and the bodies walk — any chain drawn at pull time is a lie by the time
the ball arrives, which is the one thing the band exists not to be.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-09 13:44:17 +02:00
1 parent 655b86d27f
commit 99d84b2c9d
4 files changed
+91 -6

No files matched your search

+29
View File
@@ -630,8 +630,25 @@ export function meleeSwipe(x, z, range) {
function splatter(i, fanfare = true) { // the MAIN ball hit a zombie
const zx = zombies[i].x, zy = zombieH(zombies[i]) * 0.9, zz = zombies[i].z; // for the pops — killZombie splices
const sp0 = Math.hypot(ball.vx, ball.vz); // pace BEFORE the pierce tax, for a slice to keep
killZombie(i, !!G.horde);
ball.vx *= TUNE.zPierce; ball.vz *= TUNE.zPierce; // keep enough pace to plow through the next
// SLICE: hook off this body onto the next one, at FULL pace. The pierce tax is what a straight
// ball pays for plowing through meat, and a cut ball does not plow — it leaves. Only a kill gets
// here, so a wound ends the chain on its own and no brute, steward or boss ever extends one.
if (ball.chain > 0) {
const nx = nearestTo(zx, zz, TUNE.sliceR);
if (nx) {
ball.chain--;
const k = sp0 / (Math.hypot(ball.vx, ball.vz) || 1);
ball.vx *= k; ball.vz *= k;
ball.hook = { x: nx.x, z: nx.z }; // a POINT, not the body: the hook must not pin a corpse alive
G.trail = null; // the fired band is the parabola this ball has just STOPPED flying — leaving
// it up draws a streak peeling away from the ball, which is the one thing
// the band exists to avoid. From here the chalk thread is the trail.
pock(0.5, 1100 + 450 * ball.kills); // the cut, a step higher up the scale per link
} else ball.chain = 0; // nothing in reach: it plows on as a normal ball
}
if (!fanfare) return; // machine-gun pellets splatter but skip the streak fanfare / bomb meter
ball.kills++; // this shot's running streak
// splat micro-freeze: every ball kill stutters the world a touch, and the stutter grows with the
@@ -694,6 +711,18 @@ export function firePellet(w = WEAPONS.gun) {
else if (++mgTick % 2 === 0) pock(0.25, w.ignite ? 300 : 1400);
}
const HUES = ['#ff6b6b', '#ffd166', '#7bffa0', '#6bd5ff', '#c08bff', '#ff8bd5'];
// the next body a slice hooks onto: nearest live thing to the kill it just made, in any direction —
// a cut ball can come BACK down-court, and the shot that curls round into something behind the body
// you aimed at is the one worth earning. Furniture and barrels are not bodies and never a target.
function nearestTo(x, z, maxD) {
let best = null, bd = maxD;
for (const zb of zombies) {
if ('mo'.includes(zb.variant)) continue;
const d = Math.hypot(zb.x - x, zb.z - z);
if (d < bd) { bd = d; best = zb; }
}
return best;
}
// the best thing up-court to lob at: nearest body ahead of you, ignoring furniture you can walk past
function nearestAhead() {
let best = null, bd = 1e9;