Triple-tap the scoreboard for a sandbox
A test mode for trying the new content without playing twenty games to reach it. Three taps on the scoreboard toggles it, three more turns it off, and a single tap is still the miss-log overlay. Same shape as the umpire triple-tap cheat it sits next to. It OVERRIDES the difficulty director rather than editing it, so the wave is the same whether you opened it in game 1 or game 40 and the run keeps running underneath: 8 bodies, a fixed 1.15 m/s shamble, a spawn every 1.6 s, and pickVariant pretending to be at game 20 so every body type can turn up. All four barrel weapons sit on the rack and are topped back up each frame, because committing a burst spends the whole tin and a sandbox that runs dry is not one. A barrel rolls out every 14 s so the pickup itself is testable too. The third tap must NOT toggle logShow: taps one and two already toggled it twice and it is back where it started, so toggling again left the miss-log overlay switched on behind you every single time. Also records the trap that cost a debugging round getting here: index.html loads main.js?v=N, and fetching 'main.js' does not bust that URL -- so main.js stayed stale through a reload while every other module was fresh, and the tap handler appeared to do nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
282f5145a9
commit
46e268973d
7 files changed
+101
-12
No files matched your search
+38
-1
@@ -1,6 +1,6 @@
|
||||
// Game logic: ballistics, swings, serves, rules/scoring, AI, and the per-frame update.
|
||||
|
||||
import { TUNE, UI, BOSS_ART, APPLAUSE_T, EATEN_BURST, EATEN_SUMMARY, COURT, CONTACT, VOLLEY, ZONE_DEPTH, HOME, P_BOUNDS, TOSS, SHOT_DEPTH, POSE_TIME, BOUNCE_IDLE, zombieH, Z_CHEST , WEAPONS, RACK_MAX } from './config.js';
|
||||
import { TUNE, UI, BOSS_ART, APPLAUSE_T, EATEN_BURST, EATEN_SUMMARY, COURT, CONTACT, VOLLEY, ZONE_DEPTH, HOME, P_BOUNDS, TOSS, SHOT_DEPTH, POSE_TIME, BOUNCE_IDLE, zombieH, Z_CHEST , WEAPONS, RACK_MAX , BARREL_WEAPONS } from './config.js';
|
||||
import { P, O, ball, score, crowd, G, other, deuceSide, setupPoint, sendBoy, resetState } from './state.js';
|
||||
import { audio, pock, swish, whoosh, applause, voice, sfx, aww, zombieMusic, zombieDuck, menuDuck } from './audio.js';
|
||||
import { axisX, axisZ, takeFlickAim, touchPX, resetInput } from './input.js';
|
||||
@@ -548,6 +548,42 @@ export function weaponModal(id, healLine = null) {
|
||||
icon: w.icon, iconH: 40, color: UI.warm });
|
||||
}
|
||||
|
||||
// ---- TEST MODE. Triple-tap the scoreboard. A sandbox for trying the new content without playing
|
||||
// twenty games to reach it: a steady medium wave and every barrel weapon on the rack, topped back up
|
||||
// as you spend it. It does NOT stop the run — games, duels and bosses all still happen underneath;
|
||||
// it only overrides the difficulty dials and keeps the rack stocked.
|
||||
export function toggleTestMode() {
|
||||
G.testMode = !G.testMode;
|
||||
if (!G.testMode) { G.flash = { text: 'TEST MODE OFF', t: 1.4 }; return false; }
|
||||
if (G.mode === 'tennis') forceZombies(); // no zombies to test against in a tennis match
|
||||
stockTestRack();
|
||||
G.flash = { text: 'TEST MODE', t: 1.6 };
|
||||
showModal({ title: 'TEST MODE', color: UI.pink,
|
||||
body: ['A STEADY MEDIUM WAVE', 'EVERY BARREL WEAPON, KEPT FULL',
|
||||
'', 'TRIPLE-TAP THE SCOREBOARD AGAIN TO STOP'] });
|
||||
return true;
|
||||
}
|
||||
|
||||
// every barrel weapon on the rack at full stock. Called on entry and then kept topped up in update,
|
||||
// so a burst you commit (which spends the whole tin) is available again a moment later.
|
||||
function stockTestRack() {
|
||||
for (const id of Object.keys(BARREL_WEAPONS)) {
|
||||
const have = G.rack.find(e => e.id === id);
|
||||
if (have) have.n = Math.max(have.n, WEAPONS[id].tin);
|
||||
else if (G.rack.length < RACK_MAX) G.rack.push({ id, n: WEAPONS[id].tin });
|
||||
}
|
||||
}
|
||||
let testBarrelT = 0;
|
||||
export function tickTestMode(dt) {
|
||||
if (!G.testMode) return;
|
||||
stockTestRack();
|
||||
if (G.mode !== 'splatter' || G.bossFight || G.interlude) return;
|
||||
if ((testBarrelT -= dt) <= 0) {
|
||||
testBarrelT = TUNE.testBarrelEvery;
|
||||
if (!zombies.some(z => z.variant === 'o')) spawnBarrel();
|
||||
}
|
||||
}
|
||||
|
||||
// ---- the interlude: order is restored, one sudden-death point vs the racket zombie.
|
||||
// Tennis rules apply for exactly one point — the absurdity peak: the umpire never stopped watching.
|
||||
// This is now the ONLY source of weapons in the game: win the point or leave empty-handed.
|
||||
@@ -1197,6 +1233,7 @@ export function update(dt) {
|
||||
|
||||
// --- zombies + transition timeline
|
||||
if (G.mode !== 'tennis') updateZombies(dt);
|
||||
tickTestMode(dt); // keeps the sandbox stocked and rolls it a barrel now and then
|
||||
if (G.meleeT > 0) G.meleeT -= dt;
|
||||
if (G.clearing && !zombies.some(blocksClear)) proceedAfterClear(); // the won-game wave is mopped up — advance
|
||||
if (G.mode === 'transition') transition(dt);
|
||||
|
||||
Reference in new issue
Block a user