import { html, LitElement, TemplateResult } from "lit"; import { customElement, state } from "lit/decorators.js"; import { getGamesPlayed, isInIframe, translateText, TUTORIAL_VIDEO_URL, } from "../../../client/Utils"; import { EventBus } from "../../../core/EventBus"; import { RankedType } from "../../../core/game/Game"; import { GameUpdateType } from "../../../core/game/GameUpdates"; import { GameView } from "../../../core/game/GameView"; import { getUserMe } from "../../Api"; import "../../components/CosmeticButton"; import { Controller } from "../../Controller"; import { fetchCosmetics, purchaseCosmetic, resolveCosmetics, } from "../../Cosmetics"; import { crazyGamesSDK } from "../../CrazyGamesSDK"; import { Platform } from "../../Platform"; import { SendWinnerEvent } from "../../Transport"; @customElement("win-modal") export class WinModal extends LitElement implements Controller { public game: GameView; public eventBus: EventBus; private hasShownDeathModal = false; @state() isVisible = false; @state() showButtons = false; @state() private isWin = false; @state() private isRankedGame = false; @state() private patternContent: TemplateResult | null = null; private _title: string; private rand = Math.random(); // Override to prevent shadow DOM creation createRenderRoot() { return this; } constructor() { super(); } render() { return html`

${this._title || ""}

${this.innerHtml()}
${this.isRankedGame ? html` ` : null}
`; } innerHtml() { if (isInIframe()) { return this.steamWishlist(); } if (!this.isWin && getGamesPlayed() < 3) { return this.renderYoutubeTutorial(); } if (this.rand < 0.25) { return this.steamWishlist(); } else if (this.rand < 0.5) { return this.discordDisplay(); } else { return this.renderPatternButton(); } } renderYoutubeTutorial() { return html`

${translateText("win_modal.youtube_tutorial")}

`; } renderPatternButton() { return html`

${translateText("win_modal.support_openfront")}

${translateText("win_modal.territory_pattern")}

${this.patternContent}
`; } async loadPatternContent() { const me = await getUserMe(); const cosmetics = await fetchCosmetics(); const purchasable = resolveCosmetics(cosmetics, me, null).filter( (r) => r.type === "pattern" && r.relationship === "purchasable", ); if (purchasable.length === 0) { this.patternContent = html``; return; } // Shuffle the array and take patterns based on screen size const shuffled = [...purchasable].sort(() => Math.random() - 0.5); const maxPatterns = Platform.isMobileWidth ? 1 : 3; const selected = shuffled.slice(0, Math.min(maxPatterns, shuffled.length)); this.patternContent = html`
${selected.map( (r) => html` `, )}
`; } steamWishlist(): TemplateResult { return html`

${translateText("win_modal.wishlist")}

`; } discordDisplay(): TemplateResult { return html`

${translateText("win_modal.join_discord")}

${translateText("win_modal.discord_description")}

${translateText("win_modal.join_server")}
`; } async show() { crazyGamesSDK.gameplayStop(); await this.loadPatternContent(); // Check if this is a ranked game this.isRankedGame = this.game.config().gameConfig().rankedType === RankedType.OneVOne; this.isVisible = true; this.requestUpdate(); setTimeout(() => { this.showButtons = true; this.requestUpdate(); }, 3000); } hide() { this.isVisible = false; this.showButtons = false; this.requestUpdate(); } private _handleExit() { this.hide(); window.location.href = "/"; } private _handleRequeue() { this.hide(); // Navigate to homepage and open matchmaking modal window.location.href = "/?requeue"; } init() {} tick() { const myPlayer = this.game.myPlayer(); if ( !this.hasShownDeathModal && myPlayer && !myPlayer.isAlive() && !this.game.inSpawnPhase() && myPlayer.hasSpawned() ) { this.hasShownDeathModal = true; this._title = translateText("win_modal.died"); this.show(); } const updates = this.game.updatesSinceLastTick(); const winUpdates = updates !== null ? updates[GameUpdateType.Win] : []; winUpdates.forEach((wu) => { if (wu.winner === undefined) { // ... } else if (wu.winner[0] === "team") { this.eventBus.emit(new SendWinnerEvent(wu.winner, wu.allPlayersStats)); if (wu.winner[1] === this.game.myPlayer()?.team()) { this._title = translateText("win_modal.your_team"); this.isWin = true; crazyGamesSDK.happytime(); } else { this._title = translateText("win_modal.other_team", { team: wu.winner[1], }); this.isWin = false; } history.replaceState(null, "", `${window.location.pathname}?replay`); this.show(); } else if (wu.winner[0] === "nation") { this._title = translateText("win_modal.nation_won", { nation: wu.winner[1], }); this.isWin = false; this.show(); } else { const winner = this.game.playerByClientID(wu.winner[1]); if (!winner?.isPlayer()) return; const winnerClient = winner.clientID(); if (winnerClient !== null) { this.eventBus.emit( new SendWinnerEvent(["player", winnerClient], wu.allPlayersStats), ); } if ( winnerClient !== null && winnerClient === this.game.myPlayer()?.clientID() ) { this._title = translateText("win_modal.you_won"); this.isWin = true; crazyGamesSDK.happytime(); } else { this._title = translateText("win_modal.other_won", { player: winner.displayName(), }); this.isWin = false; } history.replaceState(null, "", `${window.location.pathname}?replay`); this.show(); } }); } }