2025-04-29 16:10:24 +02:00
|
|
|
import {GameState} from "./types";
|
|
|
|
import {asyncAlert} from "./asyncAlert";
|
|
|
|
import {t} from "./i18n/i18n";
|
|
|
|
import {levelsListHTMl, max_levels, pickedUpgradesHTMl} from "./game_utils";
|
|
|
|
import {getCreativeModeWarning, getHistory} from "./gameOver";
|
|
|
|
import {pause} from "./game";
|
|
|
|
import {allLevels, icons} from "./loadGameData";
|
|
|
|
import {firstWhere} from "./pure_functions";
|
|
|
|
import {getSettingValue, getTotalScore} from "./settings";
|
|
|
|
import {getLevelUnlockCondition, reasonLevelIsLocked, upgradeName,} from "./get_level_unlock_condition";
|
2025-04-07 14:08:48 +02:00
|
|
|
|
|
|
|
export async function openScorePanel(gameState: GameState) {
|
|
|
|
pause(true);
|
|
|
|
|
|
|
|
await asyncAlert({
|
|
|
|
title: t("score_panel.title", {
|
|
|
|
score: gameState.score,
|
|
|
|
level: gameState.currentLevel + 1,
|
|
|
|
max: max_levels(gameState),
|
|
|
|
}),
|
|
|
|
|
|
|
|
content: [
|
|
|
|
getCreativeModeWarning(gameState),
|
|
|
|
pickedUpgradesHTMl(gameState),
|
|
|
|
levelsListHTMl(gameState, gameState.currentLevel),
|
|
|
|
getNearestUnlockHTML(gameState),
|
2025-04-29 16:10:24 +02:00
|
|
|
gameState.extra_lives
|
|
|
|
? t("score_panel.extra_lives_count", { count: gameState.extra_lives })
|
2025-04-07 14:08:48 +02:00
|
|
|
: "",
|
|
|
|
],
|
|
|
|
allowClose: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getNearestUnlockHTML(gameState: GameState) {
|
2025-04-07 15:25:58 +02:00
|
|
|
if (gameState.creative) return "";
|
2025-04-08 14:03:38 +02:00
|
|
|
const unlocked = new Set(getSettingValue("breakout_71_unlocked_levels", []));
|
|
|
|
const firstUnlockable = firstWhere(allLevels, (l, li) => {
|
|
|
|
if (unlocked.has(l.name)) return;
|
2025-04-26 22:40:32 +02:00
|
|
|
const reason = reasonLevelIsLocked(li, l.name, getHistory(), false);
|
2025-04-08 14:03:38 +02:00
|
|
|
if (!reason) return;
|
2025-04-07 14:08:48 +02:00
|
|
|
|
2025-04-26 22:40:32 +02:00
|
|
|
const { minScore, forbidden, required } = getLevelUnlockCondition(
|
|
|
|
li,
|
|
|
|
l.name,
|
|
|
|
);
|
2025-04-26 20:07:01 +02:00
|
|
|
const missing = required.filter((id) => !gameState?.perks?.[id]);
|
2025-04-08 14:03:38 +02:00
|
|
|
// we can't have a forbidden perk
|
2025-04-26 20:07:01 +02:00
|
|
|
if (forbidden.find((id) => gameState?.perks?.[id])) {
|
2025-04-08 14:03:38 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// All required upgrades need to be unlocked
|
|
|
|
if (missing.find((u) => u.threshold > getTotalScore())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
l,
|
|
|
|
li,
|
|
|
|
minScore,
|
|
|
|
forbidden,
|
|
|
|
required,
|
|
|
|
missing,
|
|
|
|
reason,
|
|
|
|
};
|
|
|
|
});
|
2025-04-07 14:08:48 +02:00
|
|
|
|
|
|
|
if (!firstUnlockable) return "";
|
2025-04-11 20:34:51 +02:00
|
|
|
let missingPoints = Math.max(0, firstUnlockable.minScore - gameState.score);
|
2025-04-26 22:40:32 +02:00
|
|
|
let missingUpgrades = firstUnlockable.missing
|
|
|
|
.map((id) => upgradeName(id))
|
|
|
|
.join(", ");
|
2025-04-07 14:08:48 +02:00
|
|
|
|
|
|
|
const title =
|
|
|
|
(missingUpgrades &&
|
|
|
|
t("score_panel.get_upgrades_to_unlock", {
|
|
|
|
missingUpgrades,
|
|
|
|
points: missingPoints,
|
|
|
|
level: firstUnlockable.l.name,
|
|
|
|
})) ||
|
2025-04-08 14:03:38 +02:00
|
|
|
t("score_panel.score_to_unlock", {
|
|
|
|
points: missingPoints,
|
2025-04-07 14:08:48 +02:00
|
|
|
level: firstUnlockable.l.name,
|
|
|
|
});
|
|
|
|
|
|
|
|
return `
|
2025-04-11 08:15:58 +02:00
|
|
|
<p>${t("score_panel.close_to_unlock")}</p>
|
2025-04-07 14:08:48 +02:00
|
|
|
<div class="upgrade used">
|
|
|
|
${icons[firstUnlockable.l.name]}
|
|
|
|
<p>
|
|
|
|
<strong>${title}</strong>
|
|
|
|
${firstUnlockable.reason?.text}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
`;
|
|
|
|
}
|
2025-04-29 16:10:24 +02:00
|
|
|
|