The slice stops steering: each kill strikes the ball once, then physics

Oliver, watching a sliced ball circle a shambler it had only wounded: "an
orbiting tennis ball midair, nobody knows what is going on." He is right,
and not only about that shot. Every ball in this game flies a parabola you
can read, so the one that thinks reads as broken even on the shots where it
works. The hook was the wrong primitive, not a hook with two bugs in it.

So there is no hook. At the instant of a kill the ball is struck again —
ONE velocity out of solveShot, the same solver the serve uses, aimed at the
next body's chest — and from the next frame it is an ordinary ball under
ordinary gravity. It cannot orbit, cannot hover and cannot outlive its shot,
because after the strike nothing about the slice is still running.

That also deletes the wound bug rather than fixing it. Six sites spend the
ball (lastHit = 'X') and not one of them cleared the hook, so a ball that
merely WOUNDED its target was left steering at 30% pace toward a point that
body had already walked off — the loop he saw. With no persistent state
there is nothing to clear: a ball spent on a body it failed to kill just
drops, like every other spent ball.

The hop draws its own band, white, so a chain leaves the same chalk streak
every other shot leaves. sliceTurn and sliceHookT are gone with the steering
that needed them; sliceArc stays, no longer as a turn-radius limit but to
keep a carom from doubling back down-court, which reads as a stray
deflection rather than as a cut.

Net 24 lines lighter than the thing it replaces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-09 14:15:24 +02:00
1 parent e11ad30a63
commit 5de42648ec
3 files changed
+50 -74

No files matched your search

+14 -22
View File
@@ -237,29 +237,21 @@ export const TUNE = {
meleeCrowdR: 3.4, // m — the radius that counts as "on top of you" for that scaling (> meleeRange,
// so the swish speeds up as they close in, not only once they are already on you)
zPierce: 0.75, // pace a ball keeps after a splatter — hot balls plow through lined-up pairs
// ---- SLICE. Not a tin and not a rack slot: it is what a PERFECT serve DOES. Cut the ball and it
// hooks off each body it kills onto the next one instead of plowing straight on. Every other
// weapon is something you are handed; this one is a technique, which is why it is earned on the
// timing window (the toss ritual's 45 ms, or a pull that STOPS inside perfectBand) rather than
// won out of a barrel. Only a KILL hooks — a wound ends the chain — so it is a crowd skill shot
// that does nothing to a brute, a steward or a boss, 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.
sliceHops: 2, // extra bodies one perfect serve hooks to. 2 => TRIPLE KILL is the ceiling
sliceR: 6.5, // m the hook reaches for the next body. Wider reads as the game aiming for you;
// ---- SLICE. Not a tin and not a rack slot: it is what a PERFECT serve DOES. Cut the ball and
// each body it kills strikes it on toward the next one instead of it plowing straight through.
// Every other weapon is something you are handed; this one is a technique, which is why it is
// earned on the timing window (the toss ritual's 45 ms, or a pull that STOPS inside perfectBand)
// rather than won out of a barrel. Only a KILL carries it on — a wound ends the chain — so it is
// a crowd skill shot that does nothing to a brute, a steward or a boss, and it hands the plain
// ball a route to the DOUBLE/TRIPLE KILL ladder only a bomb or a lucky line-up could reach.
// It is ONE new velocity per kill and then ordinary ballistics: see sliceCarom for why the ball
// must never steer, whatever it costs in prettiness.
sliceHops: 2, // extra bodies one perfect serve is struck on to. 2 => TRIPLE KILL is the ceiling
sliceR: 6.5, // m it will reach for the next body. Wider reads as the game aiming for you;
// much narrower and a spread-out crowd never chains at all
sliceTurn: 11, // rad/s the ball swings onto the next one: a FLOOR, not the rate. It is the knob
// for how the shot LOOKS when there is room — past ~30 it snaps like a ricochet,
// under ~6 it sails wide. The rate actually used is whatever the geometry needs
// (see the hook), because a fixed rate has a fixed turn radius (v/w = 2 m here)
// and ANY body inside that circle is unreachable: the ball flew a closed loop
// around it forever, never arriving, never falling. A crowd is all close bodies,
// so the one place the weapon should shine was the one place it hung.
sliceArc: 120, // deg: the widest bearing off the ball's heading that can be hooked at all. No
// single tangent arc reaches a body directly BEHIND the ball at any turn rate,
// so past this the chain just ends and it plows on
sliceHookT: 0.7, // s a hook may steer before it lets go. The geometry above is solved fresh every
// frame and still cannot promise an arrival when the target WALKS, so this is the
// backstop that makes an endless orbit impossible by construction, not by maths
sliceArc: 120, // deg: widest bearing off the ball's heading it will take. A carom can physically
// go anywhere, but one that doubles back down-court reads as a stray deflection
// rather than as a cut, and the chain should be walking INTO the crowd anyway
// The schedule calls the DUEL, not the tin: weapons are only ever won, but a duel comes round
// on its own so there is always a chance at one. Fires off the next hand-cleared wave.
duelFirst: 2, // game after which the first scheduled sudden-death duel is called