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`