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:
1 parent
0f524a08c9
commit
57e96d629e
5 files changed
+71
-22
No files matched your search
@@ -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', () => {
|
||||
|
||||
Reference in new issue
Block a user