import { html, LitElement } from "lit"; import { customElement, state } from "lit/decorators.js"; import { EventBus } from "../../../core/EventBus"; import { GameType } from "../../../core/game/Game"; import { GameUpdateType } from "../../../core/game/GameUpdates"; import { GameView } from "../../../core/game/GameView"; import { UserSettings } from "../../../core/game/UserSettings"; import { AlternateViewEvent, RedrawGraphicsEvent } from "../../InputHandler"; import { PauseGameEvent } from "../../Transport"; import { translateText } from "../../Utils"; import { Layer } from "./Layer"; const button = ({ classes = "", onClick = () => {}, title = "", children = "", }) => html` `; const secondsToHms = (d: number): string => { const h = Math.floor(d / 3600); const m = Math.floor((d % 3600) / 60); const s = Math.floor((d % 3600) % 60); let time = d === 0 ? "-" : `${s}s`; if (m > 0) time = `${m}m` + time; if (h > 0) time = `${h}h` + time; return time; }; @customElement("options-menu") export class OptionsMenu extends LitElement implements Layer { public game: GameView | undefined; public eventBus: EventBus | undefined; private readonly userSettings: UserSettings = new UserSettings(); @state() private showPauseButton = true; @state() private isPaused = false; @state() private timer = 0; @state() private showSettings = false; private isVisible = false; private hasWinner = false; @state() private alternateView = false; private onTerrainButtonClick() { this.alternateView = !this.alternateView; this.eventBus?.emit(new AlternateViewEvent(this.alternateView)); this.requestUpdate(); } private onExitButtonClick() { const isAlive = this.game?.myPlayer()?.isAlive(); if (isAlive) { const isConfirmed = confirm( translateText("help_modal.exit_confirmation"), ); if (!isConfirmed) return; } // redirect to the home page window.location.href = "/"; } createRenderRoot() { return this; } private onSettingsButtonClick() { this.showSettings = !this.showSettings; this.requestUpdate(); } private onPauseButtonClick() { this.isPaused = !this.isPaused; this.eventBus?.emit(new PauseGameEvent(this.isPaused)); } private onToggleEmojisButtonClick() { this.userSettings.toggleEmojis(); this.requestUpdate(); } private onToggleAlertFrameButtonClick() { this.userSettings.toggleAlertFrame(); this.requestUpdate(); } private onToggleSpecialEffectsButtonClick() { this.userSettings.toggleFxLayer(); this.requestUpdate(); } private onToggleDarkModeButtonClick() { this.userSettings.toggleDarkMode(); this.requestUpdate(); this.eventBus?.emit(new RedrawGraphicsEvent()); } private onToggleRandomNameModeButtonClick() { this.userSettings.toggleRandomName(); } private onToggleFocusLockedButtonClick() { this.userSettings.toggleFocusLocked(); this.requestUpdate(); } private onToggleLeftClickOpensMenu() { this.userSettings.toggleLeftClickOpenMenu(); } private onToggleTerritoryPatterns() { this.userSettings.toggleTerritoryPatterns(); this.requestUpdate(); } private onTogglePerformanceOverlayButtonClick() { this.userSettings.togglePerformanceOverlay(); this.requestUpdate(); } init() { if (!this.game) throw new Error("Not initialzied"); console.log("init called from OptionsMenu"); this.showPauseButton = this.game.config().gameConfig().gameType === GameType.Singleplayer || this.game.config().isReplay(); this.isVisible = true; this.requestUpdate(); } tick() { if (!this.game) throw new Error("Not initialzied"); const updates = this.game.updatesSinceLastTick(); if (updates) { this.hasWinner = this.hasWinner || updates[GameUpdateType.Win].length > 0; } if (this.game.inSpawnPhase()) { this.timer = 0; } else if (!this.hasWinner && this.game.ticks() % 10 === 0) { this.timer++; } this.isVisible = true; this.requestUpdate(); } render() { if (!this.isVisible) { return html``; } return html`
e.preventDefault()} >
${button({ children: this.isPaused ? "▶️" : "⏸", classes: !this.showPauseButton ? "hidden" : "", onClick: this.onPauseButtonClick, title: this.isPaused ? "Resume game" : "Pause game", })}
${secondsToHms(this.timer)}
${button({ children: "❌", onClick: this.onExitButtonClick, title: "Exit game", })} ${button({ children: "⚙️", onClick: this.onSettingsButtonClick, title: "Settings", })}
${button({ children: "🌲: " + (this.alternateView ? "On" : "Off"), onClick: this.onTerrainButtonClick, title: "Toggle Terrain", })} ${button({ children: "🙂: " + (this.userSettings.emojis() ? "On" : "Off"), onClick: this.onToggleEmojisButtonClick, title: "Toggle Emojis", })} ${button({ children: "🚨: " + (this.userSettings.alertFrame() ? "On" : "Off"), onClick: this.onToggleAlertFrameButtonClick, title: "Toggle Alert frame", })} ${button({ children: "💥: " + (this.userSettings.fxLayer() ? "On" : "Off"), onClick: this.onToggleSpecialEffectsButtonClick, title: "Toggle Special effects", })} ${button({ children: "🏳️: " + (this.userSettings.territoryPatterns() ? "On" : "Off"), onClick: this.onToggleTerritoryPatterns, title: "Territory Patterns", })} ${button({ children: "🌙: " + (this.userSettings.darkMode() ? "On" : "Off"), onClick: this.onToggleDarkModeButtonClick, title: "Dark Mode", })} ${button({ children: "🥷: " + (this.userSettings.anonymousNames() ? "On" : "Off"), onClick: this.onToggleRandomNameModeButtonClick, title: "Random name mode", })} ${button({ children: "🖱️: " + (this.userSettings.leftClickOpensMenu() ? "Opens menu" : "Attack"), onClick: this.onToggleLeftClickOpensMenu, title: "Left click", })} ${button({ children: "🚀: " + (this.userSettings.performanceOverlay() ? "On" : "Off"), onClick: this.onTogglePerformanceOverlayButtonClick, title: "Performance Overlay", })}
`; } }