diff --git a/.gitignore b/.gitignore index a22d8315..3b6ffa49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .DS_Store -/.claude /node_modules /server.js -*.env* \ No newline at end of file +*.env* diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index ce52c4fa..adfa85f4 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -58,7 +58,6 @@ class PracticeMode { groundY: scene._level._groundY, ceilingY: scene._level._ceilingY, speed: playerSpeed, - physicsFrame: scene._physicsFrame, timestamp: Date.now() }; this.checkpoints.push(checkpoint); @@ -101,184 +100,6 @@ class PracticeMode { } } -class MacroBot { - constructor(scene) { - this.scene = scene; - this.resetAll(); - } - - resetAll() { - this.recording = false; - this.playing = false; - - this.cursor = 0; - this.isDown = false; - - this.inputs = []; - - this.meta = { - author: "Web Dashers", - level: "", // ill fix ts later - version: 1 - }; - } - - startRecording(meta = {}) { - this.resetAll(); - this.recording = true; - this.meta = { ...meta }; - } - - stopRecording() { - this.recording = false; - return this.exportObject(); - } - - clearRecording() { - this.inputs = []; - this.cursor = 0; - this.isDown = false; - } - - rollbackRecording(currentFrame) { - this.inputs = this.inputs.filter(ev => (ev.frame ?? 0) <= currentFrame); - this.cursor = 0; - this.isDown = false; - } - - clearPlayback() { - this.cursor = 0; - this.isDown = false; - } - - rollbackPlayback(currentFrame) { - if (!this.inputs.length) return; - - this.cursor = 0; - this.isDown = false; - - this.scene._releaseButton(true); - - while ( - this.cursor < this.inputs.length && - (this.inputs[this.cursor].frame ?? 0) <= currentFrame - ) { - const ev = this.inputs[this.cursor++]; - - if (ev.down) { - this.scene._pushButton(true); - this.isDown = true; - } else { - this.scene._releaseButton(true); - this.isDown = false; - } - } - } - - startPlayback(macroData) { - const macro = typeof macroData === "string" ? JSON.parse(macroData) : macroData; - - this.resetAll(); - this.playing = true; - - this.meta = { - ...this.meta, - ...(macro || {}) - }; - - this.inputs = Array.isArray(macro?.inputs) ? macro.inputs.slice() : []; - this.inputs.sort((a, b) => (a.frame ?? 0) - (b.frame ?? 0)); - - this.cursor = 0; - this.isDown = false; - } - - stopPlayback() { - this.playing = false; - this.cursor = 0; - this.isDown = false; - } - - recordEdge(down, currentFrame) { - if (!this.recording) return; - - const last = this.inputs[this.inputs.length - 1]; - if (last && last.down === !!down && last.frame === currentFrame) { - return; - } - - this.inputs.push({ - frame: currentFrame, - down: !!down - }); - - this.isDown = !!down; - } - - step(currentFrame) { - if (!this.playing) return; - - while ( - this.cursor < this.inputs.length && - (this.inputs[this.cursor].frame ?? 0) <= currentFrame - ) { - const ev = this.inputs[this.cursor++]; - - if (ev.down) { - if (!this.isDown) { - this.scene._pushButton(true); - this.isDown = true; - } - } else { - if (this.isDown) { - this.scene._releaseButton(true); - this.isDown = false; - } - } - } - } - - exportObject() { - return { - meta: this.meta, - inputs: this.inputs.slice() - }; - } - - exportString(pretty = false) { - return JSON.stringify(this.exportObject(), null, pretty ? 2 : 0); - } - - download(filename = "macro.wbgdr") { - const blob = new Blob([this.exportString(true)], { type: "application/json" }); - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = filename; - document.body.appendChild(a); - a.click(); - a.remove(); - URL.revokeObjectURL(url); - } - - importFile(file) { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = (event) => { - try { - const text = String(event.target.result || ""); - const macro = JSON.parse(text); - resolve(macro); - } catch (err) { - reject(err); - } - }; - reader.onerror = () => reject(reader.error || new Error("Failed to read macro file")); - reader.readAsText(file); - }); - } -} - class GameScene extends Phaser.Scene { constructor() { super({ @@ -1204,7 +1025,57 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._editorOverlay = null; this._editorObjects = null; }; + // Track the active scene so WDSearch.playLevel() can find it + window._wdActiveScene = this; + this._openSearchMenu = () => { + // If launched with ?id=levelID, download that level directly (no iframe) + if (!window.levelID) { + // Open search as a full-screen iframe overlay + if (window._wdSearchFrame) return; // already open + try { this.input.keyboard.disableGlobalCapture(); } catch(e){} + try { this.input.keyboard.enabled = false; } catch(e){} + try { this.input.enabled = false; } catch(e){} + const audio = this._audio; + if (audio) try { audio.pauseMusic(); } catch(e){} + + const frame = document.createElement('iframe'); + frame.id = 'wd-search-iframe'; + frame.src = './gdbrowser/search.html?v=' + Date.now(); + frame.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;border:none;z-index:9999;background:#000;'; + document.body.appendChild(frame); + window._wdSearchFrame = frame; + + // Listen for messages from the iframe + if (!window._wdMsgListenerAdded) { + window._wdMsgListenerAdded = true; + window.addEventListener('message', function(e) { + const scene = window._wdActiveScene; + if (!scene) return; + if (e.data && e.data.type === 'WD_CLOSE_SEARCH') { + const f = document.getElementById('wd-search-iframe'); + if (f) f.remove(); + window._wdSearchFrame = null; + try { scene.input.keyboard.enableGlobalCapture(); } catch(e){} + try { scene.input.keyboard.enabled = true; } catch(e){} + try { scene.input.enabled = true; } catch(e){} + if (scene._audio) try { scene._audio.resumeMusic(); } catch(e){} + } + if (e.data && e.data.type === 'WD_PLAY_LEVEL') { + const f = document.getElementById('wd-search-iframe'); + if (f) f.remove(); + window._wdSearchFrame = null; + try { scene.input.keyboard.enableGlobalCapture(); } catch(e){} + try { scene.input.keyboard.enabled = true; } catch(e){} + try { scene.input.enabled = true; } catch(e){} + window.levelID = String(e.data.id); + window.alreadydownloaded = false; + scene._openSearchMenu(); + } + }); + } + return; + } if (this._searchOverlay) return; const sw = screenWidth; const sh = screenHeight; @@ -1393,32 +1264,367 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" gfx.fillStyle(panelColor, panelAlpha); gfx.fillRoundedRect(panelLeft, qsPanelY, panelW, qsPanelH, panelRadius); - const comingSoonLabel = this.add.bitmapText(sw / 2, qsPanelY + qsPanelH / 2, "bigFont", "Coming Soon!", 42) - .setScrollFactor(0).setDepth(105).setOrigin(0.5, 0.5).setTint(0xadd8e6).setAlpha(0.75); - this._searchOverlayObjects.push(comingSoonLabel); - const filtersLabelY = qsPanelY + qsPanelH + 24; - const filtersPanelY = filtersLabelY + 20; - const filtersPanelH = sh * 0.16; - const filtersLabel = this.add.bitmapText(sw / 2, filtersLabelY, "bigFont", "Filters", labelSize) + + // ── Quick Search buttons ───────────────────────────────────────────────── + // 3 cols × 3 rows. Icon on RIGHT of text, matching GDBrowser exactly. + // Text center at -0.14*btnW, icon center at +0.34*btnW from container centre. + // Icon target height = 0.45*btnH (near-native size for 30px sprites). + const _qsSearchObjects = []; + const _qsBtnDefs = [ + { label: "Downloads", icon: "GJ_sDownloadIcon_001.png" }, + { label: "Likes", icon: "GJ_sLikeIcon_001.png" }, + { label: "Sent", icon: "GJ_sModIcon_001.png" }, + { label: "Trending", icon: "GJ_sTrendingIcon_001.png"}, + { label: "Recent", icon: "GJ_sRecentIcon_001.png" }, + { label: "Magic", icon: "GJ_sMagicIcon_001.png" }, + { label: "Awarded", icon: "GJ_sStarsIcon_001.png" }, + { label: "Followed", icon: "GJ_sFollowedIcon_001.png"}, + { label: "More", icon: "GJ_arrow_03_001.png", teal: true }, + ]; + const _qsCols = 3; + const _qsBtnW = panelW * 0.285; // fits 3 cols with gaps + const _qsBtnH = _qsBtnW * (61 / 184); // longBtn01 native aspect + const _qsGapX = (panelW - _qsCols * _qsBtnW) / (_qsCols + 1); + const _qsRows = Math.ceil(_qsBtnDefs.length / _qsCols); + const _qsGapY = (qsPanelH - _qsRows * _qsBtnH) / (_qsRows + 1); + const _qsSclX = _qsBtnW / 184; + const _qsSclY = _qsBtnH / 61; + + _qsBtnDefs.forEach((def, idx) => { + const col = idx % _qsCols; + const row = Math.floor(idx / _qsCols); + const bx = panelLeft + _qsGapX + col * (_qsBtnW + _qsGapX) + _qsBtnW / 2; + const by = qsPanelY + _qsGapY + row * (_qsBtnH + _qsGapY) + _qsBtnH / 2; + + const ct = this.add.container(bx, by).setScrollFactor(0).setDepth(106); + + // Background + const bgFrame = def.teal ? "GJ_longBtn02_001.png" : "GJ_longBtn01_001.png"; + const bg = this.add.image(0, 0, "GJ_GameSheet03", bgFrame) + .setOrigin(0.5, 0.5).setScale(_qsSclX, _qsSclY); + ct.add(bg); + + if (def.icon) { + // Layout: text left, icon right, combined width centred in button + // Phaser auto-corrects atlas rotation — do NOT call setAngle on these. + const lbl = this.add.bitmapText(0, 0, "bigFont", def.label, 22) + .setOrigin(0, 0.5).setTint(0xffffff); + + // Some icons render mirrored due to atlas packing — flip them back + const _flipXIcons = new Set([ + "GJ_arrow_03_001.png", + "GJ_sLikeIcon_001.png", + "GJ_sFollowedIcon_001.png", + "GJ_sRecentIcon_001.png", + ]); + const ic = this.add.image(0, 0, "GJ_GameSheet03", def.icon) + .setOrigin(1, 0.5); + if (_flipXIcons.has(def.icon)) { ic.setFlipX(true); } + ic.setScale(1.1); + + // displayWidth already includes the scale — do NOT multiply again + const _gap = 5.5; + const _totalW = lbl.width + ic.displayWidth + _gap; + lbl.x = -_totalW / 2; + ic.x = _totalW / 2; + lbl.y = -1; + ic.y = 0; + + ct.add(lbl); + ct.add(ic); + } else { + // No icon: label dead-centre + const lbl = this.add.bitmapText(0, 0, "bigFont", def.label, 22) + .setOrigin(0.5, 0.5).setTint(0xffffff); + ct.add(lbl); + } + + // Hit zone + const hz = this.add.zone(0, 0, _qsBtnW, _qsBtnH).setOrigin(0.5, 0.5).setInteractive(); + ct.add(hz); + hz.on("pointerdown", () => { + hz._dn = true; + this.tweens.killTweensOf(ct); + this.tweens.add({ targets: ct, scale: 1.15, duration: 80, ease: "Quad.Out" }); + }); + hz.on("pointerup", () => { + if (!hz._dn) return; hz._dn = false; + this.tweens.killTweensOf(ct); + this.tweens.add({ targets: ct, scale: 1, duration: 400, ease: "Bounce.Out" }); + }); + hz.on("pointerout", () => { + if (!hz._dn) return; hz._dn = false; + this.tweens.killTweensOf(ct); + this.tweens.add({ targets: ct, scale: 1, duration: 250, ease: "Back.Out" }); + }); + + _qsSearchObjects.push(ct); + }); + + // ── Filters label + panel ───────────────────────────────────────────────── + const filtersLabelY = qsPanelY + qsPanelH + 24; + const filtersPanelY = filtersLabelY + 20; + const filtersPanelH = sh * 0.195; + const filtersLabel = this.add.bitmapText(sw / 2, filtersLabelY, "bigFont", "Filters", labelSize) .setScrollFactor(0).setDepth(105).setOrigin(0.5, 0.5).setTint(labelColor); gfx.fillStyle(filtersPanelColor, panelAlpha); gfx.fillRoundedRect(panelLeft, filtersPanelY, panelW, filtersPanelH, panelRadius); - const filtersComingSoon = this.add.bitmapText(sw / 2, filtersPanelY + filtersPanelH / 2, "bigFont", "Coming Soon!", 42) - .setScrollFactor(0).setDepth(105).setOrigin(0.5, 0.5).setTint(0xadd8e6).setAlpha(0.75); + // ── Difficulty icons ────────────────────────────────────────────────────── + // All 60x60 except diffIcon_06 (64x67 rotated), _09 (74x65 rotated). + // Use displayHeight for correct post-rotation scale. + // Demon (06) click expands to show 5 sub-type demons inline. + const _diffDefs = [ + { frame: "diffIcon_00_btn_001.png", label: "N/A" }, + { frame: "diffIcon_01_btn_001.png", label: "Easy" }, + { frame: "diffIcon_02_btn_001.png", label: "Normal" }, + { frame: "diffIcon_03_btn_001.png", label: "Hard" }, + { frame: "diffIcon_04_btn_001.png", label: "Harder" }, + { frame: "diffIcon_05_btn_001.png", label: "Insane" }, + { frame: "diffIcon_06_btn_001.png", label: "Demon", isDemon: true }, + { frame: "diffIcon_auto_btn_001.png", label: "Auto" }, + ]; + // Demon sub-types (shown instead of normal row when demon is clicked) + // difficulty_07/08/06 are rot=True in atlas — need setAngle(-90) to correct. + // difficulty_09/10 are rot=False and render upright with no correction. + // diffIcon_09 used for Insane because difficulty_09 bakes in "DEMON" text. + const _demonDefs = [ + { frame: "difficulty_07_btn_001.png", label: "", needsAngle: true }, // Easy + { frame: "difficulty_08_btn_001.png", label: "", needsAngle: true }, // Medium + { frame: "difficulty_06_btn_001.png", label: "", needsAngle: true }, // Hard + { frame: "diffIcon_09_btn_001.png", label: "Insane", needsAngle: false }, // Insane + { frame: "difficulty_10_btn_001.png", label: "", needsAngle: false }, // Extreme + ]; - const extraPanelY = filtersPanelY + filtersPanelH + 18; - const extraPanelH = sh * 0.11; + const _diffCount = _diffDefs.length; + const _diffPadX = panelW * 0.025; + const _diffSlotW = (panelW - _diffPadX * 2) / _diffCount; + const _diffIconH = Math.min(_diffSlotW * 0.72, filtersPanelH * 0.52); + const _diffIconY = filtersPanelY + filtersPanelH * 0.34; + const _diffLabelY = filtersPanelY + filtersPanelH * 0.70; + const _diffObjects = []; + + // Track which normal diff icons exist so we can hide/show them + const _normalDiffGroups = []; // [{icon, lbl, zone}] + const _demonDiffGroups = []; // [{icon, lbl, zone}] — hidden initially + let _demonMode = false; + + const _makeDiffSlot = (frame, label, slotIdx, totalSlots, padX, slotW, iconH, iconY, labelY, depth, onClick, angle=0) => { + const dx = panelLeft + padX + slotIdx * slotW + slotW / 2; + const icon = this.add.image(dx, iconY, "GJ_GameSheet03", frame) + .setScrollFactor(0).setDepth(depth).setOrigin(0.5, 0.5).setTint(0x888888); + if (angle) { icon.setAngle(angle); } + icon.setScale(0.88); + const _iconBase = 0.88; + const lbl = this.add.bitmapText(dx, labelY, "bigFont", label, 20) + .setScrollFactor(0).setDepth(depth).setOrigin(0.5, 0.5).setTint(0x888888); + const zoneH = labelY - iconY + iconH * 0.5; + const zoneY = iconY + zoneH / 2 - iconH * 0.25; + const zone = this.add.zone(dx, zoneY, slotW * 0.88, zoneH) + .setScrollFactor(0).setDepth(depth + 1).setInteractive(); + zone.on("pointerdown", () => { + zone._dn = true; + this.tweens.killTweensOf([icon, lbl]); + this.tweens.add({ targets: [icon, lbl], scale: _iconBase * 1.15, duration: 80, ease: "Quad.Out" }); + }); + zone.on("pointerup", () => { + if (!zone._dn) return; zone._dn = false; + this.tweens.killTweensOf([icon, lbl]); + this.tweens.add({ targets: [icon, lbl], scale: _iconBase, duration: 400, ease: "Bounce.Out" }); + onClick(icon, lbl); + }); + zone.on("pointerout", () => { + if (!zone._dn) return; zone._dn = false; + this.tweens.killTweensOf([icon, lbl]); + this.tweens.add({ targets: [icon, lbl], scale: _iconBase, duration: 200, ease: "Back.Out" }); + }); + return { icon, lbl, zone }; + }; + + // Build normal difficulty row + _diffDefs.forEach((def, i) => { + const slot = _makeDiffSlot( + def.frame, def.label, i, _diffCount, + _diffPadX, _diffSlotW, _diffIconH, _diffIconY, _diffLabelY, 106, + (icon, lbl) => { + if (def.isDemon) { + // Switch to demon sub-type row + _demonMode = true; + _normalDiffGroups.forEach(g => { g.icon.setVisible(false); g.lbl.setVisible(false); g.zone.setActive(false).setVisible(false); }); + _demonDiffGroups.forEach(g => { g.icon.setVisible(true); g.lbl.setVisible(true); g.zone.setActive(true).setVisible(true); }); + // Show list button in demon sub-row + if (this._searchListBtn) { const lb = this._searchListBtn; lb.icon.setVisible(true); lb.lbl.setVisible(true); lb.zone.setActive(true).setVisible(true); } + } else { + const on = icon._active = !icon._active; + icon.setTint(on ? 0xffffff : 0x888888); + lbl.setTint(on ? 0xffffff : 0x888888); + } + } + ); + _normalDiffGroups.push(slot); + _diffObjects.push(slot.icon, slot.lbl, slot.zone); + }); + + // ── "List" button — sits on top of the Demon slot (index 6), visible always ── + // Clicking opens the Demon List website. Uses accountBtn_myLists icon. + { + const _demonSlotIdx = 6; + const _listX = panelLeft + _diffPadX + _demonSlotIdx * _diffSlotW + _diffSlotW / 2; + const _listIcon = this.add.image(_listX, _diffIconY, "GJ_GameSheet03", "rankIcon_1_001.png") + .setScrollFactor(0).setDepth(108).setOrigin(0.5, 0.5).setScale(0.88).setVisible(false); + const _listLbl = this.add.bitmapText(_listX, _diffLabelY, "bigFont", "List", 20) + .setScrollFactor(0).setDepth(108).setOrigin(0.5, 0.5).setTint(0x888888).setVisible(false); + const _listZone = this.add.zone(_listX, _diffIconY, _diffSlotW * 0.88, filtersPanelH * 0.85) + .setScrollFactor(0).setDepth(109).setInteractive().setVisible(false).setActive(false); + const _listBase = 0.88; + _listZone.on("pointerdown", () => { + _listZone._dn = true; + this.tweens.killTweensOf([_listIcon, _listLbl]); + this.tweens.add({ targets: [_listIcon, _listLbl], scale: _listBase * 1.15, duration: 80, ease: "Quad.Out" }); + }); + _listZone.on("pointerup", () => { + if (!_listZone._dn) return; _listZone._dn = false; + this.tweens.killTweensOf([_listIcon, _listLbl]); + this.tweens.add({ targets: [_listIcon, _listLbl], scale: _listBase, duration: 400, ease: "Bounce.Out" }); + window.open("https://www.webdemonlist.org", "_blank"); + }); + _listZone.on("pointerout", () => { + if (!_listZone._dn) return; _listZone._dn = false; + this.tweens.killTweensOf([_listIcon, _listLbl]); + this.tweens.add({ targets: [_listIcon, _listLbl], scale: _listBase, duration: 200, ease: "Back.Out" }); + }); + // Show list button in demon sub-mode, hide in normal mode + // Patch the demon slot click to also toggle list button + const _demonSlotGroup = _normalDiffGroups[_demonSlotIdx]; + const _origDemonZoneUp = _demonSlotGroup.zone.listenerCount("pointerup") > 0; + _demonSlotGroup.zone.on("pointerup_list_patch", () => { + _listIcon.setVisible(true); _listLbl.setVisible(true); + _listZone.setActive(true).setVisible(true); + }); + // Override: when demon row is shown, also show list btn; when back, hide it + // We hook into the existing visibility toggles via the _demonDiffGroups show logic + _diffObjects.push(_listIcon, _listLbl, _listZone); + + // Store refs so demon/back toggles can show/hide the list button + this._searchListBtn = { icon: _listIcon, lbl: _listLbl, zone: _listZone }; + } + + // Build demon sub-type row (hidden by default, uses same panel space) + // 5 demons + 1 "back" slot = 6 slots across the panel + const _demonSlots = 6; + const _demonSlotW = (panelW - _diffPadX * 2) / _demonSlots; + // difficulty_XX_btn sprites are tall (86-95px native) and include baked-in text. + // Use a larger iconH and vertically centre them in the panel. + const _demonIconH = filtersPanelH * 0.78; + const _demonIconY = filtersPanelY + filtersPanelH * 0.50; + const _demonLabelY = filtersPanelY + filtersPanelH * 0.92; // label off-screen (empty) + // Back button (left slot) — use the pink backArrowPlain arrow, not a demon face + const _backSlot = _makeDiffSlot( + "backArrowPlain_01_001.png", "Back", 0, _demonSlots, + _diffPadX, _demonSlotW, _demonIconH, _demonIconY, _demonLabelY, 106, + (icon, lbl) => { + // Return to normal row + _demonMode = false; + _demonDiffGroups.forEach(g => { g.icon.setVisible(false); g.lbl.setVisible(false); g.zone.setActive(false).setVisible(false); }); + _normalDiffGroups.forEach(g => { g.icon.setVisible(true); g.lbl.setVisible(true); g.zone.setActive(true).setVisible(true); }); + // Hide list button + if (this._searchListBtn) { const lb = this._searchListBtn; lb.icon.setVisible(false); lb.lbl.setVisible(false); lb.zone.setActive(false).setVisible(false); } + } + ); + _backSlot.icon.setVisible(false); _backSlot.lbl.setVisible(false); + _backSlot.zone.setActive(false).setVisible(false); + _demonDiffGroups.push(_backSlot); + _diffObjects.push(_backSlot.icon, _backSlot.lbl, _backSlot.zone); + + // 5 demon sub-type slots (slots 1-5) + _demonDefs.forEach((def, i) => { + const slot = _makeDiffSlot( + def.frame, def.label, i + 1, _demonSlots, + _diffPadX, _demonSlotW, _demonIconH, _demonIconY, _demonLabelY, 106, + (icon, lbl) => { + const on = icon._active = !icon._active; + icon.setTint(on ? 0xffffff : 0x888888); + lbl.setTint(on ? 0xffffff : 0x888888); + }, + def.needsAngle ? -90 : 0 + ); + slot.icon.setVisible(false); slot.lbl.setVisible(false); + slot.zone.setActive(false).setVisible(false); + _demonDiffGroups.push(slot); + _diffObjects.push(slot.icon, slot.lbl, slot.zone); + }); + + // ── Length panel ────────────────────────────────────────────────────────── + const extraPanelY = filtersPanelY + filtersPanelH + 18; + const extraPanelH = sh * 0.09; gfx.fillStyle(extraPanelColor, panelAlpha); gfx.fillRoundedRect(panelLeft, extraPanelY, panelW, extraPanelH, panelRadius); - const extraComingSoon = this.add.bitmapText(sw / 2, extraPanelY + extraPanelH / 2, "bigFont", "Coming Soon!", 42) - .setScrollFactor(0).setDepth(105).setOrigin(0.5, 0.5).setTint(0xadd8e6).setAlpha(0.75); + // ── Length buttons ──────────────────────────────────────────────────────── + // 6 labels + star, evenly slotted. Dimmed until toggled. + const _lenDefs = ["Tiny","Short","Medium","Long","XL","Plat"]; + const _lenTotal = _lenDefs.length + 0.8; // +0.8 gives star a slightly smaller slot + const _lenPadX = panelW * 0.03; + const _lenSlotW = (panelW - _lenPadX * 2) / _lenTotal; + const _lenY = extraPanelY + extraPanelH / 2; + const _lenObjects = []; + + _lenDefs.forEach((name, i) => { + const lx = panelLeft + _lenPadX + i * _lenSlotW + _lenSlotW / 2; + const lbl = this.add.bitmapText(lx, _lenY, "bigFont", name, 28) + .setScrollFactor(0).setDepth(106).setOrigin(0.5, 0.5).setTint(0x888888); + const zone = this.add.zone(lx, _lenY, _lenSlotW * 0.88, extraPanelH * 0.85) + .setScrollFactor(0).setDepth(107).setInteractive(); + zone.on("pointerdown", () => { + zone._dn = true; + this.tweens.killTweensOf(lbl); + this.tweens.add({ targets: lbl, scale: 1.15, duration: 80, ease: "Quad.Out" }); + }); + zone.on("pointerup", () => { + if (!zone._dn) return; zone._dn = false; + this.tweens.killTweensOf(lbl); + this.tweens.add({ targets: lbl, scale: 1, duration: 400, ease: "Bounce.Out" }); + lbl.setTint((lbl._active = !lbl._active) ? 0xffffff : 0x888888); + }); + zone.on("pointerout", () => { + if (!zone._dn) return; zone._dn = false; + this.tweens.killTweensOf(lbl); + this.tweens.add({ targets: lbl, scale: 1, duration: 200, ease: "Back.Out" }); + }); + _lenObjects.push(lbl, zone); + }); + + // Star after "Plat" — uses star_small01 (25x25), fixed base scale + const _starX = panelLeft + _lenPadX + _lenDefs.length * _lenSlotW + _lenSlotW * 0.35; + const _starH = extraPanelH * 0.68; + const _star = this.add.image(_starX, _lenY, "GJ_GameSheet03", "star_small01_001.png") + .setScrollFactor(0).setDepth(106).setOrigin(0.5, 0.5).setTint(0x888888); + const _starBase = _starH / _star.displayHeight; + _star.setScale(_starBase); + const _starZone = this.add.zone(_starX, _lenY, _lenSlotW * 0.7, extraPanelH * 0.85) + .setScrollFactor(0).setDepth(107).setInteractive(); + _starZone.on("pointerdown", () => { + _starZone._dn = true; + this.tweens.killTweensOf(_star); + this.tweens.add({ targets: _star, scale: _starBase * 1.15, duration: 80, ease: "Quad.Out" }); + }); + _starZone.on("pointerup", () => { + if (!_starZone._dn) return; _starZone._dn = false; + this.tweens.killTweensOf(_star); + this.tweens.add({ targets: _star, scale: _starBase, duration: 400, ease: "Bounce.Out" }); + _star.setTint((_star._active = !_star._active) ? 0xffdd00 : 0x888888); + }); + _starZone.on("pointerout", () => { + if (!_starZone._dn) return; _starZone._dn = false; + this.tweens.killTweensOf(_star); + this.tweens.add({ targets: _star, scale: _starBase, duration: 200, ease: "Back.Out" }); + }); + _lenObjects.push(_star, _starZone); this._searchOverlayObjects.push(gfx, qsLabel, filtersLabel, cornerBR, cornerBL, placeholderLabel, typedLabel, inputCursor, inputHitZone, innerBtn1, innerBtn2, innerBtn3, - filtersComingSoon, extraComingSoon); + ..._qsSearchObjects, ..._diffObjects, ..._lenObjects); let _loading = false; const _doSearch = async () => { @@ -2318,19 +2524,6 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" .setDepth(100) .setVisible(false); - this._cpsIndicator = this.add.bitmapText(10, 70, "bigFont", "0 CPS", 20) - .setOrigin(0, 0) - .setAlpha(0.4) - .setDepth(100) - .setVisible(false); - - this._bottedIndicator = this.add.bitmapText(10, 70, "bigFont", "Botted", 20) - .setOrigin(0, 0) - .setAlpha(0.4) - .setDepth(100) - .setTint(0xff0000) - .setVisible(false); - this.noclipFlash = this.add.rectangle( this.cameras.main.centerX, this.cameras.main.centerY, @@ -2380,12 +2573,6 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._settingsPopup = null; return; } - if (this._macroPopup) { - this.events.off("update", this._refreshMacroButtons); - this._macroPopup.destroy(); - this._macroPopup = null; - return; - } if (this._settingsLayerOverlay) { if (!this._settingsScreenClosing) { this._hideSettingsScreen(); @@ -2450,7 +2637,6 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._paused = false; this._pauseContainer = null; this._sfxVolume = localStorage.getItem("userSfxVol") ?? 1; - this._initMacroBot(); this.input.on("pointerdown", () => { if (!this._menuActive && !this._paused && !this._levelSelectOverlay && !this._levelWon && !window.isEditor) { this._pushButton(); @@ -2463,11 +2649,11 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" }); if (!window.gdpointerup) { window.gdpointerup = true; - window.addEventListener("pointerup", () => this._releaseButton(true)); + window.addEventListener("pointerup", () => this._releaseButton()); } if (!window.gdtouchend) { window.gdtouchend = true; - window.addEventListener("touchend", () => this._releaseButton(true)); + window.addEventListener("touchend", () => this._releaseButton()); } this.scale.on("enterfullscreen", () => this._onFullscreenChange(true)); this.scale.on("leavefullscreen", () => this._onFullscreenChange(false)); @@ -2532,6 +2718,8 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" } if (window.levelID) { this._openSearchMenu(); + // Clear after use so re-entering scene (exit level) doesn't re-trigger + window.levelID = null; } if (this.game.registry.get("autoStartGame")) { this.game.registry.remove("autoStartGame"); @@ -3237,10 +3425,6 @@ _buildPauseOverlay() { this._pauseContainer.add(settingsBtn); this._makeBouncyButton(settingsBtn, 0.64, () => this._buildSettingsPopup()); - this._macroBtn = this.add.image(textureY + _0x4eb71b / 2 - 60, 150, "macroBot").setScale(0.4).setInteractive(); - this._pauseContainer.add(this._macroBtn); - this._makeBouncyButton(this._macroBtn, 0.4, () => this._buildMacroPopup()); - this._pauseContainer.add(this.add.bitmapText(textureY, 65, "bigFont", window.currentlevel[1], 40).setOrigin(0.5, 0.5)); const _0x21dacf = 170; @@ -3358,38 +3542,34 @@ _buildSettingsPopup() { const dim = this.add.rectangle(centerX, centerY, screenWidth, screenHeight, 0, 150 / 255).setInteractive(); this._settingsPopup.add(dim); - const innerContainer = this.add.container(centerX, centerY).setScale(0); - this._settingsPopup.add(innerContainer); - const corner = 0.325 * this.textures.get("GJ_square01").source[0].width; - const panel = this._drawScale9(0, 0, panelWidth, panelHeight, 'GJ_square01', corner, 16777215, 1); - innerContainer.add(panel); + const panel = this._drawScale9(centerX, centerY, panelWidth, panelHeight, 'GJ_square01', corner, 16777215, 1); + this._settingsPopup.add(panel); - const closeBtn = this.add.image(-(panelWidth / 2) + 10, -(panelHeight / 2) + 10, 'GJ_WebSheet', "GJ_closeBtn_001.png").setScale(0.8).setInteractive(); - innerContainer.add(closeBtn); + const closeBtn = this.add.image(centerX - (panelWidth / 2) + 10, centerY - (panelHeight / 2) + 10, 'GJ_WebSheet', "GJ_closeBtn_001.png").setScale(0.8).setInteractive(); + this._settingsPopup.add(closeBtn); this._makeBouncyButton(closeBtn, 0.8, () => { this._settingsPopup.destroy(); this._settingsPopup = null; }); - const pages = ["Gameplay", "Visual"]; let currentPage = 0; - const pageTitle = this.add.bitmapText(0, -(panelHeight / 2) + 45, "bigFont", pages[currentPage], 40).setOrigin(0.5); - innerContainer.add(pageTitle); - const leftArrow = this.add.image(-(panelWidth / 2) - 130, 0, "GJ_GameSheet03", "GJ_arrow_01_001.png") + const pageTitle = this.add.bitmapText(centerX, centerY - (panelHeight / 2) + 45, "bigFont", pages[currentPage], 40).setOrigin(0.5); + this._settingsPopup.add(pageTitle); + const leftArrow = this.add.image(centerX - (panelWidth / 2) - 130, centerY, "GJ_GameSheet03", "GJ_arrow_01_001.png") .setFlipX(false).setInteractive(); - innerContainer.add(leftArrow); - const rightArrow = this.add.image((panelWidth / 2) + 130, 0, "GJ_GameSheet03", "GJ_arrow_01_001.png") + this._settingsPopup.add(leftArrow); + const rightArrow = this.add.image(centerX + (panelWidth / 2) + 130, centerY, "GJ_GameSheet03", "GJ_arrow_01_001.png") .setInteractive().setFlipX(true); - innerContainer.add(rightArrow); - const column1X = -200; - const column2X = 200; + this._settingsPopup.add(rightArrow); + const column1X = centerX - 200; + const column2X = centerX + 200; const checkOffset = -120; const textOffset = -70; const spacingY = 70; - const startY = -150; + const startY = centerY - 150; let pageContainer = this.add.container(0, 0); - innerContainer.add(pageContainer); + this._settingsPopup.add(pageContainer); const createToggle = (container, x, y, label, getVal, setVal, callback = null) => { const getTex = () => getVal() ? "GJ_checkOn_001.png" : "GJ_checkOff_001.png"; @@ -3401,127 +3581,8 @@ _buildSettingsPopup() { setVal(!getVal()); check.setTexture("GJ_GameSheet03", getTex()); if (callback) callback(getVal()); - if (this._saveSettings) this._saveSettings(); - }); - }; - const createNumberInput = (container, x, y, label, getVal, setVal) => { - const txt = this.add.bitmapText(x + textOffset, y, "bigFont", label, 25).setOrigin(0, 0.5); - container.add(txt); - - const boxX = x + checkOffset; - const boxY = y; - const boxW = 64; - const boxH = 48; - - const bgBoxGraphics = this.add.graphics(); - bgBoxGraphics.fillStyle(0x222222, 0.5); - bgBoxGraphics.fillRoundedRect(boxX - boxW / 2, boxY - boxH / 2, boxW, boxH, 8); - container.add(bgBoxGraphics); - - const hitArea = this.add.rectangle(boxX, boxY, boxW, boxH, 0x000000, 0) - .setOrigin(0.5) - .setInteractive({ useHandCursor: true }); - container.add(hitArea); - - let initialVal = getVal() || 1; - const valueTxt = this.add.bitmapText(boxX, boxY, "bigFont", initialVal.toString(), 28) - .setOrigin(0.5); - container.add(valueTxt); - - let isFocused = false; - let internalString = initialVal.toString(); - - const updateDisplay = () => { - if (isFocused) { - valueTxt.setText(internalString + "|"); - } else { - valueTxt.setText(internalString || " "); - } - }; - - const commitValue = () => { - isFocused = false; - - let val = parseFloat(internalString); - if (isNaN(val)) val = 1; - - if (val < 0.1) val = 0.1; - if (val > 10) val = 10; - - internalString = val.toString(); - valueTxt.setText(internalString); - - setVal(val); - if (this._saveSettings) this._saveSettings(); - }; - - hitArea.on('pointerdown', (pointer, localX, localY, event) => { - if (event) event.stopPropagation(); - - if (window._activeCustomInput && window._activeCustomInput !== commitValue) { - window._activeCustomInput(); - } - - isFocused = true; - window._activeCustomInput = commitValue; - - internalString = ""; - updateDisplay(); + this._saveSettings(); }); - - const outsideClickListener = () => { - if (isFocused) commitValue(); - }; - dim.on('pointerdown', outsideClickListener); - - const keydownListener = (event) => { - if (!isFocused) return; - - const key = event.key; - - if (key === "Enter") { - event.preventDefault(); - commitValue(); - return; - } - - if (key === "Backspace") { - event.preventDefault(); - internalString = internalString.slice(0, -1); - updateDisplay(); - return; - } - - if (/^[0-9.]$/.test(key)) { - event.preventDefault(); - - if (key === "." && internalString.includes(".")) return; - - const parts = internalString.split('.'); - - if (key === ".") { - if (parts[0].length === 0) return; - } else { - if (parts.length === 1 && parts[0].length >= 2) return; - if (parts.length === 2 && parts[1].length >= 2) return; - } - - internalString += key; - updateDisplay(); - } - }; - - window.addEventListener('keydown', keydownListener); - - const originalDestroy = container.destroy; - container.destroy = (...args) => { - window.removeEventListener('keydown', keydownListener); - if (dim) dim.off('pointerdown', outsideClickListener); - if (window._activeCustomInput === commitValue) { - window._activeCustomInput = null; - } - originalDestroy.apply(container, args); - }; }; const buildGameplayPage = (container) => { @@ -3552,21 +3613,10 @@ _buildSettingsPopup() { (v) => window.noClip = v, (v) => { if (this._noclipIndicator) this._noclipIndicator.setVisible(v); } ); - createToggle(container, column1X, startY + (spacingY * 4), "Noclip Accuracy", () => window.noClipAccuracy, (v) => window.noClipAccuracy = v ); - - createToggle(container, column1X, startY + (spacingY * 5), "Macro Bot", - () => window.macroBot, - (v) => window.macroBot = v - ); - - createNumberInput(container, column2X, startY, "Speedhack", - () => window.speedHack, - (v) => window.speedHack = v - ); }; const buildVisualPage = (container) => { @@ -3603,41 +3653,25 @@ _buildSettingsPopup() { () => window.solidWave, (v) => window.solidWave = v ); - - createToggle(container, column1X, startY + (spacingY * 5), "Show CPS", - () => window.showCPS, - (v) => window.showCPS = v - ); }; const buildPage = (idx) => { pageContainer.destroy(); pageContainer = this.add.container(0, 0); - innerContainer.add(pageContainer); + this._settingsPopup.add(pageContainer); pageTitle.setText(pages[idx]); - if (idx === 0) buildGameplayPage(pageContainer); else if (idx === 1) buildVisualPage(pageContainer); }; - buildPage(0); - this._makeBouncyButton(leftArrow, 1, () => { currentPage = (currentPage - 1 + pages.length) % pages.length; buildPage(currentPage); }); - this._makeBouncyButton(rightArrow, 1, () => { currentPage = (currentPage + 1) % pages.length; buildPage(currentPage); }); - this.tweens.add({ - targets: innerContainer, - scale: 1, - duration: 660, - ease: "Elastic.Out", - easeParams: [1, 0.6] - }); } _saveSettings() { const settings = { @@ -3651,9 +3685,6 @@ _buildSettingsPopup() { solidWaveTrail: window.solidWave, noclipAccuracy: window.noClipAccuracy, hitboxesOnDeath: window.hitboxesOnDeath, - showCPS: window.showCPS, - speedHack: window.speedHack, - macroBot: window.macroBot, showEditorGlow: window.showEditorGlow }; localStorage.setItem("gd_settings", JSON.stringify(settings)); @@ -3671,9 +3702,6 @@ _buildSettingsPopup() { solidWaveTrail: false, noclipAccuracy: false, hitboxesOnDeath: false, - showCPS: false, - speedHack: 1.0, - macroBot: false, showEditorGlow: false }; @@ -3689,173 +3717,9 @@ _buildSettingsPopup() { window.solidWave = data.solidWaveTrail; window.noClipAccuracy = data.noclipAccuracy; window.hitboxesOnDeath = data.hitboxesOnDeath; - window.showCPS = data.showCPS; - window.speedHack = data.speedHack; - window.macroBot = data.macroBot; window.showEditorGlow = data.showEditorGlow; } - _buildMacroPopup() { - if (this._macroPopup) return; - const centerX = screenWidth / 2; - const centerY = 320; - const panelWidth = 800; - const panelHeight = 400; - this._macroPopup = this.add.container(0, 0).setScrollFactor(0).setDepth(250); - const dim = this.add.rectangle(centerX, centerY, screenWidth, screenHeight, 0x000000, 150 / 255).setInteractive(); - this._macroPopup.add(dim); - - const corner = 0.325 * this.textures.get("GJ_square02").source[0].width; - const panel = this._drawScale9(centerX, centerY, panelWidth, panelHeight, "GJ_square02", corner, 0xffffff, 1); - this._macroPopup.add(panel); - - this._macroPopup.add(this.add.bitmapText(centerX, centerY - (panelHeight / 2) + 45, "bigFont", "Web Bot v1.0", 40).setOrigin(0.5)); - - if (this._macroName === undefined) { - this._macroName = this._macroBot?.meta?.name || null; - } - if (this._macroLoaded === undefined) { - this._macroLoaded = !!this._macroName || (this._macroBot && this._macroBot.inputs && this._macroBot.inputs.length > 0); - } - - const loadedNameText = this.add.bitmapText(centerX, centerY - (panelHeight / 2) + 95, "goldFont", this._macroLoaded ? `Currently loaded "${this._macroName || 'macro'}"` : "No macro loaded", 24).setOrigin(0.5); - this._macroPopup.add(loadedNameText); - - const optionsBtn = this.add.image(centerX, centerY - (panelHeight / 2) + 95, "GJ_GameSheet03", "GJ_optionsBtn02_001.png").setInteractive().setFlipY(true).setAngle(90).setScale(0.45); - this._macroPopup.add(optionsBtn); - - const closeBtn = this.add.image(centerX - (panelWidth / 2) + 20, centerY - (panelHeight / 2) + 20, "GJ_WebSheet", "GJ_closeBtn_001.png").setInteractive().setScale(0.8); - this._macroPopup.add(closeBtn); - - this._makeBouncyButton(closeBtn, 0.8, () => { - this.events.off("update", this._refreshMacroButtons); - this._macroPopup.destroy(); - this._macroPopup = null; - }); - - const importBtn = this.add.image(centerX - 300, centerY + 20,"importMacro").setInteractive(); - const exportBtn = this.add.image(centerX - 150, centerY + 20, "GJ_GameSheet03", "GJ_shareBtn_001.png").setInteractive().setFlipY(true).setAngle(90).setScale(0.53); - const createBtn = this.add.image(centerX, centerY + 20, "GJ_GameSheet03", "GJ_plusBtn_001.png").setInteractive().setFlipY(true).setAngle(90).setScale(1.2); - const playbackBtn = this.add.image(centerX + 150, centerY + 20, this._macroBot?.playing ? "stopPlayback" : "playbackMacro").setInteractive().setScale(0.25); - const recordBtn = this.add.image(centerX + 300, centerY + 20, this._macroBot?.recording ? "stopRecord" : "recordMacro").setInteractive().setScale(0.25); - - this._macroPopup.add([createBtn, importBtn, exportBtn, playbackBtn, recordBtn]); - - this._refreshMacroButtons = () => { - const playing = !!this._macroBot?.playing; - const recording = !!this._macroBot?.recording; - - let currentMetaName = this._macroBot?.meta?.name; - if (currentMetaName && currentMetaName !== this._macroName) { - this._macroName = currentMetaName; - this._macroLoaded = true; - } - - if (this._macroLoaded) { - loadedNameText.setText(`Currently loaded "${this._macroName || 'macro'}"`); - optionsBtn.setAlpha(1).setActive(true); - optionsBtn.x = centerX + (loadedNameText.width / 2) + 25; - } else { - loadedNameText.setText("No macro loaded"); - optionsBtn.setAlpha(0).setActive(false); - } - - playbackBtn.setTexture( - playing - ? "stopPlayback" - : "playbackMacro" - ); - - recordBtn.setTexture( - recording - ? "stopRecord" - : "recordMacro" - ); - - createBtn.setAlpha((playing || recording || this._macroLoaded) ? 0.5 : 1); - importBtn.setAlpha((playing || recording) ? 0.5 : 1); - exportBtn.setAlpha((playing || recording || !this._macroLoaded) ? 0.5 : 1); - playbackBtn.setAlpha((recording || !this._macroLoaded) ? 0.5 : 1); - recordBtn.setAlpha((playing || !this._macroLoaded) ? 0.5 : 1); - }; - - this._refreshMacroButtons(); - - this._makeBouncyButton(optionsBtn, 0.45, () => { - if (!this._macroLoaded) return; - const renamePrompt = prompt("New name", this._macroName); - if (renamePrompt && renamePrompt.trim() !== "") { - const cleanName = renamePrompt.trim(); - if (!this._macroBot) this._initMacroBot(); - - if (!this._macroBot.meta) { - this._macroBot.meta = {}; - } - this._macroBot.meta.name = cleanName; - this._macroName = cleanName; - this._refreshMacroButtons(); - } - }); - - this._makeBouncyButton(importBtn, 1, () => { - if (this._macroBot?.playing) return; - if (this._macroBot?.recording) return; - this._importMacroFile(); - }); - - this._makeBouncyButton(exportBtn, 0.53, () => { - if (this._macroBot?.playing) return; - if (this._macroBot?.recording) return; - if (!this._macroLoaded) return; - this._exportMacroFile(this._macroName ? `${this._macroName}.wbgdr` : null); - }); - - this._makeBouncyButton(createBtn, 1.2, () => { - if (this._macroBot?.playing || this._macroBot?.recording || this._macroLoaded) return; - const name = prompt("Enter macro name"); - if (name) { - if (!this._macroBot) this._initMacroBot(); - this._macroBot.resetAll(); - this._macroBot.meta.name = name; - this._macroName = name; - this._macroLoaded = true; - this._refreshMacroButtons(); - } - }); - - this._makeBouncyButton(playbackBtn, 0.25, () => { - if (this._macroBot?.recording) return; - if (!this._macroLoaded) return; - - if (this._macroBot?.playing) { - this._stopMacroPlayback(); - } else { - if (!this._macroBot) { - return; - } - const macro = this._macroBot.exportObject(); - this._startMacroPlayback(macro); - } - this._refreshMacroButtons(); - }); - - this._makeBouncyButton(recordBtn, 0.25, () => { - if (this._macroBot?.playing) return; - if (!this._macroLoaded) return; - - if (this._macroBot?.recording) { - this._stopMacroRecording(); - } else { - this._startMacroRecording({ - level: window.currentlevel?.[2] || "", - name: this._macroName - }); - } - - this._refreshMacroButtons(); - }); - - this.events.on("update", this._refreshMacroButtons); - } + _buildInfoPopup() { if (this._infoPopup) { return; @@ -3976,9 +3840,8 @@ _buildSettingsPopup() { this.tweens.add({ targets: bounceContainer, scale: { from: 0, to: 1 }, - duration: 660, - ease: "Elastic.Out", - easeParams: [1, 0.6] + duration: 500, + ease: "Bounce.Out" }); } _closeInfoPopup() { @@ -4141,9 +4004,8 @@ _buildSettingsPopup() { this.tweens.add({ targets: panelContainer, scale: 1, - duration: 660, - ease: "Elastic.Out", - easeParams: [1, 0.6] + duration: 400, + ease: "Bounce.Out" }); } _closeHowToPlayPopup() { @@ -4266,9 +4128,8 @@ _buildSettingsPopup() { this.tweens.add({ targets: bounceContainer, scale: { from: 0, to: 1 }, - duration: 660, - ease: "Elastic.Out", - easeParams: [1, 0.6] + duration: 500, + ease: "Bounce.Out" }); } _closeUpdateLogPopup() { @@ -4332,9 +4193,8 @@ _buildSettingsPopup() { this.tweens.add({ targets: bounceContainer, scale: { from: 0, to: 1 }, - duration: 660, - ease: "Elastic.Out", - easeParams: [1, 0.6] + duration: 500, + ease: "Bounce.Out" }); } _closeNewgroundsPopup() { @@ -4382,9 +4242,8 @@ _buildSettingsPopup() { this.tweens.add({ targets: bounceContainer, scale: { from: 0, to: 1 }, - duration: 660, - ease: "Elastic.Out", - easeParams: [1, 0.6] + duration: 500, + ease: "Bounce.Out" }); } _closeFeaturedInfoPopup() { @@ -4817,7 +4676,7 @@ _buildSettingsPopup() { this._player.enterWaveMode(); } } - _pushButton(ignoreMacro = false) { + _pushButton() { const objectsUnderPointer = this.input.manager.hitTest( this.input.activePointer, this._startPosGui.list, @@ -4834,12 +4693,6 @@ _buildSettingsPopup() { this._startGame(); return; } - - if (!cancelInput) { - if (!this._clickHistory) this._clickHistory = []; - this._clickHistory.push(this.time.now); - } - if (!this._slideIn && !this._state.isDead && !cancelInput) { this._state.upKeyDown = true; this._state.upKeyPressed = true; @@ -4856,76 +4709,11 @@ _buildSettingsPopup() { localStorage.setItem("gd_totalJumps", this._totalJumps); } } - - if (!ignoreMacro && this._macroBot) { - this._macroBot.recordEdge(true, this._physicsFrame); - } } - _releaseButton(ignoreMacro = false) { + _releaseButton() { this._state.upKeyDown = false; this._state.upKeyPressed = false; this._state.queuedHold = false; - if (!ignoreMacro && this._macroBot) { - this._macroBot.recordEdge(false, this._physicsFrame); - } - } - _initMacroBot() { - this._macroBot = new MacroBot(this); - window.macroBot = this._macroBot; - } - _startMacroRecording(meta = {}) { - if (!this._macroBot) this._initMacroBot(); - this._macroBot.startRecording({ - level: window.currentlevel?.[2] || "", - ...meta - }); - } - _stopMacroRecording() { - if (!this._macroBot) return null; - return this._macroBot.stopRecording(); - } - _startMacroPlayback(macroData) { - console.log(macroData); - if (!this._macroBot) this._initMacroBot(); - this._macroBot.startPlayback(macroData); - } - _stopMacroPlayback() { - if (this._macroBot) this._macroBot.stopPlayback(); - } - _exportMacroFile(filename = null) { - if (!this._macroBot) return; - const safeName = (filename || `${window.currentlevel?.[2] || "macro"}.gdr`) - .replace(/[^\w.\-]+/g, "_"); - this._macroBot.download(safeName); - } - _importMacroFile() { - const fileInput = document.createElement("input"); - fileInput.type = "file"; - fileInput.accept = ".wbgdr"; - - fileInput.onchange = async (e) => { - const file = e.target.files?.[0]; - if (!file) return; - - try { - if (!this._macroBot) this._initMacroBot(); - - const macroData = await this._macroBot.importFile(file); - this._macroBot.inputs = Array.isArray(macroData.inputs) ? macroData.inputs.slice() : []; - const fallback = file.name.replace(/\.[^/.]+$/, ""); - const macroName = macroData.meta?.name || fallback; - - this._macroBot.meta = macroData.meta || this._macroBot.meta; - this._macroBot.meta.name = macroName; - - this._macroName = macroName; - this._macroLoaded = true; - } catch (err) { - alert("Failed to import: " + err.message); - } - }; - - fileInput.click(); } _positionMenuItems() { const _0x1e5db8 = screenWidth / 2; @@ -5014,7 +4802,6 @@ _buildSettingsPopup() { this._endCameraOverride = false; this._endCamTween = null; this._spaceWasDown = false; - this._physicsFrame = 0; } _restartLevel() { this._attempts++; @@ -5140,13 +4927,6 @@ _buildSettingsPopup() { if (this._player && this._player._hitboxTrail) { this._player._hitboxTrail = []; } - - if (this._macroBot?.recording == true){ - this._macroBot?.clearRecording(); - } - if (this._macroBot?.playing == true){ - this._macroBot?.clearPlayback(); - } } _getStartPosMusicOffset(){ const startPositions = this._level.getStartPositions(); @@ -5204,11 +4984,11 @@ _buildSettingsPopup() { this._state.isSpider = false; this._state.isBird = false; if (checkpoint.isFlying) { - this._player.enterShipMode(null, true); // dont mess with y velocity if ur loading a checkpoint + this._player.enterShipMode(); } else if (checkpoint.isBall) { this._player.enterBallMode(); } else if (checkpoint.isUfo) { - this._player.enterUfoMode(null, true); // dont mess with y velocity if ur loading a checkpoint + this._player.enterUfoMode(); } else if (checkpoint.isWave) { this._player.enterWaveMode(); } else if (checkpoint.isSpider) { @@ -5230,8 +5010,6 @@ _buildSettingsPopup() { this._state.isUfo = checkpoint.isUfo; this._state.isSpider = checkpoint.isSpider; this._state.isBird = checkpoint.isBird; - this._state.ignorePortals = true; - this._state2.ignorePortals = true; this._level.resetGroundTiles(this._cameraX); this._level.resetObjects(); this._level._flyCeilingY = checkpoint.flyCeilingY; @@ -5290,19 +5068,6 @@ _buildSettingsPopup() { if (this._player && this._player._hitboxTrail) { this._player._hitboxTrail = []; } - - this._physicsFrame = checkpoint.physicsFrame; - if (this._macroBot?.recording == true){ - this._macroBot?.rollbackRecording(this._physicsFrame); - if (this._spaceKey.isDown || this._upKey.isDown || this._wKey.isDown || this._lKey.isDown){ - this._macroBot.recordEdge(true, this._physicsFrame); - } else { - this._macroBot.recordEdge(false, this._physicsFrame); - } - } - if (this._macroBot?.playing == true){ - this._macroBot?.rollbackPlayback(this._physicsFrame); - } } _onFullscreenChange(_0x310c5b) { if (!_0x310c5b) { @@ -5388,8 +5153,7 @@ _buildSettingsPopup() { } } _quantizeDelta(_0x654f39) { - const speed = window.speedHack || 1; - let _0x578d1b = (_0x654f39 * speed) / 1000 + this._deltaBuffer; + let _0x578d1b = _0x654f39 / 1000 + this._deltaBuffer; let _0x53e02e = Math.round(_0x578d1b / u); if (_0x53e02e < 0) { _0x53e02e = 0; @@ -5458,26 +5222,6 @@ _buildSettingsPopup() { this._accuracyIndicator.setText(`${this._player.noclipStats.accuracy.toFixed(2)}%`); this._deathsIndicator.setText(`${this._player.noclipStats.deaths} Deaths`); - this._cpsIndicator.setVisible(window.showCPS && !this._menuActive); - if (this._clickHistory && this._clickHistory.length > 0) { - this._clickHistory = this._clickHistory.filter(timestamp => this.time.now - timestamp <= 1000); - this._cpsIndicator.setText(`${this._clickHistory.length} CPS`); - } else { - this._cpsIndicator.setText("0 CPS"); - } - if (this._state.upKeyDown){ - this._cpsIndicator.setTint(0x00ff00); - } else{ - this._cpsIndicator.setTint(0xffffff); - } - this._cpsIndicator.setPosition(10, 10 + (window.noClip * 20) + (window.noClip && window.noClipAccuracy * 40)); - - this._bottedIndicator.setVisible(this._macroBot?.playing); - this._bottedIndicator.setPosition(10, 10 + (window.noClip * 20) + (window.noClip && window.noClipAccuracy * 40) + (window.showCPS * 20)); - if (this._macroBtn){ - this._macroBtn.setVisible(window.macroBot); - } - this._fpsAccum += deltaTime; this._fpsFrames++; if (this._fpsAccum >= 250) { @@ -5595,7 +5339,7 @@ _buildSettingsPopup() { this._spaceWasDown = _0x368ad9; const objectsUnderPointer = this.input.manager.hitTest( - this.input.activePointer, + this.input.activePointer, this._startPosGui.list, this.cameras.main ); @@ -5607,7 +5351,7 @@ _buildSettingsPopup() { this._state.upKeyDown = true; this._state.queuedHold = true; } - if (cancelInput) { + if (cancelInput){ this._state.upKeyDown = false; this._state.upKeyPressed = false; this._state.queuedHold = false; @@ -5766,11 +5510,6 @@ _buildSettingsPopup() { const initialY = this._state.y; for (let i = 0; i < subSteps; i++) { this._state.lastY = this._state.y; - this._physicsFrame++; - console.log(this._physicsFrame) - if (this._macroBot?.playing) { - this._macroBot.step(this._physicsFrame); - } this._player.updateJump(verticalDelta); this._state.y += this._state.yVelocity * verticalDelta; this._player.checkCollisions(this._playerWorldX - centerX); @@ -5801,8 +5540,6 @@ if (!this._state.isFlying && !this._state.isWave && !this._state.isUfo) { } } this._state.lastY = initialY; - this._state.ignorePortals = false; - this._state2.ignorePortals = false; if (!this._endCameraOverride) { const cameraOffsetX = this._playerWorldX - centerX; if (this._level.endXPos > 0) { @@ -7499,8 +7236,7 @@ _applyMirrorEffect() { const _0x452429 = ["Awesome!", "Good\nJob!", "Well\nDone!", "Impressive!", "Amazing!", "Incredible!", "Skillful!", "Brilliant!", "Not\nbad!", "Warp\nSpeed!", "Challenge\nBreaker!", "Reflex\nMaster!", "I am\nspeechless...", "You are...\nThe One!", "How is this\npossible!?", "You beat\nme..."]; const _0x165c06 = _0x452429[Math.floor(Math.random() * _0x452429.length)]; const _0x45540f = 225; - const _0x8e2b = ["\x5f\x6d\x61\x63\x72\x6f\x42\x6f\x74", "\x70\x6c\x61\x79\x69\x6e\x67"];let _0x3bc14 = 0xffffff; try {if (this[_0x8e2b[0]] && this[_0x8e2b[0]][_0x8e2b[1]]) {_0x3bc14 = (_0x3bc14 & 0xffff00) | 0xfa;}} catch (_0xe31) {}const _0x17fa2b = this.add.bitmapText(containerX + _0x45540f, _0x241209, "bigFont", _0x165c06, 40).setOrigin(0.5, 0.5).setScale(0.8).setCenterAlign();if (_0x3bc14 !== 0xffffff) _0x17fa2b.setTint(_0x3bc14); - this._endLayerInternal.add(_0x17fa2b); + this._endLayerInternal.add(this.add.bitmapText(containerX + _0x45540f, _0x241209, "bigFont", _0x165c06, 40).setOrigin(0.5, 0.5).setScale(0.8).setCenterAlign()); this._endLayerInternal.add(this.add.image(containerX - _0x45540f, 352.5, "GJ_WebSheet", "getIt_001.png").setScale(1 / 1.5)); const _0x34b1bd = [{ key: "downloadApple_001", diff --git a/assets/scripts/core/loading-screen.js b/assets/scripts/core/loading-screen.js index 7171db88..276e3abf 100644 --- a/assets/scripts/core/loading-screen.js +++ b/assets/scripts/core/loading-screen.js @@ -273,12 +273,6 @@ class BootScene extends Phaser.Scene { this.load.image("GJ_moveBtn", "assets/sprites/GJ_moveBtn.png"); this.load.image("GJ_moveSBtn", "assets/sprites/GJ_moveSBtn.png"); this.load.image("slidergroove2", "assets/sprites/slidergroove2.png"); - this.load.image("macroBot", "assets/sprites/macroBot.png"); - this.load.image("importMacro", "assets/sprites/importMacro.png"); - this.load.image("playbackMacro", "assets/sprites/playbackMacro.png"); - this.load.image("stopPlayback", "assets/sprites/stopPlayback.png"); - this.load.image("recordMacro", "assets/sprites/recordMacro.png"); - this.load.image("stopRecord", "assets/sprites/stopRecord.png"); for (let i = 1; i < 23; i++) { let index = i - 1; diff --git a/assets/scripts/core/player.js b/assets/scripts/core/player.js index ff795e26..3107defc 100644 --- a/assets/scripts/core/player.js +++ b/assets/scripts/core/player.js @@ -35,7 +35,6 @@ class PlayerState { this.isDashing = false; this.dashYVelocity = 0; this.isDual = false; - this.ignorePortals = false; } } @@ -940,7 +939,7 @@ if (this.p.isFlying || this.p.isUfo) { } } } - enterShipMode(_0xeb37c6 = null, fromCheckpoint = false) { + enterShipMode(_0xeb37c6 = null) { if (this.p.isFlying) { return; } @@ -948,9 +947,7 @@ if (this.p.isFlying || this.p.isUfo) { this.exitWaveMode(); this.p.isFlying = true; this._scene.toggleGlitter(true); - if (!fromCheckpoint){ // dont mess with y velocity if ur loading a checkpoint - this.p.yVelocity *= 0.5; - } + this.p.yVelocity *= 0.5; this.p.onGround = false; this.p.canJump = false; this.p.isJumping = false; @@ -1126,16 +1123,14 @@ if (this.p.isFlying || this.p.isUfo) { this.setCubeVisible(true); this._gameLayer.setFlyMode(false, 0); } - enterUfoMode(_portal = null, fromCheckpoint = false) { + enterUfoMode(_portal = null) { if (this.p.isUfo) return; this.exitBallMode(); this.exitWaveMode(); this.exitShipMode(); this.p.isUfo = true; this._scene.toggleGlitter(true); - if (!fromCheckpoint){ // dont mess with y velocity if ur loading a checkpoint - this.p.yVelocity *= 0.4; - } + this.p.yVelocity *= 0.4; this.p.onGround = false; this.p.canJump = false; this.p.isJumping = false; @@ -1984,10 +1979,6 @@ _updateWaveJump() { } if (_broadPhaseHit) { const _colType = gameObj.type; - if (this.p.ignorePortals && (_colType.startsWith("portal_") || _colType === "speed")) { - gameObj.activated = true; - continue; - } if (_colType === "portal_fly") { if (!gameObj.activated) { gameObj.activated = true; diff --git a/assets/sprites/importMacro.png b/assets/sprites/importMacro.png deleted file mode 100644 index 9d21c272..00000000 Binary files a/assets/sprites/importMacro.png and /dev/null differ diff --git a/assets/sprites/macroBot.png b/assets/sprites/macroBot.png deleted file mode 100644 index 3f9076bb..00000000 Binary files a/assets/sprites/macroBot.png and /dev/null differ diff --git a/assets/sprites/playbackMacro.png b/assets/sprites/playbackMacro.png deleted file mode 100644 index e52a1ba0..00000000 Binary files a/assets/sprites/playbackMacro.png and /dev/null differ diff --git a/assets/sprites/recordMacro.png b/assets/sprites/recordMacro.png deleted file mode 100644 index 127355ff..00000000 Binary files a/assets/sprites/recordMacro.png and /dev/null differ diff --git a/assets/sprites/stopPlayback.png b/assets/sprites/stopPlayback.png deleted file mode 100644 index 12eb128a..00000000 Binary files a/assets/sprites/stopPlayback.png and /dev/null differ diff --git a/assets/sprites/stopRecord.png b/assets/sprites/stopRecord.png deleted file mode 100644 index 1f38f904..00000000 Binary files a/assets/sprites/stopRecord.png and /dev/null differ diff --git a/gdbrowser/assets/Pusab.ttf b/gdbrowser/assets/Pusab.ttf new file mode 100644 index 00000000..e127119e Binary files /dev/null and b/gdbrowser/assets/Pusab.ttf differ diff --git a/gdbrowser/assets/arrow-left.png b/gdbrowser/assets/arrow-left.png new file mode 100644 index 00000000..f8a7c228 Binary files /dev/null and b/gdbrowser/assets/arrow-left.png differ diff --git a/gdbrowser/assets/arrow-right.png b/gdbrowser/assets/arrow-right.png new file mode 100644 index 00000000..adc61bb4 Binary files /dev/null and b/gdbrowser/assets/arrow-right.png differ diff --git a/gdbrowser/assets/back.png b/gdbrowser/assets/back.png new file mode 100644 index 00000000..9c0cab7c Binary files /dev/null and b/gdbrowser/assets/back.png differ diff --git a/gdbrowser/assets/bluebox.png b/gdbrowser/assets/bluebox.png new file mode 100644 index 00000000..fd2afe76 Binary files /dev/null and b/gdbrowser/assets/bluebox.png differ diff --git a/gdbrowser/assets/brownbox.png b/gdbrowser/assets/brownbox.png new file mode 100644 index 00000000..4dc28435 Binary files /dev/null and b/gdbrowser/assets/brownbox.png differ diff --git a/gdbrowser/assets/browncoin.png b/gdbrowser/assets/browncoin.png new file mode 100644 index 00000000..7cf03c10 Binary files /dev/null and b/gdbrowser/assets/browncoin.png differ diff --git a/gdbrowser/assets/btn-awarded.png b/gdbrowser/assets/btn-awarded.png new file mode 100644 index 00000000..f434fcde Binary files /dev/null and b/gdbrowser/assets/btn-awarded.png differ diff --git a/gdbrowser/assets/btn-back.png b/gdbrowser/assets/btn-back.png new file mode 100644 index 00000000..e8a825d4 Binary files /dev/null and b/gdbrowser/assets/btn-back.png differ diff --git a/gdbrowser/assets/btn-cancel-green.png b/gdbrowser/assets/btn-cancel-green.png new file mode 100644 index 00000000..4ea722e1 Binary files /dev/null and b/gdbrowser/assets/btn-cancel-green.png differ diff --git a/gdbrowser/assets/btn-cancel.png b/gdbrowser/assets/btn-cancel.png new file mode 100644 index 00000000..3f8075c7 Binary files /dev/null and b/gdbrowser/assets/btn-cancel.png differ diff --git a/gdbrowser/assets/btn-check.png b/gdbrowser/assets/btn-check.png new file mode 100644 index 00000000..2eab8cd7 Binary files /dev/null and b/gdbrowser/assets/btn-check.png differ diff --git a/gdbrowser/assets/btn-delete.png b/gdbrowser/assets/btn-delete.png new file mode 100644 index 00000000..2d362f72 Binary files /dev/null and b/gdbrowser/assets/btn-delete.png differ diff --git a/gdbrowser/assets/btn-done.png b/gdbrowser/assets/btn-done.png new file mode 100644 index 00000000..81205f93 Binary files /dev/null and b/gdbrowser/assets/btn-done.png differ diff --git a/gdbrowser/assets/btn-featured.png b/gdbrowser/assets/btn-featured.png new file mode 100644 index 00000000..6b6932cb Binary files /dev/null and b/gdbrowser/assets/btn-featured.png differ diff --git a/gdbrowser/assets/btn-followed.png b/gdbrowser/assets/btn-followed.png new file mode 100644 index 00000000..8e877bfe Binary files /dev/null and b/gdbrowser/assets/btn-followed.png differ diff --git a/gdbrowser/assets/btn-liked.png b/gdbrowser/assets/btn-liked.png new file mode 100644 index 00000000..f76c3104 Binary files /dev/null and b/gdbrowser/assets/btn-liked.png differ diff --git a/gdbrowser/assets/btn-magic.png b/gdbrowser/assets/btn-magic.png new file mode 100644 index 00000000..9e28c151 Binary files /dev/null and b/gdbrowser/assets/btn-magic.png differ diff --git a/gdbrowser/assets/btn-no.png b/gdbrowser/assets/btn-no.png new file mode 100644 index 00000000..892a3162 Binary files /dev/null and b/gdbrowser/assets/btn-no.png differ diff --git a/gdbrowser/assets/btn-recent.png b/gdbrowser/assets/btn-recent.png new file mode 100644 index 00000000..0f93f5fc Binary files /dev/null and b/gdbrowser/assets/btn-recent.png differ diff --git a/gdbrowser/assets/btn-submit.png b/gdbrowser/assets/btn-submit.png new file mode 100644 index 00000000..47786b40 Binary files /dev/null and b/gdbrowser/assets/btn-submit.png differ diff --git a/gdbrowser/assets/btn-top.png b/gdbrowser/assets/btn-top.png new file mode 100644 index 00000000..e1931145 Binary files /dev/null and b/gdbrowser/assets/btn-top.png differ diff --git a/gdbrowser/assets/btn-trending.png b/gdbrowser/assets/btn-trending.png new file mode 100644 index 00000000..17e2461d Binary files /dev/null and b/gdbrowser/assets/btn-trending.png differ diff --git a/gdbrowser/assets/btn-yes.png b/gdbrowser/assets/btn-yes.png new file mode 100644 index 00000000..92784c3f Binary files /dev/null and b/gdbrowser/assets/btn-yes.png differ diff --git a/gdbrowser/assets/check-off.png b/gdbrowser/assets/check-off.png new file mode 100644 index 00000000..f123dfda Binary files /dev/null and b/gdbrowser/assets/check-off.png differ diff --git a/gdbrowser/assets/check-on.png b/gdbrowser/assets/check-on.png new file mode 100644 index 00000000..a31df6a7 Binary files /dev/null and b/gdbrowser/assets/check-on.png differ diff --git a/gdbrowser/assets/close.png b/gdbrowser/assets/close.png new file mode 100644 index 00000000..f944dc99 Binary files /dev/null and b/gdbrowser/assets/close.png differ diff --git a/gdbrowser/assets/coin.png b/gdbrowser/assets/coin.png new file mode 100644 index 00000000..c6ab23fe Binary files /dev/null and b/gdbrowser/assets/coin.png differ diff --git a/gdbrowser/assets/copied.png b/gdbrowser/assets/copied.png new file mode 100644 index 00000000..a42dc3d6 Binary files /dev/null and b/gdbrowser/assets/copied.png differ diff --git a/gdbrowser/assets/corner.png b/gdbrowser/assets/corner.png new file mode 100644 index 00000000..d7dadd61 Binary files /dev/null and b/gdbrowser/assets/corner.png differ diff --git a/gdbrowser/assets/css/Pusab.ttf b/gdbrowser/assets/css/Pusab.ttf new file mode 100644 index 00000000..e127119e Binary files /dev/null and b/gdbrowser/assets/css/Pusab.ttf differ diff --git a/gdbrowser/assets/css/browser.css b/gdbrowser/assets/css/browser.css new file mode 100644 index 00000000..75512e95 --- /dev/null +++ b/gdbrowser/assets/css/browser.css @@ -0,0 +1,1447 @@ +@font-face {font-family: Pusab; src: url('../Pusab.ttf')} + +body { + margin: 0; + height: 100vh; + overflow: hidden; + background: #000; +} + +.levelBG { + background-image: linear-gradient(#0065FD, #002E73); + height: 100vh; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + background-attachment: fixed; +} + +.darkBG { + background-image: linear-gradient(#323232, #171717) !important; +} + +.vaultBG { + background-image: linear-gradient(#4B0062, #22002D) !important; +} + +.purpleBG { + background-image: linear-gradient(#6E00FD, #330074) !important; +} + +img, .noSelect { + user-select: none; +} + +.noClick { + pointer-events: none; +} + +.yesClick { + pointer-events: all; +} + +.cornerPiece { + position: sticky; +} + +.center { + text-align: center; + max-width: 100%; +} + +.fit { + width: fit-content; +} + +.supercenter { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%,-50%); +} + +.smallMargin { + margin-top: 1%; +} + +.topMargin { + margin-top: 3%; +} + +.topMargin2 { + margin-top: 4%; +} + +.small { + font-size: 7vh; +} + +.smaller { + font-size: 5vh; + -webkit-text-stroke-width: 0.20vh; + -webkit-text-stroke-color: black; + text-shadow: 0.35vh 0.35vh 0vh rgba(0, 0, 0, 0.3); +} + +.slightlySmaller { + font-size: 6vh; + -webkit-text-stroke-width: 0.25vh; + -webkit-text-stroke-color: black; + text-shadow: 0.35vh 0.35vh 0vh rgba(0, 0, 0, 0.3); +} + +.biggerShadow { + -webkit-text-stroke-width: 0.3vh; + -webkit-text-stroke-color: black; + text-shadow: 0.5vh 0.5vh 0vh rgba(0, 0, 0, 0.3); +} + +.bigger { + font-size: 3.5vh; +} + +.veryBig { + font-size: 8vh; +} + +.mini { + font-size: 3vh; + margin-top: 0.5%; +} + +.pre { + white-space: pre; +} + +.valign { + vertical-align: middle; +} + +.underline { + text-decoration: underline; +} + +.inline { + display: inline-block; +} + +.squeeze { + margin-left: -4%; +} + +.squeezeB { + margin-left: -8%; +} + +.normalCursor { + cursor: default; +} + +.help { + cursor: help; +} + +.outOfOrder, .darkDiff { + filter: brightness(50%); +} + +.darken, .youAreNotTheOne { + filter: brightness(65%); +} + +.youAreNotTheOne { + transform: scale(0.85) +} + +#everything { + width: 100%; + height: 100%; +} + +p { + font-family: aller, helvetica, arial; + color: white; + font-size: 2.9vh; + word-break: break-word; +} + +h1, h2, h3 { + font-family: Pusab, Arial; + font-weight: normal; + margin: 0% 0%; + letter-spacing: -0.01em; + -webkit-text-size-adjust: 100%; + -webkit-text-stroke-color: black; +} + +h1 { + color: white; + font-size: 6vh; + line-height: 100%; + white-space: nowrap; + -webkit-text-stroke-width: 0.25vh; + text-shadow: 0.375vh 0.375vh 0vh rgba(0, 0, 0, 0.3); +} + +h2 { + font-size: 8vh; + -webkit-text-stroke-width: 0.265vh; + background: -webkit-linear-gradient(#FDA00C, #FFE348); + background-clip: text; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + -webkit-filter: drop-shadow(0.25vh 0.25vh rgba(0, 0, 0, 0.25)); + filter: drop-shadow(0.25vh 0.25vh rgba(0, 0, 0, 0.25)); + text-shadow: none !important; +} + +h3, input[type=text], input[type=password], input[type=number], .h3Size { + font-size: 3.5vh; + color: white; + -webkit-text-stroke-width: 0.14vh; + -webkit-text-stroke-color: black; + text-shadow: 0.2vh 0.2vh 0.02vh rgba(0, 0, 0, 0.3); +} + +a { + text-decoration: none; + color: inherit; + -webkit-text-stroke-width: inherit; + -webkit-text-stroke-color: inherit; + text-shadow: inherit; +} + +hr { + border: none; + height: 0.3%; + margin: 1.5% 0%; + background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgba(255, 255, 255, 0.5)), to(rgba(0, 0, 0, 0))); +} + +input[type=text], input[type=password], input[type=number] { + padding-left: 1.2%; + border-radius: 1vh; + height: 80%; + margin-top: 1%; + width: 65%; + font-size: 5vh; + font-family: Pusab, Arial; +} + +input[type=checkbox], .changeDaWorld { + display: none; +} + +textarea { + resize: none; + font-family: aller, helvetica, arial; + padding: 2% 1%; + border-radius: 1vh; + height: 18.5vh; + margin-top: 1%; + width: 90%; + font-size: 3vh; + color: white; + text-align: center; + word-break: break-word; + white-space: initial !important; +} + +textarea::-webkit-scrollbar { + height: 8%; + width: 1.5vh; + background: #6d3c24; +} + +textarea::-webkit-scrollbar-thumb { + background: rgb(83, 47, 28); + overflow: hidden; +} + +input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active { + box-shadow: 0 0 0px 1000px #764F1A inset !important; + -webkit-box-shadow: 0 0 0px 1000px #764F1A inset !important; + -webkit-text-fill-color: white !important; +} + +.gdcheckbox { + vertical-align: middle; + display: inline-block; + background-image: url(../check-off.png); + background-repeat: no-repeat; + background-size: contain; + padding-right: 20%; + height: 5vh; + width: 5vh; + margin-right: 1vh; + cursor: pointer; +} + +input[type=checkbox]:checked + label.gdcheckbox { + background-image: url(../check-on.png); +} + +::placeholder { + color: #6F98D8; + font-size: 4vh; +} + +textarea::placeholder { + color: lightgray; + font-size: 3vh; +} + +#listLevels::placeholder { + color: rgba(211, 211, 211, 0.5); + font-size: 2.5vh; +} + +input:focus, textarea:focus { + outline: none; +} + +.copied { + border: 0 solid transparent; + border-radius: 10px; + padding: 0.5% 0; + background-color: rgba(0, 0, 0, 0.6); +} + +#iconsDiv img { + height: 9%; + margin: 1% 1%; + vertical-align: middle; +} + +.transparentBox, input[type=text], input[type=password], input[type=number], textarea { + border: 0 solid transparent; + border-radius: 2vh; + background-color: rgba(0, 0, 0, 0.3); + white-space: nowrap; +} + +#pageSelect { + height: 25%; + font-size: 5.5vh; + width: 18vh; + margin: 8% 0% 8% 0%; + text-align: center; + padding-left: 0; +} + +input[type='number'] { + -moz-appearance:textfield; +} + +input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { + -webkit-appearance: none; +} + +.lightBox { + border: 0.2vh solid #803E1E; + border-radius: 2vh; + background-color: #BE6F3F; + white-space: nowrap; +} + +.brownBox { + border-width: 2.5vh; + border-style: solid; + border-radius: 3vh; + background-color: #995533; + border-image: url('../brownbox.png') 10% round; +} + +.blueBox { + border-width: 2.5vh; + border-style: solid; + border-radius: 3vh; + background-color: #334499; + border-image: url('../bluebox.png') 10% round; +} + +.fancybox { + width: 69vh; + padding: 1vh 3vh; + border-width: 3.5vh; + border-style: solid; + border-radius: 3vh; + background-color: #001931; + border-image: url('../fancybox.png') 10% stretch; + border-image-slice: 65; +} + +.bounce { + animation: boxAnimator 0.25s; +} + +.epicbox { + + border-width: 3.5vh; + border-style: solid; + border-image: url('../epicbox.png') 20% stretch; + border-image-slice: 85 77; + border-image-width: 9.5vh; +} + +.leaderboardBox { + + border-width: 3.5vh; + border-style: solid; + border-image: url('../leaderboardbox.png') 20% stretch; + border-image-slice: 85 77; + border-image-width: 9.5vh; +} + +.levelButtons img { + height: 16%; +} + +.spaced { + margin-bottom: 2%; +} + +.lessSpaced { + margin-bottom: 1%; +} + +.sideSpace { + margin-left: 2%; +} + +.sideSpaceB { + margin-left: 4%; +} + +.sideSpaceC { + margin-left: 1%; +} + +.sideSpaceD { + margin-right: 25%; +} + +.rightSpace { + margin-right: 2%; +} + +.diffDiv { + display: inline-block; + width: 10%; + margin-left: 0.8%; + margin-right: 0.8%; + filter: brightness(50%); + text-align: center; +} + +.diffDiv img { + width: 75%; +} + +.demonDiff { + margin-left: 1.93%; + margin-right: 1.93%; + text-align: center; +} + +.demonDiff .smallTextWoo { + margin-top: 3.5%; + font-size: 2.7vh; +} + +.lengthDiv { + display: inline-block; + margin-left: 2%; + margin-right: 2%; + filter: brightness(50%); +} + +.lengthDiv h3 { + font-size: 4vh; +} + +.selectedFilter { + filter: brightness(100%); +} + +#filterStuff div { + text-align: left; + display: inline-block; + width: 30%; +} + +#filterStuff div h1, .smallerer { + font-size: 4vh; + -webkit-text-stroke-width: 0.18vh; + -webkit-text-stroke-color: black; + text-shadow: 0.3vh 0.3vh 0vh rgba(0, 0, 0, 0.3);} + +.sideButton { + margin-bottom: 30%; + height: 11% +} + +.msgAuthor:hover { + transform: scale(1.03); +} + +.gdButton { + cursor: pointer; + z-index: 1; + user-select: none; + pointer-events: all; + transition-duration: 0.07s; + transition-timing-function: ease-in-out; +} + +.gdButton:active, .gdButton:focus-visible, a:focus-visible .gdButton { + animation: bounceButton 0.25s ease-in-out forwards; +} + +.likeButton { + height: 14vh; + margin: 2% 1.2% 2% 1.2%; +} + +.iconRope { + cursor: pointer; + z-index: 1; + user-select: none; + transition-duration: 0.14s; + transition-timing-function: ease-in-out; +} + +.iconRope:active { + transform: translateY(10%) +} + +.socialButton { + width: 100%; + margin-bottom: 15%; +} + +.menuButtonList td { + padding: 1.2vh 2vh; +} + +.menuButtonList td a { + display: inline-block; +} + +.menuButton { + width: 24vh; + cursor: pointer; +} + +.menuButton:active, .menuButton:focus-visible, a:focus-visible .menuButton { + animation: bounceButton 0.25s ease-in-out forwards; +} + +.menuLink { + color: aqua; + text-decoration: underline; + cursor: pointer; +} + +.vaultLink { + color: aqua; + cursor: pointer; + filter: opacity(40%); +} + +.vaultLink:hover { + filter: opacity(100%); +} + +.youCanClickThis:hover { + border-bottom: 2px solid aqua +} + +.youCanClickThis2:hover { + border-bottom: 2px solid lime +} + +.unregistered:hover { + color: rgb(0, 230, 0); +} + +.popup { + position: fixed; + display: none; + width: 100%; + height: 100%; + top: 0; left: 0; right: 0; bottom: 0; + background-color: rgba(0,0,0,0.4); + z-index: 2; +} + +.gauntlet { + vertical-align: top; + width: 300px; + height: 50px; + margin: 0px 9px 250px 9px; + display: inline-block; + cursor: pointer; +} + +.gauntlet:hover, .mappack:hover { + transition-duration: 0.06s; + transition-timing-function: ease-in-out; + transform: translateY(-25%) scale(1.04) +} + +.mappack h3, .gauntlet h3 { + font-size: 35px +} + +.mappack { + vertical-align: top; + width: 250px; + height: 60px; + margin: 0px 9px 210px 9px; + display: inline-block; + cursor: pointer; +} + +.gauntletText { + font-size: 4vh; +} + +.leaderboardTab { + user-select: none; + -webkit-user-drag: none; + height: 9vh; +} + +.leaderboardClick { + cursor: pointer; +} + +.leaderboardClick:active { + filter: brightness(90%); +} + +#scoreTabs { + position: absolute; + text-align: center; + top: 2.45%; + width: 100%; + margin-left: -13.5vh +} + +#searchBox { + background-color: rgb(173, 115, 76); + width: 122vh; + height: 75%; + overflow-y: auto; + overflow-x: hidden; +} + +#searchBox::-webkit-scrollbar, #statusDiv::-webkit-scrollbar, #commentBox::-webkit-scrollbar { + display: none; +} + +.searchResult { + width: 80%; + height: 32%; + background-color: #A1582C; + margin: auto; + border-bottom: 0.18vh rgba(0, 0, 0, 0.4) solid; + padding-left: 18vh; + padding-top: 1vh; + white-space: nowrap; + overflow-x: hidden; +} + +.searchResult:nth-child(odd) { + background-color: #C1743F; +} + +#statusDiv, #commentBox { + overflow-x: hidden; + overflow-y: auto; +} + +.commentBG { + width: 100%; + height: 23vh; + background-color: #A1582C; + overflow: hidden; + margin: auto; + border-bottom: 0.18vh rgba(0, 0, 0, 0.4) solid; +} + +.compactBG { + height: 14vh; +} + +.commentBG:nth-child(odd) { + background-color: #b96c39; +} + +.oddComment { + background-color: #A1582C !important; +} +.evenComment { + background-color: #b96c39 !important; +} + +.comment { + margin: 1.5vh auto 0 auto; + width: 96%; + height: 18.5vh; + background-color: rgba(147, 79, 39, 0.8); + border-radius: 1.5vh; + text-align: left; + padding-top: 1.5vh; + padding-left: 1.5vh; +} + +.compact { + background-color: transparent; + padding-left: 0vh; + margin-top: 0.5vh; + transform: scale(0.8) translate(-13%, -12.5%) +} + + +.comment h2, .smallGold { + background: -webkit-linear-gradient(#e28000, #ffee44); + background-clip: text; + width: fit-content; + vertical-align: top; + font-size: 3.7vh; + -webkit-text-stroke-width: 0.14vh; + -webkit-text-stroke-color: black; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + -webkit-filter: drop-shadow(0.2vh 0.2vh rgba(0, 0, 0, 0.25)); + filter: drop-shadow(0.2vh 0.2vh rgba(0, 0, 0, 0.25)); +} + +.commentText { + margin-top: 1.6vh; + font-size: 3.5vh; + white-space: normal; + overflow: hidden; + margin: 0 3vh 0 0; +} + +.commentAlign { + height: 11vh; + display: table-cell; + vertical-align: middle; +} + +.commentDate { + transform: translate(-3vh, -4.8vh); + text-align: right; + font-size: 1.8vh; + color: rgba(0, 0, 0, 0.5); + pointer-events: none; +} + +.compactDate { + transform: translate(-3vh, -11.5vh); +} + +.commentPercent { + vertical-align: top; + margin: 0 0 0 1.5vh; + font-size: 2vh; + color: rgba(0, 0, 0, 0.5); +} + +.commentLikes { + transform: translate(-3vh, -24.8vh); + text-align: right; + font-size: 3.2vh; + pointer-events: none; +} + +.commentLikes h3 { + transform: translateY(-19%) +} + +.commentIcon { + margin-right: 1.25%; + width: 3.5%; +} + +.commentIcon img { + width: 100%; +} + +.commentRow { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; +} + +.creditsIcon { + height: 30%; + margin-bottom: 7%; +} + +.creditsIcon img { + height: 100%; +} + +.specialThanksIcon img { + width: 42%; + height: unset; +} + +.leaderboardSlot { + height: 25%; + display: flex; + flex-direction: row; + align-items: flex-start; + padding-left: 0%; + width: 100%; + overflow: hidden; +} + +.leaderboardName { + margin-right: 2.5%; +} + +.leaderboardStars { + display: flex; + flex-direction: row; + align-items: center; +} + +.weeklyStuff { + display: none; +} + +.ranking { + display: flex; + padding-left: 5%; + padding-right: 2%; + flex-direction: column; + justify-content: center; + align-items: center; + height: 88%; + width: 10% +} + +.ranking h2 { + width: 100%; + margin-top: 2%; +} + +.leaderboardIcon { + height: 100%; + display: flex; + align-items: flex-end; +} + +.leaderboardIcon img { + height: 80%; + max-width: 150%; +} + +.leaderboardSide { + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; + margin-top: 0.5% +} + +#collectibles, .leaderboardStats { + font-size: 4.3vh; + white-space: nowrap; +} + +#collectibles img { + transform: translate(-20%, -7%); + height: 6.5%; +} + +.leaderboardStats { + display: flex; + margin-top: 2%; + width: 100%; + align-items: center; +} + +.leaderboardStats img { + width: 4.3%; + margin-left: 1%; + margin-right: 2.5%; +} + +#boomling { + transform: rotate(350deg); + cursor: pointer; + user-select: none; + transition-duration: 0.06s; + transition-timing-function: ease-in-out; +} + +#boomling:hover { + transform: rotate(355deg) scale(1.1) translate(-4%, -6%); + cursor: pointer; + user-select: none; +} + +#boomling:active { + transform: rotate(355deg) scale(1.2) translate(-4%, -6%); +} + +#collectibles img:first-child, #collectibles img:last-child { + transform: translate(-20%, -10%); + height: 5.5%; +} + +#msgList { + margin: 2% auto; + width: 115vh; + height: 75%; + background-color: #BE6F3F; + overflow-y: scroll; + scrollbar-width: none; + -ms-overflow-style: none; +} + +#msgList::-webkit-scrollbar { + width: 0; + height: 0; +} + +#theMfMessage { + margin: 2% auto 1.2% auto; + width: 90%; + height: 65%; + display: table; + padding: 1% 3%; +} + +#theMfMessage p { + white-space: normal; + vertical-align: middle; + display: table-cell; + font-size: 3.5vh; +} + +#messageOptions img { + margin: 0% 5%; +} + +.gdMessage { + text-align: left; + padding-left: 10%; + padding-top: 0.75%; + height: 12.5vh; + width: auto; + overflow: hidden; + cursor: pointer; + border: 0.6vh solid transparent; + transition-duration: 0.07s; +} + +.gdMessage h3 { + font-size: 4vh; + min-height: 35%; +} + +.gdMessage:hover { + border: 0.6vh solid rgba(0, 0, 0, 0.5); +} + +.messageInput { + font-size: 3.5vh; + text-align: left; + padding: 1.5%; + overflow: hidden; + background-color: rgba(0, 0, 0, 0.35); +} + +.labelButton { + pointer-events: none; + position: relative; + bottom: 90%; + right: 9.25%; +} + +.labelButton label { + padding: 3% 3.5%; +} + +.xButton { + pointer-events: none; + position: relative; + bottom: 152%; + text-align: right; + margin-right: 2.5%; +} + +#selectCount { + position: absolute; + bottom: 7.5%; + left: 4.8%; + background-color: red; + width: 4.5vh; + height: 4.5vh; + border-radius: 10vh; + border: 0.25vh solid white; +} + +.msgDate { + text-align: left; + font-size: 1.9vh; + color: rgba(0, 0, 0, 0.5); + margin-top: 0.4%; +} + +.specialThanks { + display: inline-block; + width: 27%; + height: 21%; + margin: 0% 0% 7.5% 0%; +} + +.specialThanks h2 { + margin-bottom: 3%; + font-size: 4vh; +} + +.analysis { + height: 20%; + width: 90%; + margin: 1% auto; + padding: 0% 2%; + overflow-x: auto; + overflow-y: hidden; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.roundBottom { + border-bottom-left-radius: 2vh; + border-bottom-right-radius: 2vh; +} + +.analysis::-webkit-scrollbar, .levelCode::-webkit-scrollbar { + width: 1%; + background: rgba(0, 0, 0, 0.1); +} + +.analysis::-webkit-scrollbar-thumb, .levelCode::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.3); + overflow: hidden; +} + +#colorDiv { + height: auto; + min-height: 20%; + max-height: 60%; + overflow-y: auto; + overflow-x: auto; + border-bottom-left-radius: 2vh; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + white-space: normal; +} + +#colorDiv::-webkit-scrollbar, .levelCode::-webkit-scrollbar { + height: 8% !important; + width: unset !important; +} + +.levelCode { + width: 90%; + margin: 1% auto; + padding: 0% 2%; + overflow-x: hidden; + overflow-y: auto; + line-height: 1.5vh; + min-height: 12%; + max-height: 200%; + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.aColor { + margin: 1.3% 0.8%; + width: 15vh; +} + +.aColor div { + width: 60%; + height: 9%; + border-radius: 1vh; + display: inherit; +} + +.aColor h3 { + font-size: 3vh; +} + +.color { + cursor: pointer; +} + +.color:hover { + transform:scale(1.1); + transition-duration: 0.1s; + transition-timing-function: ease-in-out; +} + +.colorBox { + position: absolute; + height: 22vh; + width: 22vh; + border-radius: 2vh; + border: 0.75vh solid; + margin: 2.5% auto; + right: 20%; + top: 34%; +} + +.colorSection { + display: inline-block; + width: 30%; + margin: 3% 0; +} + +.colorSection h1 { + font-size: 4vh; +} + +.colorSection p { + font-size: 3.2vh; + margin: 3% auto; + padding: 0.5% 0; + background-color: rgba(0, 0, 0, 0.2); + border-color: rgba(0, 0, 0, 0.2); + border-radius: 1vh; + max-width: 80%; +} + +.colorCheckbox { + text-align: left; + margin: 3% 0 0.5% 7%; +} + +.colorCheckbox label { + height: 7%; + padding-right: 17%; +} + +.colorSection2 { + width: 55%; + text-align: left; + display: inline-block; + vertical-align: top; +} + +.copyDetails { + text-align: center; + width: 48%; + margin: 3% 0; +} + +.blendingDot { + text-align: left; + margin-left: 9%; + margin-top: -6%; + font-size: 3.5vh !important; + user-select: none; +} + +.copiedColor { + text-align: left; + margin-left: 7%; + margin-top: 3%; + font-size: 2.5vh !important; + user-select: none; +} + +.copiedHSV { + font-size: 2vh !important; +} + +.codeFont { + font-size: 1.5vh; + white-space: normal; + word-break: break-all; +} + +#codeLength { + font-size: 2.2vh; + margin-top: -0.3%; +} + +.portalImage { + height: 65%; + vertical-align: top; + margin-bottom: 1%; +} + +.portalDiv { + margin: 1% 1.5%; +} + +.portalDiv h3 { + transform: translateY(15%) +} + +.speedPortal { + height: 57%; + transform: translateY(-6%) +} + +.portalButton { + margin-right: 0.7%; + padding-right: 5vh; + height: 4%; +} + +.portalSetting { + text-align: left; + display: inline-block; + width: 23%; +} + +.triggerDiv { + margin: 1.6% 1.7%; +} + +.groupDiv { + margin: 1.2% 1.8%; +} + +.groupID { + font-size: 8vh; + margin: 0% 2%; + overflow: visible; +} + +.orbDiv, .blockDiv, .styleDiv { + margin: 1.75% 1.7%; +} + +.miscDiv { + margin: 1% 2%; +} + +.styleDiv { + margin-top: 3.5vh; +} + +#style { + border-top-right-radius: 2vh; + border-bottom-right-radius: 2vh; +} + +.styleBG { + background-position: 2vh; + outline: 0.4vh solid black; + outline-offset: -0.4vh; +} + +.flex { + display: flex; +} + +.flex img { + align-self: center; +} + +.colorCircle { + border: 3.75px solid black; + border-radius: 420px; +} + +.typeFilter { + background-color: rgba(0, 0, 0, 0.3); + padding: 0.75% 0.75%; + border-radius: 0.5vh; +} + +.typeFilter.achDeselected, .gameFilter.achDeselected { + filter: brightness(30%) saturate(50%); +} + +.rewardFilter.achDeselected { + filter: brightness(60%); +} + +.typeFilter.achDeselected { + background-color: rgba(0, 0, 0, 0.75); +} + +.labelHover { + color: yellow; + transform: scale(0.8); +} + +.achSelect { + cursor: pointer; + z-index: 1; + user-select: none; + pointer-events: all; +} + +.achSelect:active { + transform: scale(1.04); +} + +.gdpslogo { + margin-bottom: 0%; + border-radius: 10%; + filter: drop-shadow(0.5vh 0.5vh 0.15vh rgba(0, 0, 0, 0.6)) +} + +.menuDisabled, .downloadDisabled { + filter: opacity(50%); +} + +.downloadDisabled { + text-decoration: line-through; +} + +.hidey { + opacity: 0%; + pointer-events: none; + transition-duration: 0s !important; +} + +cr { color: #ff5a5a } +co { color: #ffa54b } +cy { color: #ffff00 } +cg { color: #40e348 } +ca { color: #00ffff } +cb { color: #60abef } +cp { color: #ff00ff } + +.red { + color: #ff0000 !important; +} + +.yellow { + color: #ffde00; +} + +.gold { + color: rgb(255, 200, 0); +} + +.green { + color: rgb(85, 204, 55); +} + +.lightgreen { + color: #4CDA5B +} + +.whatIfItWasPurple { + color: #FF82FF; +} + +.nong { + color: #FFAABE; +} + +.blue { + color: #27CEFA; +} + +.brightblue { + color: #99ffff +} + +.brightred { + color: #ffaaaa; +} + +.gray { + filter: grayscale(100%); +} + +.grayscale { + filter: grayscale(100%) brightness(0.7); +} + +.disabled { + filter: grayscale(100%) brightness(0.9); + pointer-events: none !important; +} + +.spin { + -webkit-animation: spin 2s linear infinite; + -moz-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; + mix-blend-mode: luminosity; +} + +@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } } +@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } } + +@keyframes spin { + 100% { + -webkit-transform: rotate(360deg); + transform:rotate(360deg); } + } + +@keyframes boxAnimator { + 0% { + transform: scale(0) translate(-50%, -50%); + transform-origin:left top + } + 75% { + transform: scale(1.075) translate(-50%, -50%); + transform-origin:left top + } + 100% { + transform: scale(1) translate(-50%, -50%); + transform-origin:left top + } +} +@keyframes menuBounce { + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.2); + } + 75% { + transform: scale(1.15); + } + 100% { + transform: scale(1.2); + } +} +@keyframes bounceButton { + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.12); + } + 75% { + transform: scale(1.06); + } + 100% { + transform: scale(1.1); + } +} + +/* + * Disable all transitions and animations if the user has reduced motion enabled in their sytem settings + * Also disabled on devices that may be slow to render new frames for performance optimization + */ +@media screen and + (prefers-reduced-motion: reduce), + (update: slow) { + *, *::before, *::after { + animation-duration: 0.001ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.001ms !important; + } +} \ No newline at end of file diff --git a/gdbrowser/assets/difficulties/auto-epic.png b/gdbrowser/assets/difficulties/auto-epic.png new file mode 100644 index 00000000..5d401e28 Binary files /dev/null and b/gdbrowser/assets/difficulties/auto-epic.png differ diff --git a/gdbrowser/assets/difficulties/auto-featured.png b/gdbrowser/assets/difficulties/auto-featured.png new file mode 100644 index 00000000..a831e99b Binary files /dev/null and b/gdbrowser/assets/difficulties/auto-featured.png differ diff --git a/gdbrowser/assets/difficulties/auto-legendary.png b/gdbrowser/assets/difficulties/auto-legendary.png new file mode 100644 index 00000000..de520304 Binary files /dev/null and b/gdbrowser/assets/difficulties/auto-legendary.png differ diff --git a/gdbrowser/assets/difficulties/auto-mythic.png b/gdbrowser/assets/difficulties/auto-mythic.png new file mode 100644 index 00000000..768e1a09 Binary files /dev/null and b/gdbrowser/assets/difficulties/auto-mythic.png differ diff --git a/gdbrowser/assets/difficulties/auto.png b/gdbrowser/assets/difficulties/auto.png new file mode 100644 index 00000000..c32fe2f5 Binary files /dev/null and b/gdbrowser/assets/difficulties/auto.png differ diff --git a/gdbrowser/assets/difficulties/demon-easy-epic.png b/gdbrowser/assets/difficulties/demon-easy-epic.png new file mode 100644 index 00000000..87217a8b Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-easy-epic.png differ diff --git a/gdbrowser/assets/difficulties/demon-easy-featured.png b/gdbrowser/assets/difficulties/demon-easy-featured.png new file mode 100644 index 00000000..3385a45c Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-easy-featured.png differ diff --git a/gdbrowser/assets/difficulties/demon-easy-legendary.png b/gdbrowser/assets/difficulties/demon-easy-legendary.png new file mode 100644 index 00000000..1811d5d6 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-easy-legendary.png differ diff --git a/gdbrowser/assets/difficulties/demon-easy-mythic.png b/gdbrowser/assets/difficulties/demon-easy-mythic.png new file mode 100644 index 00000000..4fb9caf1 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-easy-mythic.png differ diff --git a/gdbrowser/assets/difficulties/demon-easy.png b/gdbrowser/assets/difficulties/demon-easy.png new file mode 100644 index 00000000..82cc6d01 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-easy.png differ diff --git a/gdbrowser/assets/difficulties/demon-epic.png b/gdbrowser/assets/difficulties/demon-epic.png new file mode 100644 index 00000000..c802247b Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-epic.png differ diff --git a/gdbrowser/assets/difficulties/demon-extreme-epic.png b/gdbrowser/assets/difficulties/demon-extreme-epic.png new file mode 100644 index 00000000..3e8957a2 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-extreme-epic.png differ diff --git a/gdbrowser/assets/difficulties/demon-extreme-featured.png b/gdbrowser/assets/difficulties/demon-extreme-featured.png new file mode 100644 index 00000000..82025697 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-extreme-featured.png differ diff --git a/gdbrowser/assets/difficulties/demon-extreme-legendary.png b/gdbrowser/assets/difficulties/demon-extreme-legendary.png new file mode 100644 index 00000000..d4bd6491 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-extreme-legendary.png differ diff --git a/gdbrowser/assets/difficulties/demon-extreme-mythic.png b/gdbrowser/assets/difficulties/demon-extreme-mythic.png new file mode 100644 index 00000000..308901bb Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-extreme-mythic.png differ diff --git a/gdbrowser/assets/difficulties/demon-extreme.png b/gdbrowser/assets/difficulties/demon-extreme.png new file mode 100644 index 00000000..e97d15c3 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-extreme.png differ diff --git a/gdbrowser/assets/difficulties/demon-featured.png b/gdbrowser/assets/difficulties/demon-featured.png new file mode 100644 index 00000000..8034d67b Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-featured.png differ diff --git a/gdbrowser/assets/difficulties/demon-hard-epic.png b/gdbrowser/assets/difficulties/demon-hard-epic.png new file mode 100644 index 00000000..c802247b Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-hard-epic.png differ diff --git a/gdbrowser/assets/difficulties/demon-hard-featured.png b/gdbrowser/assets/difficulties/demon-hard-featured.png new file mode 100644 index 00000000..8034d67b Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-hard-featured.png differ diff --git a/gdbrowser/assets/difficulties/demon-hard-legendary.png b/gdbrowser/assets/difficulties/demon-hard-legendary.png new file mode 100644 index 00000000..da701803 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-hard-legendary.png differ diff --git a/gdbrowser/assets/difficulties/demon-hard-mythic.png b/gdbrowser/assets/difficulties/demon-hard-mythic.png new file mode 100644 index 00000000..e3120f03 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-hard-mythic.png differ diff --git a/gdbrowser/assets/difficulties/demon-hard.png b/gdbrowser/assets/difficulties/demon-hard.png new file mode 100644 index 00000000..10de48be Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-hard.png differ diff --git a/gdbrowser/assets/difficulties/demon-insane-epic.png b/gdbrowser/assets/difficulties/demon-insane-epic.png new file mode 100644 index 00000000..0bba8cce Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-insane-epic.png differ diff --git a/gdbrowser/assets/difficulties/demon-insane-featured.png b/gdbrowser/assets/difficulties/demon-insane-featured.png new file mode 100644 index 00000000..3c93c006 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-insane-featured.png differ diff --git a/gdbrowser/assets/difficulties/demon-insane-legendary.png b/gdbrowser/assets/difficulties/demon-insane-legendary.png new file mode 100644 index 00000000..d64ac815 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-insane-legendary.png differ diff --git a/gdbrowser/assets/difficulties/demon-insane-mythic.png b/gdbrowser/assets/difficulties/demon-insane-mythic.png new file mode 100644 index 00000000..c0b875ed Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-insane-mythic.png differ diff --git a/gdbrowser/assets/difficulties/demon-insane.png b/gdbrowser/assets/difficulties/demon-insane.png new file mode 100644 index 00000000..e722e861 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-insane.png differ diff --git a/gdbrowser/assets/difficulties/demon-legendary.png b/gdbrowser/assets/difficulties/demon-legendary.png new file mode 100644 index 00000000..da701803 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-legendary.png differ diff --git a/gdbrowser/assets/difficulties/demon-medium-epic.png b/gdbrowser/assets/difficulties/demon-medium-epic.png new file mode 100644 index 00000000..eb062b99 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-medium-epic.png differ diff --git a/gdbrowser/assets/difficulties/demon-medium-featured.png b/gdbrowser/assets/difficulties/demon-medium-featured.png new file mode 100644 index 00000000..8e5e947b Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-medium-featured.png differ diff --git a/gdbrowser/assets/difficulties/demon-medium-legendary.png b/gdbrowser/assets/difficulties/demon-medium-legendary.png new file mode 100644 index 00000000..6246e43d Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-medium-legendary.png differ diff --git a/gdbrowser/assets/difficulties/demon-medium-mythic.png b/gdbrowser/assets/difficulties/demon-medium-mythic.png new file mode 100644 index 00000000..be084a98 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-medium-mythic.png differ diff --git a/gdbrowser/assets/difficulties/demon-medium.png b/gdbrowser/assets/difficulties/demon-medium.png new file mode 100644 index 00000000..9b43d8f9 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-medium.png differ diff --git a/gdbrowser/assets/difficulties/demon-mythic.png b/gdbrowser/assets/difficulties/demon-mythic.png new file mode 100644 index 00000000..e3120f03 Binary files /dev/null and b/gdbrowser/assets/difficulties/demon-mythic.png differ diff --git a/gdbrowser/assets/difficulties/demon.png b/gdbrowser/assets/difficulties/demon.png new file mode 100644 index 00000000..10de48be Binary files /dev/null and b/gdbrowser/assets/difficulties/demon.png differ diff --git a/gdbrowser/assets/difficulties/easy-epic.png b/gdbrowser/assets/difficulties/easy-epic.png new file mode 100644 index 00000000..cc837c84 Binary files /dev/null and b/gdbrowser/assets/difficulties/easy-epic.png differ diff --git a/gdbrowser/assets/difficulties/easy-featured.png b/gdbrowser/assets/difficulties/easy-featured.png new file mode 100644 index 00000000..895116c2 Binary files /dev/null and b/gdbrowser/assets/difficulties/easy-featured.png differ diff --git a/gdbrowser/assets/difficulties/easy-legendary.png b/gdbrowser/assets/difficulties/easy-legendary.png new file mode 100644 index 00000000..5582d259 Binary files /dev/null and b/gdbrowser/assets/difficulties/easy-legendary.png differ diff --git a/gdbrowser/assets/difficulties/easy-mythic.png b/gdbrowser/assets/difficulties/easy-mythic.png new file mode 100644 index 00000000..32fbc7be Binary files /dev/null and b/gdbrowser/assets/difficulties/easy-mythic.png differ diff --git a/gdbrowser/assets/difficulties/easy.png b/gdbrowser/assets/difficulties/easy.png new file mode 100644 index 00000000..316e8297 Binary files /dev/null and b/gdbrowser/assets/difficulties/easy.png differ diff --git a/gdbrowser/assets/difficulties/hard-epic.png b/gdbrowser/assets/difficulties/hard-epic.png new file mode 100644 index 00000000..5e6fca14 Binary files /dev/null and b/gdbrowser/assets/difficulties/hard-epic.png differ diff --git a/gdbrowser/assets/difficulties/hard-featured.png b/gdbrowser/assets/difficulties/hard-featured.png new file mode 100644 index 00000000..7408021d Binary files /dev/null and b/gdbrowser/assets/difficulties/hard-featured.png differ diff --git a/gdbrowser/assets/difficulties/hard-legendary.png b/gdbrowser/assets/difficulties/hard-legendary.png new file mode 100644 index 00000000..51df986b Binary files /dev/null and b/gdbrowser/assets/difficulties/hard-legendary.png differ diff --git a/gdbrowser/assets/difficulties/hard.png b/gdbrowser/assets/difficulties/hard.png new file mode 100644 index 00000000..31b53fc1 Binary files /dev/null and b/gdbrowser/assets/difficulties/hard.png differ diff --git a/gdbrowser/assets/difficulties/harder-epic.png b/gdbrowser/assets/difficulties/harder-epic.png new file mode 100644 index 00000000..076b5ddc Binary files /dev/null and b/gdbrowser/assets/difficulties/harder-epic.png differ diff --git a/gdbrowser/assets/difficulties/harder-featured.png b/gdbrowser/assets/difficulties/harder-featured.png new file mode 100644 index 00000000..6d991936 Binary files /dev/null and b/gdbrowser/assets/difficulties/harder-featured.png differ diff --git a/gdbrowser/assets/difficulties/harder-legendary.png b/gdbrowser/assets/difficulties/harder-legendary.png new file mode 100644 index 00000000..7b69c33f Binary files /dev/null and b/gdbrowser/assets/difficulties/harder-legendary.png differ diff --git a/gdbrowser/assets/difficulties/harder-mythic.png b/gdbrowser/assets/difficulties/harder-mythic.png new file mode 100644 index 00000000..c179cfc7 Binary files /dev/null and b/gdbrowser/assets/difficulties/harder-mythic.png differ diff --git a/gdbrowser/assets/difficulties/harder.png b/gdbrowser/assets/difficulties/harder.png new file mode 100644 index 00000000..aa9138f9 Binary files /dev/null and b/gdbrowser/assets/difficulties/harder.png differ diff --git a/gdbrowser/assets/difficulties/insane-epic.png b/gdbrowser/assets/difficulties/insane-epic.png new file mode 100644 index 00000000..dcda9e2e Binary files /dev/null and b/gdbrowser/assets/difficulties/insane-epic.png differ diff --git a/gdbrowser/assets/difficulties/insane-featured.png b/gdbrowser/assets/difficulties/insane-featured.png new file mode 100644 index 00000000..10ae55e1 Binary files /dev/null and b/gdbrowser/assets/difficulties/insane-featured.png differ diff --git a/gdbrowser/assets/difficulties/insane-legendary.png b/gdbrowser/assets/difficulties/insane-legendary.png new file mode 100644 index 00000000..7d3423e0 Binary files /dev/null and b/gdbrowser/assets/difficulties/insane-legendary.png differ diff --git a/gdbrowser/assets/difficulties/insane-mythic.png b/gdbrowser/assets/difficulties/insane-mythic.png new file mode 100644 index 00000000..5b0407f5 Binary files /dev/null and b/gdbrowser/assets/difficulties/insane-mythic.png differ diff --git a/gdbrowser/assets/difficulties/insane.png b/gdbrowser/assets/difficulties/insane.png new file mode 100644 index 00000000..4150ef22 Binary files /dev/null and b/gdbrowser/assets/difficulties/insane.png differ diff --git a/gdbrowser/assets/difficulties/normal-epic.png b/gdbrowser/assets/difficulties/normal-epic.png new file mode 100644 index 00000000..f834cad6 Binary files /dev/null and b/gdbrowser/assets/difficulties/normal-epic.png differ diff --git a/gdbrowser/assets/difficulties/normal-featured.png b/gdbrowser/assets/difficulties/normal-featured.png new file mode 100644 index 00000000..a572f475 Binary files /dev/null and b/gdbrowser/assets/difficulties/normal-featured.png differ diff --git a/gdbrowser/assets/difficulties/normal-legendary.png b/gdbrowser/assets/difficulties/normal-legendary.png new file mode 100644 index 00000000..769a9f69 Binary files /dev/null and b/gdbrowser/assets/difficulties/normal-legendary.png differ diff --git a/gdbrowser/assets/difficulties/normal-mythic.png b/gdbrowser/assets/difficulties/normal-mythic.png new file mode 100644 index 00000000..175ea990 Binary files /dev/null and b/gdbrowser/assets/difficulties/normal-mythic.png differ diff --git a/gdbrowser/assets/difficulties/normal.png b/gdbrowser/assets/difficulties/normal.png new file mode 100644 index 00000000..23a5a34b Binary files /dev/null and b/gdbrowser/assets/difficulties/normal.png differ diff --git a/gdbrowser/assets/difficulties/unrated-epic.png b/gdbrowser/assets/difficulties/unrated-epic.png new file mode 100644 index 00000000..131e010e Binary files /dev/null and b/gdbrowser/assets/difficulties/unrated-epic.png differ diff --git a/gdbrowser/assets/difficulties/unrated-featured.png b/gdbrowser/assets/difficulties/unrated-featured.png new file mode 100644 index 00000000..66a10828 Binary files /dev/null and b/gdbrowser/assets/difficulties/unrated-featured.png differ diff --git a/gdbrowser/assets/difficulties/unrated.png b/gdbrowser/assets/difficulties/unrated.png new file mode 100644 index 00000000..eb7981fd Binary files /dev/null and b/gdbrowser/assets/difficulties/unrated.png differ diff --git a/gdbrowser/assets/dislike.png b/gdbrowser/assets/dislike.png new file mode 100644 index 00000000..ae6e7478 Binary files /dev/null and b/gdbrowser/assets/dislike.png differ diff --git a/gdbrowser/assets/double-arrow.png b/gdbrowser/assets/double-arrow.png new file mode 100644 index 00000000..2cc5325c Binary files /dev/null and b/gdbrowser/assets/double-arrow.png differ diff --git a/gdbrowser/assets/download.png b/gdbrowser/assets/download.png new file mode 100644 index 00000000..802ccefb Binary files /dev/null and b/gdbrowser/assets/download.png differ diff --git a/gdbrowser/assets/epicbox.png b/gdbrowser/assets/epicbox.png new file mode 100644 index 00000000..27898354 Binary files /dev/null and b/gdbrowser/assets/epicbox.png differ diff --git a/gdbrowser/assets/fancybox.png b/gdbrowser/assets/fancybox.png new file mode 100644 index 00000000..d3c473fc Binary files /dev/null and b/gdbrowser/assets/fancybox.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_backBtn_001.png b/gdbrowser/assets/game-sprites/GJ_backBtn_001.png new file mode 100644 index 00000000..796032ce Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_backBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_bigStar_001.png b/gdbrowser/assets/game-sprites/GJ_bigStar_001.png new file mode 100644 index 00000000..9fe9d17f Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_bigStar_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_checkOff_001.png b/gdbrowser/assets/game-sprites/GJ_checkOff_001.png new file mode 100644 index 00000000..baae23a4 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_checkOff_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_checkOn_001.png b/gdbrowser/assets/game-sprites/GJ_checkOn_001.png new file mode 100644 index 00000000..26e3a414 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_checkOn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_closeBtn_001.png b/gdbrowser/assets/game-sprites/GJ_closeBtn_001.png new file mode 100644 index 00000000..d6a1deb4 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_closeBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_featuredIcon_001.png b/gdbrowser/assets/game-sprites/GJ_featuredIcon_001.png new file mode 100644 index 00000000..c10c63ab Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_featuredIcon_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_filterIcon_001.png b/gdbrowser/assets/game-sprites/GJ_filterIcon_001.png new file mode 100644 index 00000000..70e0f1c1 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_filterIcon_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_listAddBtn_001.png b/gdbrowser/assets/game-sprites/GJ_listAddBtn_001.png new file mode 100644 index 00000000..dc331484 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_listAddBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn01_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn01_001.png new file mode 100644 index 00000000..e26ee13b Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn01_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn02_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn02_001.png new file mode 100644 index 00000000..6433a405 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn02_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn03_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn03_001.png new file mode 100644 index 00000000..b4144c1e Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn03_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn04_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn04_001.png new file mode 100644 index 00000000..43c28aca Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn04_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn05_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn05_001.png new file mode 100644 index 00000000..ffde0541 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn05_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn06_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn06_001.png new file mode 100644 index 00000000..9eecebc4 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn06_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_longBtn07_001.png b/gdbrowser/assets/game-sprites/GJ_longBtn07_001.png new file mode 100644 index 00000000..2325ba77 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_longBtn07_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_normalBtn_001.png b/gdbrowser/assets/game-sprites/GJ_normalBtn_001.png new file mode 100644 index 00000000..794baa93 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_normalBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_plainBtn_001.png b/gdbrowser/assets/game-sprites/GJ_plainBtn_001.png new file mode 100644 index 00000000..1ac64263 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_plainBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_playBtn2_001.png b/gdbrowser/assets/game-sprites/GJ_playBtn2_001.png new file mode 100644 index 00000000..c76437f0 Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_playBtn2_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_plus2Btn_001.png b/gdbrowser/assets/game-sprites/GJ_plus2Btn_001.png new file mode 100644 index 00000000..68add90b Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_plus2Btn_001.png differ diff --git a/gdbrowser/assets/game-sprites/GJ_plusBtn_001.png b/gdbrowser/assets/game-sprites/GJ_plusBtn_001.png new file mode 100644 index 00000000..28d6fcde Binary files /dev/null and b/gdbrowser/assets/game-sprites/GJ_plusBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/ws_GJ_closeBtn_001.png b/gdbrowser/assets/game-sprites/ws_GJ_closeBtn_001.png new file mode 100644 index 00000000..c9c39cc0 Binary files /dev/null and b/gdbrowser/assets/game-sprites/ws_GJ_closeBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/ws_GJ_menuBtn_001.png b/gdbrowser/assets/game-sprites/ws_GJ_menuBtn_001.png new file mode 100644 index 00000000..5fe4c9b9 Binary files /dev/null and b/gdbrowser/assets/game-sprites/ws_GJ_menuBtn_001.png differ diff --git a/gdbrowser/assets/game-sprites/ws_GJ_playBtn2_001.png b/gdbrowser/assets/game-sprites/ws_GJ_playBtn2_001.png new file mode 100644 index 00000000..e6b7eb92 Binary files /dev/null and b/gdbrowser/assets/game-sprites/ws_GJ_playBtn2_001.png differ diff --git a/gdbrowser/assets/game-sprites/ws_GJ_playBtn_001.png b/gdbrowser/assets/game-sprites/ws_GJ_playBtn_001.png new file mode 100644 index 00000000..d8b4b11d Binary files /dev/null and b/gdbrowser/assets/game-sprites/ws_GJ_playBtn_001.png differ diff --git a/gdbrowser/assets/large.png b/gdbrowser/assets/large.png new file mode 100644 index 00000000..2a5f8c5f Binary files /dev/null and b/gdbrowser/assets/large.png differ diff --git a/gdbrowser/assets/like.png b/gdbrowser/assets/like.png new file mode 100644 index 00000000..bf296c68 Binary files /dev/null and b/gdbrowser/assets/like.png differ diff --git a/gdbrowser/assets/listbutton.png b/gdbrowser/assets/listbutton.png new file mode 100644 index 00000000..30423681 Binary files /dev/null and b/gdbrowser/assets/listbutton.png differ diff --git a/gdbrowser/assets/loading.png b/gdbrowser/assets/loading.png new file mode 100644 index 00000000..dfedcd28 Binary files /dev/null and b/gdbrowser/assets/loading.png differ diff --git a/gdbrowser/assets/magnify.png b/gdbrowser/assets/magnify.png new file mode 100644 index 00000000..ff5ad238 Binary files /dev/null and b/gdbrowser/assets/magnify.png differ diff --git a/gdbrowser/assets/ok.png b/gdbrowser/assets/ok.png new file mode 100644 index 00000000..d45d1f03 Binary files /dev/null and b/gdbrowser/assets/ok.png differ diff --git a/gdbrowser/assets/orbs.png b/gdbrowser/assets/orbs.png new file mode 100644 index 00000000..44f6e835 Binary files /dev/null and b/gdbrowser/assets/orbs.png differ diff --git a/gdbrowser/assets/play.png b/gdbrowser/assets/play.png new file mode 100644 index 00000000..e51a7e1e Binary files /dev/null and b/gdbrowser/assets/play.png differ diff --git a/gdbrowser/assets/playbutton.png b/gdbrowser/assets/playbutton.png new file mode 100644 index 00000000..5fda582d Binary files /dev/null and b/gdbrowser/assets/playbutton.png differ diff --git a/gdbrowser/assets/plus.png b/gdbrowser/assets/plus.png new file mode 100644 index 00000000..c59001d4 Binary files /dev/null and b/gdbrowser/assets/plus.png differ diff --git a/gdbrowser/assets/plus_blue.png b/gdbrowser/assets/plus_blue.png new file mode 100644 index 00000000..8518e815 Binary files /dev/null and b/gdbrowser/assets/plus_blue.png differ diff --git a/gdbrowser/assets/random.png b/gdbrowser/assets/random.png new file mode 100644 index 00000000..ed60adc8 Binary files /dev/null and b/gdbrowser/assets/random.png differ diff --git a/gdbrowser/assets/refresh.png b/gdbrowser/assets/refresh.png new file mode 100644 index 00000000..61358f18 Binary files /dev/null and b/gdbrowser/assets/refresh.png differ diff --git a/gdbrowser/assets/search-user.png b/gdbrowser/assets/search-user.png new file mode 100644 index 00000000..f4a79bd4 Binary files /dev/null and b/gdbrowser/assets/search-user.png differ diff --git a/gdbrowser/assets/search.png b/gdbrowser/assets/search.png new file mode 100644 index 00000000..73756616 Binary files /dev/null and b/gdbrowser/assets/search.png differ diff --git a/gdbrowser/assets/silvercoin.png b/gdbrowser/assets/silvercoin.png new file mode 100644 index 00000000..8c905cec Binary files /dev/null and b/gdbrowser/assets/silvercoin.png differ diff --git a/gdbrowser/assets/song-custom.png b/gdbrowser/assets/song-custom.png new file mode 100644 index 00000000..3e55291e Binary files /dev/null and b/gdbrowser/assets/song-custom.png differ diff --git a/gdbrowser/assets/song-normal.png b/gdbrowser/assets/song-normal.png new file mode 100644 index 00000000..79d88e73 Binary files /dev/null and b/gdbrowser/assets/song-normal.png differ diff --git a/gdbrowser/assets/star.png b/gdbrowser/assets/star.png new file mode 100644 index 00000000..59bc2b1d Binary files /dev/null and b/gdbrowser/assets/star.png differ diff --git a/gdbrowser/assets/time.png b/gdbrowser/assets/time.png new file mode 100644 index 00000000..14615f9a Binary files /dev/null and b/gdbrowser/assets/time.png differ diff --git a/gdbrowser/assets/trophy.png b/gdbrowser/assets/trophy.png new file mode 100644 index 00000000..6250c1bc Binary files /dev/null and b/gdbrowser/assets/trophy.png differ diff --git a/gdbrowser/assets/twoPlayer.png b/gdbrowser/assets/twoPlayer.png new file mode 100644 index 00000000..1fc010e0 Binary files /dev/null and b/gdbrowser/assets/twoPlayer.png differ diff --git a/gdbrowser/assets/view.png b/gdbrowser/assets/view.png new file mode 100644 index 00000000..99306e40 Binary files /dev/null and b/gdbrowser/assets/view.png differ diff --git a/gdbrowser/assets/whitearrow-left.png b/gdbrowser/assets/whitearrow-left.png new file mode 100644 index 00000000..858fc56b Binary files /dev/null and b/gdbrowser/assets/whitearrow-left.png differ diff --git a/gdbrowser/assets/whitearrow-right.png b/gdbrowser/assets/whitearrow-right.png new file mode 100644 index 00000000..f23ec742 Binary files /dev/null and b/gdbrowser/assets/whitearrow-right.png differ diff --git a/gdbrowser/dragscroll.js b/gdbrowser/dragscroll.js new file mode 100644 index 00000000..8646f7f9 --- /dev/null +++ b/gdbrowser/dragscroll.js @@ -0,0 +1,30 @@ +function somethingSelected() { + return typeof window.getSelection == 'function' && window.getSelection().toString() != ""; +} +const remover = / |\n|\t/g; +$('.dragscroll').each(function(_, el) { + let previouslyMouseDown = false; + el.addEventListener('mousemove', function(e) { + if (e.buttons != 1) { + if (previouslyMouseDown) { + el.style.removeProperty('user-select'); + el.style.removeProperty('-webkit-user-select'); + previouslyMouseDown = false; + } + return; + } + if (somethingSelected()) + return; + if (!previouslyMouseDown) { + for (let el of e.target.childNodes) { + if (el.nodeType === Node.TEXT_NODE && el.textContent.replace(remover, '').length) + return; + } + el.style['user-select'] = 'none'; + el.style['-webkit-user-select'] = 'none'; + previouslyMouseDown = true; + } + //el.scrollLeft -= e.movementX; + el.scrollTop -= e.movementY; + }, {passive: true}); +}); \ No newline at end of file diff --git a/gdbrowser/global.js b/gdbrowser/global.js new file mode 100644 index 00000000..653b73ae --- /dev/null +++ b/gdbrowser/global.js @@ -0,0 +1,157 @@ +$('body').append(` + +`) + + +$(window).resize(function () { + if (window.innerHeight > window.innerWidth - 75) { + $('#everything').hide(); + $('#tooSmall').show(); + } + + else { + $('#everything').show(); + $('#tooSmall').hide() + } +}); + +function saveUrl() { + if (window.location.href.endsWith('?download')) return; + sessionStorage.setItem('prevUrl', window.location.href); +} + +function backButton() { + if (window.history.length > 1 && document.referrer.startsWith(window.location.origin)){ + if (window.location.href.endsWith('?download') && sessionStorage.getItem('prevUrl') === window.location.href.replace('?download', '')) window.history.go(-2); + else window.history.back() + } + else window.location.href = "../../../../../" +} + +let gdps = null +let onePointNine = false + +function Fetch(link) { + return new Promise(function (res, rej) { + fetch(link).then(resp => { + if (!resp.ok) return rej(resp) + gdps = resp.headers.get('gdps') + if (gdps && gdps.startsWith('1.9/')) { onePointNine = true; gdps = gdps.slice(4) } + resp.json().then(res) + }).catch(rej) + }) +} + +let allowEsc = true; +let popupEsc = true; + +$(document).keydown(function(k) { + if (k.keyCode == 27) { //esc + if (!allowEsc) return + k.preventDefault() + if (popupEsc && $('.popup').is(":visible")) $('.popup').hide(); + else $('#backButton').trigger('click') + } +}); + +let iconData = null +let iconCanvas = null +let iconRenderer = null +let overrideLoader = false +let renderedIcons = {} + +// very shitty code :) i suck at this stuff + +async function renderIcons() { + if (overrideLoader) return + let iconsToRender = $('gdicon:not([rendered], [dontload])') + if (iconsToRender.length < 1) return + if (!iconData) iconData = await Fetch("../api/icons") + if (!iconCanvas) iconCanvas = document.createElement('canvas') + if (!iconRenderer) iconRenderer = new PIXI.Application({ view: iconCanvas, width: 300, height: 300, backgroundAlpha: 0}); + if (loader.loading) return overrideLoader = true + buildIcon(iconsToRender, 0) +} + +function buildIcon(elements, current) { + if (current >= elements.length) return + let currentIcon = elements.eq(current) + + let cacheID = currentIcon.attr('cacheID') + let foundCache = renderedIcons[cacheID] + if (foundCache) { + finishIcon(currentIcon, foundCache.name, foundCache.data) + return buildIcon(elements, current + 1) + } + + let iconConfig = { + id: +currentIcon.attr('iconID'), + form: parseIconForm(currentIcon.attr('iconForm')), + col1: parseIconColor(currentIcon.attr('col1')), + col2: parseIconColor(currentIcon.attr('col2')), + glow: currentIcon.attr('glow') == "true", + app: iconRenderer + } + + loadIconLayers(iconConfig.form, iconConfig.id, function(a, b, c) { + if (c) iconConfig.new = true + new Icon(iconConfig, function(icon) { + let dataURL = icon.toDataURL() + let titleStr = `${Object.values(iconData.forms).find(x => x.form == icon.form).name} ${icon.id}` + if (cacheID) renderedIcons[cacheID] = {name: titleStr, data: dataURL} + finishIcon(currentIcon, titleStr, dataURL) + if (overrideLoader) { + overrideLoader = false + renderIcons() + } + else buildIcon(elements, current + 1) + }) + }) +} + +function finishIcon(currentIcon, name, data) { + currentIcon.append(``) + currentIcon.attr("rendered", "true") +} + +// reset scroll +while ($(this).scrollTop() != 0) { + $(this).scrollTop(0); +} + +$(document).ready(function() { + $(window).trigger('resize'); +}); + +// Adds all necessary elements into the tab index (all buttons and links that aren't natively focusable) +const inaccessibleLinkSelector = "*:not(a) > img.gdButton, .leaderboardTab, .gdcheckbox, .diffDiv, .lengthDiv"; + +document.querySelectorAll(inaccessibleLinkSelector).forEach(elem => { + elem.setAttribute('tabindex', 0); +}) + +document.getElementById('backButton')?.setAttribute('tabindex', 1); // Prioritize back button, first element to be focused + +// Event listener to run a .click() function if +window.addEventListener("keydown", e => { + if(e.key !== 'Enter') return; + + const active = document.activeElement; + const isUnsupportedLink = active.hasAttribute('tabindex'); // Only click on links that aren't already natively supported to prevent double clicking + if(isUnsupportedLink) active.click(); +}) + +// stolen from stackoverflow +$.fn.isInViewport = function () { + let elementTop = $(this).offset().top; + let elementBottom = elementTop + $(this).outerHeight(); + let viewportTop = $(window).scrollTop(); + let viewportBottom = viewportTop + $(window).height(); + return elementBottom > viewportTop && elementTop < viewportBottom; +}; \ No newline at end of file diff --git a/gdbrowser/results.html b/gdbrowser/results.html new file mode 100644 index 00000000..9fb82816 --- /dev/null +++ b/gdbrowser/results.html @@ -0,0 +1,250 @@ + + Level Search + + + + + + + + +
+ + + +
+ +
+
+ +
+ + + +
+ +
+

+
+ +
+

+
+ +
+ +
+ + + +
+ +
+ +
+ +
+
+ +
+ + + +
+ + + + + diff --git a/gdbrowser/search.html b/gdbrowser/search.html new file mode 100644 index 00000000..e9569eb2 --- /dev/null +++ b/gdbrowser/search.html @@ -0,0 +1,295 @@ + + + + Level Search + + + + + + + +
+ + + +
+ +
+
+ +
+ +
+
+ + + +
+
+ +
+

Quick Search

+
+ +
+ + + +
+ + + +
+ + + +
+ +
+

Filters

+
+ +
+

N/A

+

Easy

+

Normal

+

Hard

+

Harder

+

Insane

+

Demon

+

Auto

+
+ + + +
+

Tiny

+

Short

+

Medium

+

Long

+

XL

+
+
+ + +
+ +
+ + +
+ + +
+ +
+ + + + + diff --git a/index.html b/index.html index 146f5979..a981fe36 100644 --- a/index.html +++ b/index.html @@ -6,20 +6,114 @@ Web Dashers + + + + + + + + + + + - - - - - - - - - - - - - @@ -29,7 +123,6 @@ - @@ -37,20 +130,15 @@ - + + -