From 572219f703dc7bba76a45b14220cadbe87b4c94d Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 1 Jan 2026 09:34:47 -0700 Subject: [PATCH] Add debug menu --- app.js | 85 ++++++++ debug.html | 533 ++++++++++++++++++++++++++++++++++++++++++++++ debug.js | 214 +++++++++++++++++++ index.html | 11 +- ogel.webp | Bin 0 -> 10802 bytes style.css | 227 ++++++++++++++++++++ sw.js | 2 +- workbox-config.js | 2 +- 8 files changed, 1071 insertions(+), 3 deletions(-) create mode 100644 debug.html create mode 100644 debug.js create mode 100644 ogel.webp diff --git a/app.js b/app.js index 3534984..9135074 100644 --- a/app.js +++ b/app.js @@ -37,6 +37,78 @@ document.addEventListener('DOMContentLoaded', function () { const widescreenBgs = document.getElementById('check-widescreen-bgs'); const outroFmv = document.getElementById('check-outro'); const badEnding = document.getElementById('check-ending'); + const logo = document.getElementById('island-logo-img'); + + // --- Debug Mode Activation (5 taps on logo) --- + let debugTapCount = 0; + let debugTapTimeout = null; + let debugEnabled = false; + + // Pizza celebration animation for OGEL mode + function celebratePizza(originElement) { + const rect = originElement.getBoundingClientRect(); + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + const sliceCount = 12; + + for (let i = 0; i < sliceCount; i++) { + const slice = document.createElement('div'); + slice.className = 'pizza-slice'; + slice.textContent = '🍕'; + + // Calculate direction for this slice + const angle = (i / sliceCount) * Math.PI * 2; + const distance = 150 + Math.random() * 100; + const tx = Math.cos(angle) * distance; + const ty = Math.sin(angle) * distance; + const rotation = (Math.random() - 0.5) * 720; + + slice.style.left = centerX + 'px'; + slice.style.top = centerY + 'px'; + slice.style.setProperty('--tx', tx + 'px'); + slice.style.setProperty('--ty', ty + 'px'); + slice.style.setProperty('--rot', rotation + 'deg'); + slice.style.animationDelay = (Math.random() * 0.2) + 's'; + + document.body.appendChild(slice); + + // Remove after animation completes + setTimeout(function() { + slice.remove(); + }, 1700); + } + } + + logo.addEventListener('click', function() { + if (debugEnabled) { + // Replay pizza animation on subsequent clicks + celebratePizza(logo); + return; + } + + debugTapCount++; + clearTimeout(debugTapTimeout); + + if (debugTapCount >= 5) { + // Enable debug mode + debugEnabled = true; + logo.src = 'ogel.webp'; + logo.alt = 'OGEL Mode Enabled'; + + // Celebrate with pizza! + celebratePizza(logo); + + // Dynamically load debug.js + const script = document.createElement('script'); + script.src = 'debug.js'; + document.body.appendChild(script); + } else { + // Reset tap count after 1 second of no taps + debugTapTimeout = setTimeout(function() { + debugTapCount = 0; + }, 1000); + } + }); // --- Sound Toggle --- function updateSoundEmojiState() { @@ -96,11 +168,24 @@ document.addEventListener('DOMContentLoaded', function () { }); let progressUpdates = 0; + const debugUI = document.getElementById('debug-ui'); + let debugUIVisible = false; + + // MutationObserver to prevent Emscripten from hiding the debug UI + const debugUIObserver = new MutationObserver(function(mutations) { + if (debugUIVisible && debugUI.style.display === 'none') { + debugUI.style.setProperty('display', 'block', 'important'); + } + }); + debugUIObserver.observe(debugUI, { attributes: true, attributeFilter: ['style'] }); + emscriptenCanvas.addEventListener('presenterProgress', function (event) { // Intro animation is ready if (event.detail.objectName == 'Lego_Smk' && event.detail.tickleState == 1) { loadingGifOverlay.style.display = 'none'; emscriptenCanvas.style.setProperty('display', 'block', 'important'); + debugUIVisible = true; + debugUI.style.setProperty('display', 'block', 'important'); } else if (progressUpdates < 1003) { progressUpdates++; diff --git a/debug.html b/debug.html new file mode 100644 index 0000000..0f5c100 --- /dev/null +++ b/debug.html @@ -0,0 +1,533 @@ + +
+
Debug Options
+
+
General
+ + + + +
+
+
Debug Mode (OGEL)
+ + + + +
+
+
Camera/View
+ + +
+
+
LOD (Level of Detail)
+ + + +
+
+
Misc
+ +
+
+
Switch Act
+ + + + +
+
+
Locations
+ + +
+
+
Animations
+ + + +
+
diff --git a/debug.js b/debug.js new file mode 100644 index 0000000..0cb3b37 --- /dev/null +++ b/debug.js @@ -0,0 +1,214 @@ +(async function() { + const debugUI = document.getElementById('debug-ui'); + const canvas = document.getElementById('canvas'); + + // Fetch and inject debug panel HTML + try { + const response = await fetch('debug.html'); + const html = await response.text(); + debugUI.innerHTML = html; + } catch (error) { + console.error('Failed to load debug panel:', error); + return; + } + + // Now get references to elements after they've been injected + const debugToggle = document.getElementById('debug-toggle'); + const debugPanel = document.getElementById('debug-panel'); + const debugPasswordBtn = document.querySelector('.debug-password'); + const requiresDebugBtns = document.querySelectorAll('.requires-debug'); + + let debugModeActive = false; + + // Key code mapping for special keys + const keyCodeMap = { + 'Pause': { key: 'Pause', code: 'Pause', keyCode: 19 }, + 'Escape': { key: 'Escape', code: 'Escape', keyCode: 27 }, + ' ': { key: ' ', code: 'Space', keyCode: 32 }, + 'Tab': { key: 'Tab', code: 'Tab', keyCode: 9 }, + 'F11': { key: 'F11', code: 'F11', keyCode: 122 }, + 'F12': { key: 'F12', code: 'F12', keyCode: 123 }, + '+': { key: '+', code: 'NumpadAdd', keyCode: 107 }, + '-kp': { key: '-', code: 'NumpadSubtract', keyCode: 109 }, + '*': { key: '*', code: 'NumpadMultiply', keyCode: 106 }, + '/': { key: '/', code: 'NumpadDivide', keyCode: 111 }, + // Digit keys + '0': { key: '0', code: 'Digit0', keyCode: 48 }, + '1': { key: '1', code: 'Digit1', keyCode: 49 }, + '2': { key: '2', code: 'Digit2', keyCode: 50 }, + '3': { key: '3', code: 'Digit3', keyCode: 51 }, + '4': { key: '4', code: 'Digit4', keyCode: 52 }, + '5': { key: '5', code: 'Digit5', keyCode: 53 }, + '6': { key: '6', code: 'Digit6', keyCode: 54 }, + '7': { key: '7', code: 'Digit7', keyCode: 55 }, + '8': { key: '8', code: 'Digit8', keyCode: 56 }, + '9': { key: '9', code: 'Digit9', keyCode: 57 }, + }; + + // Toggle debug panel + debugToggle.addEventListener('click', function(e) { + e.stopPropagation(); + debugPanel.classList.toggle('open'); + debugToggle.classList.toggle('active'); + }); + + // Dispatch a keyboard event to the canvas + function sendKey(key) { + let keyInfo = keyCodeMap[key]; + + if (!keyInfo) { + // Regular character key (letters) + const char = key.toLowerCase(); + const charCode = char.charCodeAt(0); + keyInfo = { + key: char, + code: 'Key' + char.toUpperCase(), + keyCode: charCode >= 97 && charCode <= 122 ? charCode - 32 : charCode + }; + } + + const eventInit = { + key: keyInfo.key, + code: keyInfo.code, + keyCode: keyInfo.keyCode, + which: keyInfo.keyCode, + bubbles: true, + cancelable: true + }; + + canvas.dispatchEvent(new KeyboardEvent('keydown', eventInit)); + canvas.dispatchEvent(new KeyboardEvent('keyup', eventInit)); + } + + // Send a sequence of keys with delay (longer delay for multi-stage commands) + function sendKeySequence(keys, delay = 100) { + let index = 0; + function sendNext() { + if (index < keys.length) { + sendKey(keys[index]); + index++; + setTimeout(sendNext, delay); + } else { + canvas.focus(); + } + } + sendNext(); + } + + // Update button states based on debug mode + function updateDebugModeUI() { + if (debugModeActive) { + debugPasswordBtn.classList.add('active'); + debugPasswordBtn.textContent = 'Debug Mode Active'; + requiresDebugBtns.forEach(btn => btn.classList.add('enabled')); + } else { + debugPasswordBtn.classList.remove('active'); + debugPasswordBtn.textContent = 'Enter Debug Mode'; + requiresDebugBtns.forEach(btn => btn.classList.remove('enabled')); + } + } + + // Handle button clicks + debugPanel.addEventListener('click', function(e) { + const btn = e.target.closest('button'); + if (!btn || btn === debugToggle) return; + + const keys = btn.dataset.keys; + if (!keys) return; + + e.preventDefault(); + e.stopPropagation(); + + // Handle special cases + if (keys === 'ogel') { + // Enter debug password + sendKeySequence(['o', 'g', 'e', 'l']); + debugModeActive = true; + updateDebugModeUI(); + return; + } + + // For requires-debug buttons, ensure debug mode is active + if (btn.classList.contains('requires-debug') && !debugModeActive) { + // Auto-enter debug mode first + sendKeySequence(['o', 'g', 'e', 'l']); + debugModeActive = true; + updateDebugModeUI(); + // Then send the actual keys after a delay + setTimeout(() => { + sendKeySequence(keys.split('')); + }, 500); + return; + } + + // Handle multi-key sequences (like 'g1' for act switch or 'c00' for locations) + if (keys.length > 1 && !keyCodeMap[keys]) { + sendKeySequence(keys.split('')); + } else { + sendKey(keys); + canvas.focus(); + } + }); + + // Handle location teleport + const locationSelect = document.getElementById('debug-location-select'); + const gotoLocationBtn = document.getElementById('debug-goto-location'); + + gotoLocationBtn.addEventListener('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + + const locationValue = locationSelect.value; + if (!locationValue) return; + + // Ensure debug mode is active + if (!debugModeActive) { + sendKeySequence(['o', 'g', 'e', 'l']); + debugModeActive = true; + updateDebugModeUI(); + // Then send location keys after a delay + setTimeout(() => { + sendKeySequence(locationValue.split('')); + }, 500); + return; + } + + sendKeySequence(locationValue.split('')); + }); + + // Handle animation playback + const animationSelect = document.getElementById('debug-animation-select'); + const playAnimationBtn = document.getElementById('debug-play-animation'); + + playAnimationBtn.addEventListener('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + + const animationId = animationSelect.value; + if (!animationId) return; + + // Ensure debug mode is active + if (!debugModeActive) { + sendKeySequence(['o', 'g', 'e', 'l']); + debugModeActive = true; + updateDebugModeUI(); + // Then send animation keys after a delay + setTimeout(() => { + playAnimation(animationId); + }, 500); + return; + } + + playAnimation(animationId); + }); + + function playAnimation(animationId) { + // Animation command: 'v' + 3 digits (padded with leading zeros) + const paddedId = animationId.toString().padStart(3, '0'); + const keys = ['v', ...paddedId.split('')]; + sendKeySequence(keys); + } + + // Initialize UI + updateDebugModeUI(); +})(); diff --git a/index.html b/index.html index 762ee47..3d3ecc6 100644 --- a/index.html +++ b/index.html @@ -155,6 +155,12 @@

Changelog

+
+ January 2026 +
    +
  • New: Debug menu for developers and power users. Tap the LEGO Island logo 5 times to unlock OGEL mode and access debug features like teleporting to locations, switching acts, and playing animations
  • +
+
December 2025
    @@ -727,7 +733,7 @@
@@ -751,6 +757,9 @@ + +
+ diff --git a/ogel.webp b/ogel.webp new file mode 100644 index 0000000000000000000000000000000000000000..db98c8e445f1225a2470a70d5787bc16cf3d8af4 GIT binary patch literal 10802 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 literal 0 HcmV?d00001 diff --git a/style.css b/style.css index da07b6d..f12dc7b 100644 --- a/style.css +++ b/style.css @@ -909,4 +909,231 @@ select { grid-template-columns: 1fr; gap: 25px; } +} + +/* Debug UI Panel */ +#debug-ui { + display: none; + position: fixed; + top: 10px; + right: 10px; + z-index: 1000; + font-family: Arial, sans-serif; +} + +#debug-toggle { + width: 40px; + height: 40px; + border-radius: 50%; + background-color: rgba(0, 0, 0, 0.7); + border: 2px solid #FFD700; + color: #FFD700; + font-size: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + margin-left: auto; +} + +#debug-toggle:hover { + background-color: rgba(255, 215, 0, 0.2); + transform: rotate(90deg); +} + +#debug-toggle.active { + background-color: #FFD700; + color: #000; +} + +#debug-panel { + display: none; + position: absolute; + top: 50px; + right: 0; + width: 280px; + max-height: calc(100dvh - 70px); + overflow-y: auto; + background-color: rgba(24, 24, 24, 0.95); + border: 1px solid #444; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); +} + +#debug-panel.open { + display: block; +} + +.debug-header { + padding: 12px 15px; + background-color: #FFD700; + color: #000; + font-weight: bold; + font-size: 14px; + border-radius: 7px 7px 0 0; + position: sticky; + top: 0; + z-index: 1; +} + +.debug-section { + padding: 10px 12px; + border-bottom: 1px solid #333; +} + +.debug-section:last-child { + border-bottom: none; +} + +.debug-section-title { + color: #FFD700; + font-size: 11px; + font-weight: bold; + text-transform: uppercase; + margin-bottom: 8px; + letter-spacing: 0.5px; +} + +#debug-panel button { + display: block; + width: 100%; + padding: 8px 10px; + margin-bottom: 4px; + background-color: #2a2a2a; + border: 1px solid #444; + border-radius: 4px; + color: #e0e0e0; + font-size: 12px; + cursor: pointer; + text-align: left; + transition: all 0.15s ease; +} + +#debug-panel button:last-child { + margin-bottom: 0; +} + +#debug-panel button:hover { + background-color: #3a3a3a; + border-color: #FFD700; +} + +#debug-panel button:active { + background-color: #FFD700; + color: #000; +} + +#debug-panel button.debug-password { + background-color: #3d2a00; + border-color: #FFD700; + color: #FFD700; +} + +#debug-panel button.debug-password:hover { + background-color: #FFD700; + color: #000; +} + +#debug-panel button.debug-password.active { + background-color: #00aa00; + border-color: #00ff00; + color: #fff; +} + +#debug-panel button.requires-debug { + opacity: 0.5; +} + +#debug-panel button.requires-debug.enabled { + opacity: 1; +} + +.debug-location-grid { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 4px; +} + +.debug-location-grid button { + text-align: center; + padding: 6px 4px; + font-size: 11px; + font-family: 'Consolas', 'Menlo', monospace; +} + +/* Scrollbar styling for debug panel */ +#debug-panel::-webkit-scrollbar { + width: 6px; +} + +#debug-panel::-webkit-scrollbar-track { + background: #1a1a1a; +} + +#debug-panel::-webkit-scrollbar-thumb { + background: #555; + border-radius: 3px; +} + +#debug-panel::-webkit-scrollbar-thumb:hover { + background: #FFD700; +} + +#debug-animation-select, +#debug-location-select { + width: 100%; + padding: 8px 10px; + margin-bottom: 8px; + background-color: #2a2a2a; + border: 1px solid #444; + border-radius: 4px; + color: #e0e0e0; + font-size: 12px; + cursor: pointer; +} + +#debug-animation-select:hover, +#debug-location-select:hover { + border-color: #FFD700; +} + +#debug-animation-select:focus, +#debug-location-select:focus { + outline: none; + border-color: #FFD700; +} + +#debug-animation-select optgroup, +#debug-location-select optgroup { + background-color: #1a1a1a; + color: #FFD700; + font-weight: bold; +} + +#debug-animation-select option, +#debug-location-select option { + background-color: #2a2a2a; + color: #e0e0e0; + padding: 4px; +} + +/* Pizza celebration animation for OGEL mode */ +.pizza-slice { + position: fixed; + font-size: 32px; + pointer-events: none; + z-index: 10000; + animation: pizza-fly 1.5s ease-out forwards; +} + +@keyframes pizza-fly { + 0% { + opacity: 1; + transform: translate(0, 0) rotate(0deg) scale(1); + } + 100% { + opacity: 0; + transform: translate(var(--tx), var(--ty)) rotate(var(--rot)) scale(0.5); + } } \ No newline at end of file diff --git a/sw.js b/sw.js index 6216212..068c42d 100644 --- a/sw.js +++ b/sw.js @@ -10,7 +10,7 @@ const { Strategy } = workbox.strategies; const { CacheableResponsePlugin } = workbox.cacheableResponse; const { RangeRequestsPlugin } = workbox.rangeRequests; -precacheAndRoute([{"revision":"1941a2dd1683d34e6503354fa9002d99","url":"index.html"},{"revision":"013ceb7d67293d532e979dde0347f3af","url":"cancel_off.webp"},{"revision":"bfc1563be018d82685716c6130529129","url":"cancel_on.webp"},{"revision":"d282c260fd35522036936bb6faf8ad21","url":"cdspin.gif"},{"revision":"3d820bf72b19bd4e437a61e75f317b83","url":"configure_off.webp"},{"revision":"e2c0c5e6aa1f7703c385a433a2d2a519","url":"configure_on.webp"},{"revision":"88e1e81c930d8e6c24dfdc7af274e812","url":"favicon.png"},{"revision":"d16b293eca457e2fb1e7ef2caca8c904","url":"favicon.svg"},{"revision":"d2b9c2e128ef1e5e4265c603b0bc3305","url":"free_stuff_off.webp"},{"revision":"cbc6a6779897f932c3a3c8dceb329804","url":"free_stuff_on.webp"},{"revision":"05fba4ef1884cbbd6afe09ea3325efc0","url":"install_off.webp"},{"revision":"11247e92082ba3d978a2e3785b0acf51","url":"install_on.webp"},{"revision":"d23ea8243c18eb217ef08fe607097824","url":"island.webp"},{"revision":"92952ef8f080c355aec499e669214840","url":"isle.js"},{"revision":"4fb9dbeadeb5781c3a069b5acb1d5f45","url":"isle.wasm"},{"revision":"6d4248f1a08c218943e582673179b7be","url":"poster.pdf"},{"revision":"a6fcac24a24996545c039a1755af33ea","url":"read_me_off.webp"},{"revision":"aae783d064996b4322e23b092d97ea4a","url":"read_me_on.webp"},{"revision":"766a9e6e6d890f24cef252e81753b29d","url":"run_game_off.webp"},{"revision":"70208e00e9ea641e4c98699f74100db3","url":"run_game_on.webp"},{"revision":"0a65c71d9983c9bb1bc6a5f405fd6fd9","url":"shark.webp"},{"revision":"88c1fd032e6fc16814690712a26c1ede","url":"uninstall_off.webp"},{"revision":"0118a4aca04c5fb0a525bf00b001844e","url":"uninstall_on.webp"},{"revision":"b21ea085712e7a731dd721578b46186b","url":"app.js"},{"revision":"2898f0ebd4847281c7020d48f43812d9","url":"style.css"},{"revision":"060210979e13e305510de6285e085db1","url":"manifest.json"},{"revision":"4f0172bc7007d34cebf681cc233ab57f","url":"install.webp"},{"revision":"6a70d35dadf51d2ec6e38a6202d7fb0b","url":"install.mp3"},{"revision":"eac041a0b8835bfea706d997b0b7b224","url":"downloader.js"}]); +precacheAndRoute([{"revision":"413569e7f8f884133ea6c1d2c9a9cb99","url":"index.html"},{"revision":"013ceb7d67293d532e979dde0347f3af","url":"cancel_off.webp"},{"revision":"bfc1563be018d82685716c6130529129","url":"cancel_on.webp"},{"revision":"d282c260fd35522036936bb6faf8ad21","url":"cdspin.gif"},{"revision":"3d820bf72b19bd4e437a61e75f317b83","url":"configure_off.webp"},{"revision":"e2c0c5e6aa1f7703c385a433a2d2a519","url":"configure_on.webp"},{"revision":"88e1e81c930d8e6c24dfdc7af274e812","url":"favicon.png"},{"revision":"d16b293eca457e2fb1e7ef2caca8c904","url":"favicon.svg"},{"revision":"d2b9c2e128ef1e5e4265c603b0bc3305","url":"free_stuff_off.webp"},{"revision":"cbc6a6779897f932c3a3c8dceb329804","url":"free_stuff_on.webp"},{"revision":"05fba4ef1884cbbd6afe09ea3325efc0","url":"install_off.webp"},{"revision":"11247e92082ba3d978a2e3785b0acf51","url":"install_on.webp"},{"revision":"d23ea8243c18eb217ef08fe607097824","url":"island.webp"},{"revision":"b4754844f694858c2c08307a197c5434","url":"isle.js"},{"revision":"e66ee40529da22100b5f3d55d9aa1850","url":"isle.wasm"},{"revision":"6d4248f1a08c218943e582673179b7be","url":"poster.pdf"},{"revision":"a6fcac24a24996545c039a1755af33ea","url":"read_me_off.webp"},{"revision":"aae783d064996b4322e23b092d97ea4a","url":"read_me_on.webp"},{"revision":"766a9e6e6d890f24cef252e81753b29d","url":"run_game_off.webp"},{"revision":"70208e00e9ea641e4c98699f74100db3","url":"run_game_on.webp"},{"revision":"0a65c71d9983c9bb1bc6a5f405fd6fd9","url":"shark.webp"},{"revision":"88c1fd032e6fc16814690712a26c1ede","url":"uninstall_off.webp"},{"revision":"0118a4aca04c5fb0a525bf00b001844e","url":"uninstall_on.webp"},{"revision":"bc17c7c6ecae6a5258cf2d0d89962e7e","url":"app.js"},{"revision":"ceeab6ec27aba25418c3ded77ebd4517","url":"style.css"},{"revision":"060210979e13e305510de6285e085db1","url":"manifest.json"},{"revision":"4f0172bc7007d34cebf681cc233ab57f","url":"install.webp"},{"revision":"6a70d35dadf51d2ec6e38a6202d7fb0b","url":"install.mp3"},{"revision":"eac041a0b8835bfea706d997b0b7b224","url":"downloader.js"},{"revision":"6899f72755d4e84c707b93ac54a8fb06","url":"debug.js"},{"revision":"7817b36ddda9f07797c05a0ff6cacb21","url":"debug.html"},{"revision":"4ea2aac9446188b8a588811bc593919e","url":"ogel.webp"}]); const gameFiles = [ "/LEGO/Scripts/CREDITS.SI", "/LEGO/Scripts/INTRO.SI", "/LEGO/Scripts/NOCD.SI", "/LEGO/Scripts/SNDANIM.SI", diff --git a/workbox-config.js b/workbox-config.js index 6aa6c54..f31828c 100644 --- a/workbox-config.js +++ b/workbox-config.js @@ -7,7 +7,7 @@ module.exports = { 'island.webp', 'isle.js', 'isle.wasm', 'poster.pdf', 'read_me_off.webp', 'read_me_on.webp', 'run_game_off.webp', 'run_game_on.webp', 'shark.webp', 'uninstall_off.webp', 'uninstall_on.webp', 'app.js', 'style.css', 'manifest.json', - 'install.webp', 'install.mp3', 'downloader.js' + 'install.webp', 'install.mp3', 'downloader.js', 'debug.js', 'debug.html', 'ogel.webp' ], swSrc: 'src/sw.js', swDest: 'sw.js',