import { GameState, PerkId } from "./types"; import { catchRateBest, catchRateGood, levelTimeBest, levelTimeGood, missesBest, missesGood, wallBouncedBest, wallBouncedGood, } from "./pure_functions"; import { t } from "./i18n/i18n"; import { icons, upgrades } from "./loadGameData"; import { asyncAlert } from "./asyncAlert"; import { escapeAttribute, getPossibleUpgrades, levelsListHTMl, max_levels, upgradeLevelAndMaxDisplay, } from "./game_utils"; import { getNearestUnlockHTML } from "./openScorePanel"; export async function openUpgradesPicker(gameState: GameState) { const catchRate = gameState.levelCoughtCoins / (gameState.levelSpawnedCoins || 1); let choices = 3; let livesWon = 1; let missedOpportunities = []; const good = ""; // ''+t('level_up.missed.good')+': ' const best = ""; //''+t('level_up.missed.best')+': ' if (gameState.levelWallBounces < wallBouncedGood) { choices++; livesWon++; } else { missedOpportunities.push( good + t("level_up.missed.levelWallBounces.good", { target: wallBouncedGood, }), ); } if (gameState.levelWallBounces < wallBouncedBest) { choices++; } else { missedOpportunities.push( best + t("level_up.missed.levelWallBounces.best", { target: wallBouncedBest, }), ); } if (gameState.levelTime < levelTimeGood * 1000) { choices++; livesWon++; } else { missedOpportunities.push( good + t("level_up.missed.levelTime.good", { target: levelTimeGood, }), ); } if (gameState.levelTime < levelTimeBest * 1000) { choices++; } else { missedOpportunities.push( best + t("level_up.missed.levelTime.best", { target: levelTimeBest, }), ); } if (catchRate > catchRateGood / 100) { choices++; livesWon++; } else { missedOpportunities.push( good + t("level_up.missed.catchRate.good", { target: catchRateGood, }), ); } if (catchRate > catchRateBest / 100) { choices++; } else { missedOpportunities.push( best + t("level_up.missed.catchRate.best", { target: catchRateBest, }), ); } if (gameState.levelMisses < missesGood) { choices++; livesWon++; } else { missedOpportunities.push( good + t("level_up.missed.levelMisses.good", { target: missesGood, }), ); } if (gameState.levelMisses < missesBest) { choices++; } else { missedOpportunities.push( best + t("level_up.missed.levelMisses.best", { target: missesBest, }), ); } gameState.extra_lives += livesWon; let offered: PerkId[] = getPossibleUpgrades(gameState) .map((u) => ({ ...u, score: Math.random() + (gameState.lastOffered[u.id] || 0), })) .sort((a, b) => a.score - b.score) .filter((u) => gameState.perks[u.id] < u.max + gameState.perks.limitless) .map((u) => u.id); const fromStart = upgrades .map((u) => u.id) .filter((id) => gameState.perks[id]); while (true) { const updatedChoices = gameState.perks.one_more_choice + choices; let list = upgrades.filter( (u) => offered.slice(0, updatedChoices).includes(u.id) || gameState.perks[u.id], ); list = list .filter((u) => fromStart.includes(u.id)) .concat(list.filter((u) => !fromStart.includes(u.id))); list.forEach((u) => { dontOfferTooSoon(gameState, u.id); }); const upgradeId = await asyncAlert({ title: t("level_up.title", { level: gameState.currentLevel, max: max_levels(gameState), }), content: [ { text: t("level_up.go", { name: gameState.level.name }), icon: icons[gameState.level.name], value: null, }, gameState.extra_lives ? `

${t("level_up.instructions", { count: gameState.extra_lives, gain: livesWon, })}

` : `

${t("level_up.no_points")}

`, ...list.map((u) => { const max = u.max + gameState.perks.limitless; const lvl = gameState.perks[u.id]; const button = !gameState.extra_lives || gameState.perks[u.id] >= max ? "" : ` `; const lvlInfo = lvl ? upgradeLevelAndMaxDisplay(u, gameState) : ""; return `
${icons["icon:" + u.id]}

${u.name} ${lvlInfo} ${u.help(Math.max(1, lvl))}

${button}
`; }), ...missedOpportunities.map( (reason) => `
${icons["icon:locked"]}

${reason}

`, ), levelsListHTMl(gameState, gameState.currentLevel), getNearestUnlockHTML(gameState), `
`, ], }); if (upgradeId) { gameState.perks[upgradeId]++; gameState.runStatistics.upgrades_picked++; gameState.extra_lives--; } else { return; } } } export function dontOfferTooSoon(gameState: GameState, id: PerkId) { gameState.lastOffered[id] = Math.round(Date.now() / 1000); }