Phase 9: weapons ride the new-balls rule — kill meter retired
- Deliveries are scheduled by the rules of tennis: game ballChangeFirst (3), then every ballChangeEvery (4) games; the tin lands at the NEXT changeover (a due tin survives hordes and even-game endings until a changeover comes) - Fresh tin = bombMax (3) bombs; boy run + 'new balls, please' + NEW BALLS flash - Shame rule: zombies took a game since the last delivery -> NO NEW BALLS, slate wiped either way - killMeter/bombEvery deleted from state/config/zombies Verified: delivery at game 3 (bombs 3); due-but-even games hold the tin until the next changeover; NO NEW BALLS withholds and clears shame; bomb serve still arms and detonates; killMeter gone; no console errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a3bd45e2f1
commit
eb66376033
4 files changed
+15
-10
No files matched your search
@@ -28,8 +28,9 @@ export const TUNE = {
|
|||||||
zPushback: 1.4, // m a staggered zombie is knocked back
|
zPushback: 1.4, // m a staggered zombie is knocked back
|
||||||
splatterOverT: 0.1, // s the spent-ball 'over' beat lasts before the next serve is armed
|
splatterOverT: 0.1, // s the spent-ball 'over' beat lasts before the next serve is armed
|
||||||
zPierce: 0.75, // pace a ball keeps after a splatter — hot balls plow through lined-up pairs
|
zPierce: 0.75, // pace a ball keeps after a splatter — hot balls plow through lined-up pairs
|
||||||
bombEvery: 8, // splatter kills between bomb-ball rewards
|
ballChangeFirst: 3, // game of the first new-balls delivery (real rule: 7, then every 9 — too sparse here)
|
||||||
bombMax: 3, // bomb balls you can stock at once
|
ballChangeEvery: 4, // games between deliveries after the first
|
||||||
|
bombMax: 3, // bomb balls in a fresh tin
|
||||||
bombRadius: 2.5, // m blast radius of a bomb ball
|
bombRadius: 2.5, // m blast radius of a bomb ball
|
||||||
hordeLen: 12, // s a horde wave lasts
|
hordeLen: 12, // s a horde wave lasts
|
||||||
hordeRate: 2.5, // zombies spawned per second during a horde
|
hordeRate: 2.5, // zombies spawned per second during a horde
|
||||||
|
|||||||
+11
-2
@@ -186,7 +186,11 @@ export function splatPoint(side, quiet = false) {
|
|||||||
const gameOver = advancePoint(side);
|
const gameOver = advancePoint(side);
|
||||||
if (gameOver) {
|
if (gameOver) {
|
||||||
G.runGames++;
|
G.runGames++;
|
||||||
if (side === 'O') G.shameGame = true; // they took a game — Oliver pays at the next new-balls delivery
|
if (side === 'O') G.shameGame = true; // they took a game — the next new-balls delivery is withheld
|
||||||
|
// the new-balls rule arms you: deliveries land at the changeover that follows the scheduled game
|
||||||
|
if (G.runGames === TUNE.ballChangeFirst ||
|
||||||
|
(G.runGames > TUNE.ballChangeFirst && (G.runGames - TUNE.ballChangeFirst) % TUNE.ballChangeEvery === 0))
|
||||||
|
G.tinDue = true;
|
||||||
voice(side === 'P' ? 'game_set_massacre' : 'game_opponent', 0.5); // game-win lines always speak
|
voice(side === 'P' ? 'game_set_massacre' : 'game_opponent', 0.5); // game-win lines always speak
|
||||||
cheer(2.2, 0.5);
|
cheer(2.2, 0.5);
|
||||||
const i = side === 'P' ? 0 : 1;
|
const i = side === 'P' ? 0 : 1;
|
||||||
@@ -206,7 +210,12 @@ function startChangeover() {
|
|||||||
G.changeover = true;
|
G.changeover = true;
|
||||||
G.phase = 'over'; G.overT = TUNE.changeoverT;
|
G.phase = 'over'; G.overT = TUNE.changeoverT;
|
||||||
sendBoy();
|
sendBoy();
|
||||||
G.flash = { text: 'CHANGEOVER', t: 1.4 };
|
if (G.tinDue) { // the boys arm you — unless they took a game since the last delivery
|
||||||
|
G.tinDue = false;
|
||||||
|
if (G.shameGame) G.flash = { text: 'NO NEW BALLS', t: 1.6 }; // the umpire withholds
|
||||||
|
else { G.bombs = TUNE.bombMax; voice('new_balls', 0.6); G.flash = { text: 'NEW BALLS', t: 1.6 }; }
|
||||||
|
G.shameGame = false; // the slate is clean either way
|
||||||
|
} else G.flash = { text: 'CHANGEOVER', t: 1.4 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// retire the splatter ball; a running changeover's long beat must not be clobbered short
|
// retire the splatter ball; a running changeover's long beat must not be clobbered short
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const G = {
|
|||||||
wasServe: false, // the ball in flight is a serve (first bounce must hit the box)
|
wasServe: false, // the ball in flight is a serve (first bounce must hit the box)
|
||||||
splatT: 0, // time survived in splatter mode — drives the difficulty ramp
|
splatT: 0, // time survived in splatter mode — drives the difficulty ramp
|
||||||
bombs: 0, // bomb-ball stock (max TUNE.bombMax); the next serve auto-consumes one
|
bombs: 0, // bomb-ball stock (max TUNE.bombMax); the next serve auto-consumes one
|
||||||
killMeter: 0, // splatter kills toward the next bomb reward (every TUNE.bombEvery)
|
tinDue: false, // the rules called for new balls — deliver at the next changeover
|
||||||
horde: null, // active horde wave {t, spawnT, mgT} — machine-gun racket, no serving
|
horde: null, // active horde wave {t, spawnT, mgT} — machine-gun racket, no serving
|
||||||
runGames: 0, // games finished this run (either side) — the difficulty director
|
runGames: 0, // games finished this run (either side) — the difficulty director
|
||||||
sets: [0, 0], // splatter sets won [you, them]; 6 games = a set = a horde
|
sets: [0, 0], // splatter sets won [you, them]; 6 games = a set = a horde
|
||||||
|
|||||||
@@ -62,11 +62,6 @@ function splatter(i, fanfare = true) { // the MAIN ball hit a zombie
|
|||||||
if (ball.kills === 2) { G.flash = { text: 'DOUBLE KILL', t: 0.9 }; cheer(1.6, 0.45); voice('double_kill', 0.4); }
|
if (ball.kills === 2) { G.flash = { text: 'DOUBLE KILL', t: 0.9 }; cheer(1.6, 0.45); voice('double_kill', 0.4); }
|
||||||
else if (ball.kills === 3) { G.flash = { text: 'TRIPLE KILL', t: 0.9 }; cheer(2.2, 0.6); voice('triple_kill', 0.4); }
|
else if (ball.kills === 3) { G.flash = { text: 'TRIPLE KILL', t: 0.9 }; cheer(2.2, 0.6); voice('triple_kill', 0.4); }
|
||||||
else if (ball.kills >= 4) { G.flash = { text: `MASSACRE ×${ball.kills}`, t: 0.9 }; cheer(2.8, 0.7); voice('unbelievable', 0.4); }
|
else if (ball.kills >= 4) { G.flash = { text: `MASSACRE ×${ball.kills}`, t: 0.9 }; cheer(2.8, 0.7); voice('unbelievable', 0.4); }
|
||||||
// bomb-ball reward: every bombEvery kills a boy delivers one (up to bombMax in stock)
|
|
||||||
if (++G.killMeter >= TUNE.bombEvery) {
|
|
||||||
G.killMeter = 0;
|
|
||||||
if (G.bombs < TUNE.bombMax) { G.bombs++; sendBoy(); voice('new_balls', 0.2); G.flash = { text: 'BOMB BALL', t: 0.9 }; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- horde wave: dense spawns + an auto-firing machine-gun racket (pellets, not the match ball)
|
// ---- horde wave: dense spawns + an auto-firing machine-gun racket (pellets, not the match ball)
|
||||||
|
|||||||
Reference in new issue
Block a user