The finishing shot is spent, and the wound skins come back

"one-shot is bad - way too easy - also we're losing all the nice gore
animation sprites" and "I noticed the last kill of a game can carry to the
spawn of a new zombie of the next round".

drillOneShot is off. The second half of that note is the part worth
remembering: a 1 hp body never passes through a wound stage, so every skin in
ZWOUND — arm off, ribs out, still walking — is skipped and the roster's best
art never renders at all. Kept as a switch, never a default.

The carry-over was a real unfairness, not a curiosity. A ball keeps pace
through a kill and travels UP-COURT, which is exactly where the next batch is
born — so the shot that finished your round flew on into bodies that did not
exist when you took it, and faulted you on a round you had not been shown
yet. The shot that ends a round is spent now, and drillCaught does the same
since it also refills the court up-court. Pierce within a batch is untouched:
that is honest occlusion you could have read, this was not.

Verified with real aimed serves through a whole round: round banks, ball goes
inactive, the next batch walks on with 0 faults and a clean sequence, and the
gang carries roster HP again (brute 5, ball boy 3).

33 tests, 15 seeds clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-11 20:43:26 +02:00
1 parent 0f524a08c9
commit 57e96d629e
5 files changed
+71 -22

No files matched your search

+40 -9
View File
@@ -490,17 +490,48 @@ test('a wrong kill never leaves an un-winnable round', () => {
}
});
test('drillOneShot drops every body on the drill court to a single hit', () => {
test('the shot that ends a round cannot carry into the next batch', () => {
// Oliver: "the last kill of a game can carry to the spawn of a new zombie of the next round". A
// ball keeps pace through a kill and travels UP-COURT, which is exactly where the next batch is
// born — so it faulted you on a round you had not been shown yet.
drillPlaying();
const seq = G.drill.seq.slice();
for (const v of seq) drillKillType(v);
assert.ok(G.drill.rounds >= 1, 'setup: the round completed');
assert.equal(ball.active, false, 'the finishing shot is spent, not left in flight');
// let the next batch walk on and confirm it arrives untouched
for (let i = 0; i < 30; i++) update(DT);
const gang = zombies.filter(z => z.drill);
assert.ok(gang.length >= 2, 'the next batch is on court');
assert.equal(G.drill.faults, 0, 'and it did not inherit a fault from the previous round');
assert.equal(G.drill.step, 0, 'nor a half-finished sequence');
});
test('being caught also spends the ball, for the same reason', () => {
drillPlaying();
ball.active = true; ball.lastHit = 'P';
killPlayer();
assert.equal(ball.active, false, 'the court refills up-court; a live ball would meet it');
});
test('drillOneShot is a switch, and OFF means the roster HP is intact', () => {
// Off by default: one-shot bodies were "way too easy" AND skipped every wound skin in ZWOUND,
// because a 1 hp body never passes through a damage stage. Asserts whichever way the knob is set
// rather than being deleted when it was turned off.
startDrill();
assert.ok(TUNE.drillOneShot >= 0.5, 'setup: the testing knob is on');
for (const z of zombies) assert.equal(z.hp, 1, z.variant + ' should be one-shot, saw hp ' + z.hp);
// and it really dies to ONE splat-quality ball, roster HP notwithstanding
const tank = zombies.find(z => z.drill && z.variant === 'k')
|| zombies.find(z => z.drill && z.variant === 'g') || zombies.find(z => z.drill);
ball.active = true; ball.lastHit = 'P'; ball.y = 1; ball.pow = 1; ball.bounces = 0;
ball.x = tank.x; ball.z = tank.z; ball.vx = ball.vy = ball.vz = 0;
update(DT);
assert.ok(!zombies.includes(tank), 'one hit put down a ' + tank.variant);
|| zombies.find(z => z.drill && z.variant === 'g');
if (TUNE.drillOneShot >= 0.5) {
for (const z of zombies) assert.equal(z.hp, 1, z.variant + ' should be one-shot, saw hp ' + z.hp);
} else if (tank) {
assert.ok(tank.hp > 1, 'the heavy bodies keep the roster HP: ' + tank.variant + ' at ' + tank.hp);
// ...and that is what lets it show a wound stage on the way down
ball.active = true; ball.lastHit = 'P'; ball.y = 1; ball.pow = 1; ball.bounces = 0;
ball.x = tank.x; ball.z = tank.z; ball.vx = ball.vy = ball.vz = 0;
update(DT);
assert.ok(zombies.includes(tank), 'one hit does not put down a ' + tank.variant);
assert.ok(tank.hp < tank.hpMax, 'but it is wounded: ' + tank.hp + '/' + tank.hpMax);
}
});
test('a batch body that walks past you counts as caught, never as a free escape', () => {