import { LitElement, html } from "lit"; import { customElement, query, state } from "lit/decorators.js"; import { translateText } from "../client/Utils"; import { UserSettings } from "../core/game/UserSettings"; import "./components/baseComponents/setting/SettingKeybind"; import { SettingKeybind } from "./components/baseComponents/setting/SettingKeybind"; import "./components/baseComponents/setting/SettingNumber"; import "./components/baseComponents/setting/SettingSlider"; import "./components/baseComponents/setting/SettingToggle"; @customElement("user-setting") export class UserSettingModal extends LitElement { private userSettings: UserSettings = new UserSettings(); @state() private settingsMode: "basic" | "keybinds" = "basic"; @state() private keybinds: Record = {}; @state() private keySequence: string[] = []; @state() private showEasterEggSettings = false; connectedCallback() { super.connectedCallback(); window.addEventListener("keydown", this.handleKeyDown); const savedKeybinds = localStorage.getItem("settings.keybinds"); if (savedKeybinds) { try { this.keybinds = JSON.parse(savedKeybinds); } catch (e) { console.warn("Invalid keybinds JSON:", e); } } } @query("o-modal") private modalEl!: HTMLElement & { open: () => void; close: () => void; isModalOpen: boolean; }; createRenderRoot() { return this; } disconnectedCallback() { window.removeEventListener("keydown", this.handleKeyDown); super.disconnectedCallback(); document.body.style.overflow = "auto"; } private handleKeyDown = (e: KeyboardEvent) => { if (!this.modalEl?.isModalOpen || this.showEasterEggSettings) return; if (e.code === "Escape") { e.preventDefault(); this.close(); } const key = e.key.toLowerCase(); const nextSequence = [...this.keySequence, key].slice(-4); this.keySequence = nextSequence; if (nextSequence.join("") === "evan") { this.triggerEasterEgg(); this.keySequence = []; } }; private triggerEasterEgg() { console.log("🪺 Setting~ unlocked by EVAN combo!"); this.showEasterEggSettings = true; const popup = document.createElement("div"); popup.className = "easter-egg-popup"; popup.textContent = "🎉 You found a secret setting!"; document.body.appendChild(popup); setTimeout(() => { popup.remove(); }, 5000); } toggleDarkMode(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") { console.warn("Unexpected toggle event payload", e); return; } this.userSettings.set("settings.darkMode", enabled); if (enabled) { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } console.log("🌙 Dark Mode:", enabled ? "ON" : "OFF"); } private toggleEmojis(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.emojis", enabled); console.log("🤡 Emojis:", enabled ? "ON" : "OFF"); } private toggleAlertFrame(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.alertFrame", enabled); console.log("🚨 Alert frame:", enabled ? "ON" : "OFF"); } private toggleFxLayer(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.specialEffects", enabled); console.log("💥 Special effects:", enabled ? "ON" : "OFF"); } private toggleAnonymousNames(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.anonymousNames", enabled); console.log("🙈 Anonymous Names:", enabled ? "ON" : "OFF"); } private toggleLobbyIdVisibility(e: CustomEvent<{ checked: boolean }>) { const hideIds = e.detail?.checked; if (typeof hideIds !== "boolean") return; this.userSettings.set("settings.lobbyIdVisibility", !hideIds); // Invert because checked=hide console.log("👁️ Hidden Lobby IDs:", hideIds ? "ON" : "OFF"); } private toggleLeftClickOpensMenu(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.leftClickOpensMenu", enabled); console.log("🖱️ Left Click Opens Menu:", enabled ? "ON" : "OFF"); this.requestUpdate(); } private sliderAttackRatio(e: CustomEvent<{ value: number }>) { const value = e.detail?.value; if (typeof value === "number") { const ratio = value / 100; localStorage.setItem("settings.attackRatio", ratio.toString()); } else { console.warn("Slider event missing detail.value", e); } } private sliderTroopRatio(e: CustomEvent<{ value: number }>) { const value = e.detail?.value; if (typeof value === "number") { const ratio = value / 100; localStorage.setItem("settings.troopRatio", ratio.toString()); } else { console.warn("Slider event missing detail.value", e); } } private toggleTerritoryPatterns(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.territoryPatterns", enabled); console.log("🏳️ Territory Patterns:", enabled ? "ON" : "OFF"); } private togglePerformanceOverlay(e: CustomEvent<{ checked: boolean }>) { const enabled = e.detail?.checked; if (typeof enabled !== "boolean") return; this.userSettings.set("settings.performanceOverlay", enabled); } private handleKeybindChange( e: CustomEvent<{ action: string; value: string }>, ) { const { action, value } = e.detail; const prevValue = this.keybinds[action] ?? ""; const values = Object.entries(this.keybinds) .filter(([k]) => k !== action) .map(([, v]) => v); if (values.includes(value) && value !== "Null") { const popup = document.createElement("div"); popup.className = "setting-popup"; popup.textContent = `The key "${value}" is already assigned to another action.`; document.body.appendChild(popup); const element = this.renderRoot.querySelector( `setting-keybind[action="${action}"]`, ) as SettingKeybind; if (element) { element.value = prevValue; element.requestUpdate(); } return; } this.keybinds = { ...this.keybinds, [action]: value }; localStorage.setItem("settings.keybinds", JSON.stringify(this.keybinds)); } render() { return html` (this.settingsMode = "basic")} > ${translateText("user_setting.tab_basic")} (this.settingsMode = "keybinds")} > ${translateText("user_setting.tab_keybinds")} ${this.settingsMode === "basic" ? this.renderBasicSettings() : this.renderKeybindSettings()} `; } private renderBasicSettings() { return html` ) => this.toggleDarkMode(e)} > ${this.showEasterEggSettings ? html` { const value = e.detail?.value; if (value !== undefined) { console.log("Changed:", value); } else { console.warn("Slider event missing detail.value", e); } }} > { const value = e.detail?.value; if (value !== undefined) { console.log("Changed:", value); } else { console.warn("Slider event missing detail.value", e); } }} > ` : null} `; } private renderKeybindSettings() { return html` ${translateText("user_setting.view_options")} ${translateText("user_setting.attack_ratio_controls")} ${translateText("user_setting.attack_keybinds")} ${translateText("user_setting.zoom_controls")} ${translateText("user_setting.camera_movement")} `; } public open() { this.requestUpdate(); this.modalEl?.open(); } public close() { this.modalEl?.close(); } }