The back room: five taps on the logo, not three on the scoreboard

The weapon-test cheat sat on the SCOREBOARD, where a single tap is the miss-log
overlay — so the thing you tap to read a log was also the thing that opened a
sandbox mid-run, three taps in, by accident. That tap does one job again.

The cheats now live behind five taps on the splash logo, where nothing marks
them and nothing in play can reach them:

  WEAPON TEST  the old sandbox. It stocked only the BARREL weapons, on a screen
               called the weapon test — it stocks every weapon in the game now,
               eight of the nine slots.
  BOSS TEST    a portrait of every chapter boss, built by asking bossArt() what
               each chapter gets, so the list cannot drift from what a run
               actually spawns. Pick one and you land in a real fight at that
               chapter's game number with the full arsenal at ×99.

Neither is a special mode: both ride the transition out with laserScene's trick
(force the turn, then step the ten-second cinematic out in one frame) and hand
you the ordinary update loop, ordinary scoring, ordinary death. A test that
plays by different rules tells you nothing about the game.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-09 16:19:12 +02:00
1 parent 04ee0174ce
commit 1bb528f7e0
3 files changed
+100 -31

No files matched your search

+53 -19
View File
@@ -3,7 +3,7 @@
// Module map: config (tuning/constants) · state (mutable game state) · gameplay (logic/update)
// render (camera/drawing) · input (keys/touch) · audio (sfx/umpire) · panel (T tuning UI)
import { TUNE, COURTS, TOURS, EATEN_RESTART } from './config.js';
import { TUNE, COURTS, TOURS, EATEN_RESTART, WEAPONS, bossArt } from './config.js';
import { P, O, ball, score, G, setupPoint, selectCourt, selectTour } from './state.js';
import { update, restartRun, keyPressed, solveShot, inServeBox, inCourt, forceZombies, splatPoint, deliverTin, selectWeapon, grantWeapon, showModal, dismissModal, startDuel, resolveInterlude, flickTarget, startBossFight, endBossFight , toggleTestMode } from './gameplay.js';
import { fitViewport, render, proj, RES, SPRV, LOAD } from './render.js';
@@ -186,8 +186,55 @@ document.getElementById('nbSend').addEventListener('click', async () => {
});
nbName.addEventListener('keydown', e => { if (e.key === 'Enter') document.getElementById('nbSend').click(); });
document.getElementById('cStart').addEventListener('click', start);
for (const id of ['sBack', 'stBack', 'rkBack'])
for (const id of ['sBack', 'stBack', 'rkBack', 'scBack'])
document.getElementById(id).addEventListener('click', () => go('splash'));
document.getElementById('bsBack').addEventListener('click', () => go('secret'));
// ---- THE BACK ROOM: five taps on the logo, and nothing on the screen says so. It replaces the
// triple-tap on the in-play scoreboard, which sat on top of the miss-log tap and which the
// testteam kept opening by accident — a cheat you can trip mid-run is a bug.
let logoTaps = [];
document.querySelector('#splash .mid').addEventListener('pointerdown', () => {
const now = performance.now();
logoTaps = logoTaps.filter(t => now - t < 2000);
logoTaps.push(now);
if (logoTaps.length >= 5) { logoTaps = []; go('secret'); }
});
// Both entries drop you into a REAL run rather than a special mode — same update loop, same
// scoring, same death — which is the only way a test tells you anything about the game.
// This is laserScene's trick: force the turn and then step the transition out in one go, because
// the cinematic is ten seconds you did not come here to watch.
function intoSplatter() {
if (G.mode === 'tennis') forceZombies();
for (let i = 0; i < 900 && G.mode !== 'splatter'; i++) update(1 / 60);
G.modal = null; G.horde = null; G.interlude = false; G.changeover = 0; G.clearing = false;
G.mgT = 0; G.gunId = null; G.beam = null; G.hp = G.hpMax = TUNE.playerHp;
zombies.length = 0; shots.length = 0; pellets.length = 0;
score.server = 'P'; setupPoint();
}
document.getElementById('scWeapons').addEventListener('click', () => {
start(); intoSplatter(); toggleTestMode();
});
document.getElementById('scBosses').addEventListener('click', () => go('bosses'));
// The list is built by ASKING bossArt which design each chapter gets, so it can never drift from
// what the run actually spawns — including the champion sitting on chapter 10 rather than 7.
const bossList = document.getElementById('bossList');
for (let ch = 1; ch <= 10; ch++) {
const art = bossArt(ch), b = document.createElement('button');
b.innerHTML = `<img src="assets/${art.walk[0]}.png?v=${SPRV}" alt="">`
+ `<b>${art.name}</b><i>CHAPTER ${ch} · GAME ${ch * TUNE.bossEvery}</i>`;
b.addEventListener('click', () => {
start(); intoSplatter();
G.runGames = ch * TUNE.bossEvery; // the roster, the HUD and the spawn ramp all read this one
G.bossDue = 0; // ...and the schedule must not queue a SECOND fight behind it
for (const id of Object.keys(WEAPONS)) grantWeapon(id, TUNE.wCap); // full arsenal, every tin
G.weapon = 0;
startBossFight(ch);
});
bossList.appendChild(b);
}
// the three period tabs are one listener on the strip — the button carries the period in data-p
document.getElementById('stTabs').addEventListener('click', e => {
const b = e.target.closest('button'); if (!b) return;
@@ -278,27 +325,14 @@ const maybeRestart = () => {
cv.addEventListener('pointerdown', maybeRestart);
addEventListener('keydown', maybeRestart);
// hidden shortcut: three taps on the SCOREBOARD opens test mode (a medium wave plus every barrel
// weapon — see gameplay.toggleTestMode). The umpire triple-tap (skip to zombie mode) is REMOVED:
// the testteam found it, and a cheat a player can trip by accident is a bug. T.forceZombies()
// still exists for the console.
let boardTaps = [];
// A tap on the SCOREBOARD toggles the miss-log overlay, and that is now all it does. The triple-tap
// that opened test mode has moved to the back room on the splash (see below): a cheat you can trip
// by accident mid-run is a bug, and this one sat on the one thing you tap to read the log.
cv.addEventListener('pointerdown', e => {
const r = cv.getBoundingClientRect();
const x = (e.clientX - r.left) / r.width * (cv.width / RES); // logical coords
const y = (e.clientY - r.top) / r.height * (cv.height / RES);
if (x >= 6 && x <= 138 && y >= 6 && y <= 36) { // the scoreboard
const now = performance.now();
boardTaps = boardTaps.filter(t => now - t < 1600);
boardTaps.push(now);
if (boardTaps.length >= 3) {
boardTaps = [];
// taps one and two already toggled the miss-log twice, so it is back where it started —
// this third one must NOT toggle it again, or every trip through test mode leaves the
// overlay on behind you
toggleTestMode();
} else G.logShow = !G.logShow; // a single tap is still the miss-log overlay
}
if (x >= 6 && x <= 138 && y >= 6 && y <= 36) G.logShow = !G.logShow; // the scoreboard
});