import { allLevels, appVersion, icons, upgrades } from "./loadGameData"; import { t } from "./i18n/i18n"; import { GameState, RunHistoryItem } from "./types"; import { gameState, pause, restart } from "./game"; import { currentLevelInfo, describeLevel, pickedUpgradesHTMl, } from "./game_utils"; import { askForPersistentStorage, getSettingValue, getTotalScore, setSettingValue, } from "./settings"; import { stopRecording } from "./recording"; import { asyncAlert } from "./asyncAlert"; import { editRawLevelList } from "./levelEditor"; import { openCreativeModePerksPicker } from "./creative"; import { isLevelLocked, reasonLevelIsLocked, } from "./get_level_unlock_condition"; import { getWorstFPSAndReset } from "./fps"; import { applySettingsChangeReco, settingsChangeRecommendations, } from "./openUpgradesPicker"; export function addToTotalPlayTime(ms: number) { setSettingValue( "breakout_71_total_play_time", getSettingValue("breakout_71_total_play_time", 0) + ms, ); } export async function gameOver(title: string, intro: string) { if (!gameState.running) return; // Ignore duplicated calls, can happen when ticking is split in multiple updates because the ball goes fast if (gameState.isGameOver) return; gameState.isGameOver = true; pause(false); askForPersistentStorage(); stopRecording(); addToTotalPlayTime(gameState.runStatistics.runTime); if (typeof gameState.startParams.isEditorTrialRun === "number") { editRawLevelList(gameState.startParams.isEditorTrialRun); restart({}); return; } if (gameState.startParams.isCreativeRun) { openCreativeModePerksPicker(); restart({}); return; } // unlocks const endTs = getTotalScore(); const startTs = endTs - gameState.score; const unlockedPerks = upgrades.filter( (o) => o.threshold > startTs && o.threshold < endTs, ); let unlocksInfo = unlockedPerks.length ? `
${u.name} ${u.help(1)}
${intro}
${t("gameOver.cumulative_total", { startTs, endTs })}
`, settingsChangeRecommendations(), { icon: icons["icon:new_run"], value: null, text: t("confirmRestart.yes"), help: "", }, ``, unlocksInfo, getHistograms(gameState), pickedUpgradesHTMl(gameState), ], }); applySettingsChangeReco(choice); restart({ levelToAvoid: currentLevelInfo(gameState).name, }); } export function getCreativeModeWarning(gameState: GameState) { if (gameState.creative) { return "" + t("gameOver.creative") + "
"; } return ""; } let runsHistory = []; try { runsHistory = JSON.parse( localStorage.getItem("breakout_71_runs_history") || "[]", ) .sort((a, b) => b.score - a.score) .slice(0, 100) as RunHistoryItem[]; } catch (e) {} export function getHistory() { return runsHistory; } export function getHistograms(gameState: GameState) { if (gameState.creative) return ""; let unlockedLevels = ""; let runStats = ""; try { const locked = allLevels .map((l, li) => ({ li, l, r: reasonLevelIsLocked(li, l.name, runsHistory, false)?.text, })) .filter((l) => l.r); gameState.runStatistics.runTime = Math.round( gameState.runStatistics.runTime, ); const perks = { ...gameState.perks }; for (let id in perks) { if (!perks[id]) { delete perks[id]; } } runsHistory.push({ ...gameState.runStatistics, perks, appVersion, }); const unlocked = locked.filter( ({ li, l }) => !isLevelLocked(li, l.name, runsHistory), ); if (unlocked.length) { unlockedLevels = `${l.name} ${describeLevel(l)}
${t("gameOver.stats_intro", { count: runsHistory.length - 1 })}
` + runStats; } } catch (e) { console.warn(e); } return unlockedLevels + runStats; }