diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ea157f1..c98810a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,8 +29,8 @@ android { applicationId = "me.lecaro.breakout" minSdk = 21 targetSdk = 34 - versionCode = 29088937 - versionName = "29088937" + versionCode = 29090246 + versionName = "29090246" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true diff --git a/app/src/main/assets/index.html b/app/src/main/assets/index.html deleted file mode 100644 index 491e7db..0000000 --- a/app/src/main/assets/index.html +++ /dev/null @@ -1 +0,0 @@ -
${u.name} ${u.help(Math.max(1, gameState.perks[u.id]))} @@ -3508,7 +3516,7 @@ function isExcluded(id) { "slow_down" ]); // Avoid excluding a perk that's needed for the required one - (0, _upgrades.rawUpgrades).forEach((u)=>{ + (0, _loadGameData.upgrades).forEach((u)=>{ if (u.requires) excluded.add(u.requires); }); } @@ -3518,7 +3526,7 @@ function getLevelUnlockCondition(levelIndex) { let required = [], forbidden = [], minScore = Math.max(-1000 + 100 * levelIndex, 0); if (levelIndex > 20) { const possibletargets = [ - ...(0, _upgrades.rawUpgrades) + ...(0, _loadGameData.upgrades) ].slice(0, Math.floor(levelIndex / 2)).filter((u)=>!isExcluded(u.id)).sort((a, b)=>(0, _getLevelBackground.hashCode)(levelIndex + a.id) - (0, _getLevelBackground.hashCode)(levelIndex + b.id)); const length = Math.min(3, Math.ceil(levelIndex / 30)); required = possibletargets.slice(0, length); @@ -3574,7 +3582,7 @@ function hoursSpentPlaying() { } } -},{"./loadGameData":"l1B4x","./i18n/i18n":"eNPRm","./pure_functions":"6pQh7","./upgrades":"1u3Dx","./getLevelBackground":"7OIPf","./settings":"5blfu","./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"2n0gK":[function(require,module,exports,__globalThis) { +},{"./loadGameData":"l1B4x","./i18n/i18n":"eNPRm","./pure_functions":"6pQh7","./getLevelBackground":"7OIPf","./settings":"5blfu","./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"2n0gK":[function(require,module,exports,__globalThis) { var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); parcelHelpers.defineInteropFlag(exports); if ("serviceWorker" in navigator && window.location.href.endsWith("/index.html?isPWA=true")) { @@ -5357,7 +5365,6 @@ var _gameUtils = require("./game_utils"); var _settings = require("./settings"); var _recording = require("./recording"); var _asyncAlert = require("./asyncAlert"); -var _upgrades = require("./upgrades"); var _levelEditor = require("./levelEditor"); var _creative = require("./creative"); function addToTotalPlayTime(ms) { @@ -5384,7 +5391,7 @@ function gameOver(title, intro) { // unlocks const endTs = (0, _settings.getTotalScore)(); const startTs = endTs - (0, _game.gameState).score; - const unlockedPerks = (0, _upgrades.rawUpgrades).filter((o)=>o.threshold > startTs && o.threshold < endTs); + const unlockedPerks = (0, _loadGameData.upgrades).filter((o)=>o.threshold > startTs && o.threshold < endTs); let unlocksInfo = unlockedPerks.length ? `
${u.name}
${u.help(1)}
@@ -6557,7 +6585,6 @@ var _gameOver = require("./gameOver");
var _loadGameData = require("./loadGameData");
var _i18N = require("./i18n/i18n");
var _asyncAlert = require("./asyncAlert");
-var _upgrades = require("./upgrades");
var _settings = require("./settings");
function runHistoryViewerMenuEntry() {
const history = (0, _gameOver.getHistory)();
@@ -6583,7 +6610,7 @@ function runHistoryViewerMenuEntry() {
label: (0, _i18N.t)("history.columns.score"),
field: (r)=>r.score
},
- ...(0, _upgrades.rawUpgrades).map((u)=>({
+ ...(0, _loadGameData.upgrades).map((u)=>({
label: (0, _loadGameData.icons)["icon:" + u.id],
tooltip: u.name,
field: (r)=>r.perks?.[u.id] || 0,
@@ -6635,7 +6662,7 @@ function runHistoryViewerMenuEntry() {
};
}
-},{"./gameOver":"caCAf","./loadGameData":"l1B4x","./i18n/i18n":"eNPRm","./asyncAlert":"rSqLY","./upgrades":"1u3Dx","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3","./settings":"5blfu"}],"aHTmD":[function(require,module,exports,__globalThis) {
+},{"./gameOver":"caCAf","./loadGameData":"l1B4x","./i18n/i18n":"eNPRm","./asyncAlert":"rSqLY","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3","./settings":"5blfu"}],"aHTmD":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "openScorePanel", ()=>openScorePanel);
diff --git a/src/PWA/sw-b71.js b/src/PWA/sw-b71.js
index b9f1dc2..207ce85 100644
--- a/src/PWA/sw-b71.js
+++ b/src/PWA/sw-b71.js
@@ -1,5 +1,5 @@
// The version of the cache.
-const VERSION = "29088937";
+const VERSION = "29090246";
// The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`;
diff --git a/src/asyncAlert.ts b/src/asyncAlert.ts
index 6eb9e23..9e619b4 100644
--- a/src/asyncAlert.ts
+++ b/src/asyncAlert.ts
@@ -1,4 +1,5 @@
import { t } from "./i18n/i18n";
+import { isOptionOn } from "./options";
export let alertsOpen = 0,
closeModal: null | (() => void) = null;
@@ -118,9 +119,6 @@ ${icon}
${help || ""}
${u.name} ${u.help(Math.max(1, gameState.perks[u.id]))} @@ -310,7 +309,7 @@ function isExcluded(id: PerkId) { "slow_down", ]); // Avoid excluding a perk that's needed for the required one - rawUpgrades.forEach((u) => { + upgrades.forEach((u) => { if (u.requires) excluded.add(u.requires); }); } @@ -323,7 +322,7 @@ export function getLevelUnlockCondition(levelIndex: number) { minScore = Math.max(-1000 + 100 * levelIndex, 0); if (levelIndex > 20) { - const possibletargets = [...rawUpgrades] + const possibletargets = [...upgrades] .slice(0, Math.floor(levelIndex / 2)) .filter((u) => !isExcluded(u.id)) .sort( diff --git a/src/help.ts b/src/help.ts index cee8710..0f04c19 100644 --- a/src/help.ts +++ b/src/help.ts @@ -39,7 +39,7 @@ export function helpMenuEntry() { ...upgrades.map( (u) => `
${u.name}
${u.help(1)}
diff --git a/src/levelEditor.ts b/src/levelEditor.ts
index e4d620f..a4b64ec 100644
--- a/src/levelEditor.ts
+++ b/src/levelEditor.ts
@@ -40,7 +40,7 @@ async function openLevelEditorLevelsList() {
content: [
...customLevels.map((l, li) => ({
text: l.name,
- icon: levelIconHTML(l.bricks, l.size, l.color),
+ icon: levelIconHTML(l.bricks, l.size),
value() {
editRawLevelList(li);
},
diff --git a/src/levelIcon.ts b/src/levelIcon.ts
index b52d3d3..d5c236e 100644
--- a/src/levelIcon.ts
+++ b/src/levelIcon.ts
@@ -10,7 +10,6 @@ const levelIconHTMLCanvasCtx =
export function levelIconHTML(
bricks: string[],
levelSize: number,
- color: string,
) {
const size = 46;
const c = levelIconHTMLCanvas;
diff --git a/src/level_editor/levels_editor.tsx b/src/level_editor/levels_editor.tsx
index 10cd64b..5c96edd 100644
--- a/src/level_editor/levels_editor.tsx
+++ b/src/level_editor/levels_editor.tsx
@@ -2,14 +2,13 @@ import { Level, Palette, RawLevel } from "../types";
import _backgrounds from "../data/backgrounds.json";
import _palette from "../data/palette.json";
import { createRoot } from "react-dom/client";
-import { useEffect, useState } from "react";
+import { useEffect, useState } from "react";
import { moveLevel, resizeLevel, setBrick } from "./levels_editor_util";
import {
automaticBackgroundColor,
levelCodeToRawLevel,
} from "../pure_functions";
-
const palette = _palette as Palette;
let allLevels = null;
@@ -22,13 +21,22 @@ function App() {
fetch("http://localhost:4400/src/data/levels.json")
.then((r) => r.json())
.then((lvls) => {
-
- const cleaned = lvls.map(l=>({name:l.name, size:l.size, bricks:(l.bricks+'_'.repeat(l.size*l.size)).slice(0,l.size*l.size), credit:l.credit||''}))
- const sorted = [
- ...cleaned.filter(l=>l.name.match('icon:')).sort((a,b)=>a.name>b.name ? 1:-1),
- ...cleaned.filter(l=>!l.name.match('icon:'))
- ]
- setLevels(sorted as RawLevel[])
+ const cleaned = lvls.map((l) => ({
+ name: l.name,
+ size: l.size,
+ bricks: (l.bricks + "_".repeat(l.size * l.size)).slice(
+ 0,
+ l.size * l.size,
+ ),
+ credit: l.credit || "",
+ }));
+ const sorted = [
+ ...cleaned
+ .filter((l) => l.name.match("icon:"))
+ .sort((a, b) => (a.name > b.name ? 1 : -1)),
+ ...cleaned.filter((l) => !l.name.match("icon:")),
+ ];
+ setLevels(sorted as RawLevel[]);
allLevels = sorted;
});
}, []);
diff --git a/src/loadGameData.test.ts b/src/loadGameData.test.ts
index ba3887f..1559671 100644
--- a/src/loadGameData.test.ts
+++ b/src/loadGameData.test.ts
@@ -30,18 +30,6 @@ describe("json data checks", () => {
it("Has a few colors", () => {
expect(Object.keys(_palette).length).toBeGreaterThan(10);
});
- it("Avoids dark bricks on dark bg", () => {
- const levelsWithDarkBricksAndBG = _rawLevelsList
- .filter((l) => !l.color && !l.name.match(/^icon:/))
- .map((l) => ({
- name: l.name,
- bricks: l.bricks.split("").filter((c) => c !== "_").length,
- darkBricks: l.bricks.split("").filter((c) => c === "g").length,
- }))
- .filter((l) => l.darkBricks > 0.05 * l.bricks);
-
- expect(levelsWithDarkBricksAndBG).toEqual([]);
- });
it("Has an _appVersion", () => {
expect(parseInt(_appVersion)).toBeGreaterThan(2000);
});
diff --git a/src/loadGameData.ts b/src/loadGameData.ts
index b00b11e..d770702 100644
--- a/src/loadGameData.ts
+++ b/src/loadGameData.ts
@@ -8,6 +8,7 @@ import { levelIconHTML } from "./levelIcon";
import { automaticBackgroundColor } from "./pure_functions";
+export const upgrades = [...rawUpgrades].sort((a, b) => a.category - b.category || a.threshold - b.threshold) as Upgrade[];
const palette = _palette as Palette;
const rawLevelsList = _rawLevelsList as RawLevel[];
@@ -22,7 +23,7 @@ export function transformRawLevel(level: RawLevel) {
.map((c) => palette[c])
.slice(0, level.size * level.size);
const bricksCount = bricks.filter((i) => i).length;
- const icon = levelIconHTML(bricks, level.size, level.color);
+ const icon = levelIconHTML(bricks, level.size);
icons[level.name] = icon;
return {
...level,
@@ -43,7 +44,3 @@ export const allLevels = allLevelsAndIcons.filter(
(l) => !l.name.startsWith("icon:"),
);
-export const upgrades = rawUpgrades.map((u) => ({
- ...u,
- icon: icons["icon:" + u.id],
-})) as Upgrade[];
diff --git a/src/runHistoryViewer.ts b/src/runHistoryViewer.ts
index d6546e7..f50857c 100644
--- a/src/runHistoryViewer.ts
+++ b/src/runHistoryViewer.ts
@@ -1,8 +1,7 @@
import { getHistory } from "./gameOver";
-import { appVersion, icons } from "./loadGameData";
+import {appVersion, icons, upgrades} from "./loadGameData";
import { t } from "./i18n/i18n";
import { asyncAlert } from "./asyncAlert";
-import { rawUpgrades } from "./upgrades";
import { getSettingValue, setSettingValue } from "./settings";
export function runHistoryViewerMenuEntry() {
@@ -31,7 +30,7 @@ export function runHistoryViewerMenuEntry() {
label: t("history.columns.score"),
field: (r) => r.score,
},
- ...rawUpgrades.map((u) => ({
+ ...upgrades.map((u) => ({
label: icons["icon:" + u.id],
tooltip: u.name,
field: (r) => r.perks?.[u.id] || 0,
diff --git a/src/startingPerks.ts b/src/startingPerks.ts
index 5d54aa9..3555c3d 100644
--- a/src/startingPerks.ts
+++ b/src/startingPerks.ts
@@ -31,7 +31,7 @@ export async function openStartingPerksEditor() {
const buttons = avaliable.map((u) => {
const checked = isStartingPerk(u);
return {
- icon: u.icon,
+ icon: icons['icon:'+u.id],
text: u.name,
tooltip: u.help(1),
value: [u],
diff --git a/src/types.d.ts b/src/types.d.ts
index 3e41bf2..8eb009d 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -7,7 +7,6 @@ export type RawLevel = {
name: string;
size: number;
bricks: string;
- color: string;
credit?: string;
};
export type Level = {
@@ -28,8 +27,7 @@ export type Upgrade = {
gift: boolean;
id: PerkId;
name: string;
- category: string;
- icon: string;
+ category: number;
max: number;
help: (lvl: number) => string;
fullHelp: string;
diff --git a/src/upgrades.ts b/src/upgrades.ts
index 430546a..b7453ed 100644
--- a/src/upgrades.ts
+++ b/src/upgrades.ts
@@ -1,7 +1,7 @@
import { t } from "./i18n/i18n";
import { comboKeepingRate } from "./pure_functions";
-import { PerkId } from "./types";
+import {PerkId, Upgrade} from "./types";
// Those perks are excluded from creative mode
export const noCreative: PerkId[] = [
@@ -10,877 +10,882 @@ export const noCreative: PerkId[] = [
"one_more_choice",
];
-export const categories={
- beginner:1,
- combo:2,
- combo_boost:2.5,
- simple:3,
- advanced:4,
-}
+export const categories = {
+ beginner: 1,
+ combo: 2,
+ combo_boost: 2.5,
+ simple: 3,
+ advanced: 4,
+};
-export const rawUpgrades = [
- {
- category: categories.beginner,
- requires: "",
- threshold: 0,
- gift: false,
- id: "slow_down",
- max: 2,
- name: t("upgrades.slow_down.name"),
- help: (lvl: number) => t("upgrades.slow_down.tooltip", { lvl }),
- fullHelp: t("upgrades.slow_down.verbose_description"),
- },
- {
- category: categories.beginner,
- requires: "",
- threshold: 0,
- gift: false,
- id: "extra_life",
- max: 7,
- name: t("upgrades.extra_life.name"),
- help: (lvl: number) =>
- lvl === 1
- ? t("upgrades.extra_life.tooltip")
- : t("upgrades.extra_life.help_plural", { lvl }),
- fullHelp: t("upgrades.extra_life.verbose_description"),
- },
- {
- category: categories.beginner,
- requires: "",
- threshold: 60000,
- gift: false,
- id: "concave_puck",
- max: 1,
- name: t("upgrades.concave_puck.name"),
- help: (lvl: number) => t("upgrades.concave_puck.tooltip"),
- fullHelp: t("upgrades.concave_puck.verbose_description"),
- },
- {
- category: categories.beginner,
- requires: "",
- threshold: 500,
- id: "telekinesis",
- gift: true,
- max: 1,
- name: t("upgrades.telekinesis.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.telekinesis.tooltip")
- : t("upgrades.telekinesis.help_plural"),
- fullHelp: t("upgrades.telekinesis.verbose_description"),
- },
- {
- category: categories.beginner,
- requires: "",
- threshold: 85000,
- gift: false,
- id: "yoyo",
- max: 1,
- name: t("upgrades.yoyo.name"),
- help: (lvl: number) => t("upgrades.yoyo.tooltip"),
- fullHelp: t("upgrades.yoyo.verbose_description"),
- },
- {
- category: categories.beginner,
- requires: "",
- threshold: 0,
- gift: false,
- id: "bigger_puck",
- max: 2,
- name: t("upgrades.bigger_puck.name"),
- help: () => t("upgrades.bigger_puck.tooltip"),
- fullHelp: t("upgrades.bigger_puck.verbose_description"),
- },
+export const rawUpgrades = [
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 0,
+ gift: false,
+ id: "slow_down",
+ max: 2,
+ name: t("upgrades.slow_down.name"),
+ help: (lvl: number) => t("upgrades.slow_down.tooltip", { lvl }),
+ fullHelp: t("upgrades.slow_down.verbose_description"),
+ },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 0,
+ gift: false,
+ id: "extra_life",
+ max: 7,
+ name: t("upgrades.extra_life.name"),
+ help: (lvl: number) =>
+ lvl === 1
+ ? t("upgrades.extra_life.tooltip")
+ : t("upgrades.extra_life.help_plural", { lvl }),
+ fullHelp: t("upgrades.extra_life.verbose_description"),
+ },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 60000,
+ gift: false,
+ id: "concave_puck",
+ max: 1,
+ name: t("upgrades.concave_puck.name"),
+ help: (lvl: number) => t("upgrades.concave_puck.tooltip"),
+ fullHelp: t("upgrades.concave_puck.verbose_description"),
+ },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 500,
+ id: "telekinesis",
+ gift: true,
+ max: 1,
+ name: t("upgrades.telekinesis.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.telekinesis.tooltip")
+ : t("upgrades.telekinesis.help_plural"),
+ fullHelp: t("upgrades.telekinesis.verbose_description"),
+ },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 85000,
+ gift: false,
+ id: "yoyo",
+ max: 1,
+ name: t("upgrades.yoyo.name"),
+ help: (lvl: number) => t("upgrades.yoyo.tooltip"),
+ fullHelp: t("upgrades.yoyo.verbose_description"),
+ },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 0,
+ gift: false,
+ id: "bigger_puck",
+ max: 2,
+ name: t("upgrades.bigger_puck.name"),
+ help: () => t("upgrades.bigger_puck.tooltip"),
+ fullHelp: t("upgrades.bigger_puck.verbose_description"),
+ },
- {
- category: categories.beginner,
- requires: "",
- threshold: 50000,
- gift: false,
- id: "one_more_choice",
- max: 3,
- name: t("upgrades.one_more_choice.name"),
- help: (lvl: number) => t("upgrades.one_more_choice.tooltip", { lvl }),
- fullHelp: t("upgrades.one_more_choice.verbose_description"),
- },
- {
- category: categories.beginner,
- requires: "",
- threshold: 50,
- gift: false,
- id: "skip_last",
- max: 7,
- name: t("upgrades.skip_last.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.skip_last.tooltip")
- : t("upgrades.skip_last.help_plural", { lvl }),
- fullHelp: t("upgrades.skip_last.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 100,
- id: "streak_shots",
- gift: true,
- max: 1,
- name: t("upgrades.streak_shots.name"),
- help: (lvl: number) => t("upgrades.streak_shots.tooltip", { lvl }),
- fullHelp: t("upgrades.streak_shots.verbose_description"),
- },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 50000,
+ gift: false,
+ id: "one_more_choice",
+ max: 3,
+ name: t("upgrades.one_more_choice.name"),
+ help: (lvl: number) => t("upgrades.one_more_choice.tooltip", { lvl }),
+ fullHelp: t("upgrades.one_more_choice.verbose_description"),
+ },
+ {
+ category: categories.beginner,
+ requires: "",
+ threshold: 50,
+ gift: false,
+ id: "skip_last",
+ max: 7,
+ name: t("upgrades.skip_last.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.skip_last.tooltip")
+ : t("upgrades.skip_last.help_plural", { lvl }),
+ fullHelp: t("upgrades.skip_last.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 100,
+ id: "streak_shots",
+ gift: true,
+ max: 1,
+ name: t("upgrades.streak_shots.name"),
+ help: (lvl: number) => t("upgrades.streak_shots.tooltip", { lvl }),
+ fullHelp: t("upgrades.streak_shots.verbose_description"),
+ },
- {
- category: categories.combo,
- requires: "",
- threshold: 200,
- id: "left_is_lava",
- gift: true,
- max: 1,
- name: t("upgrades.left_is_lava.name"),
- help: (lvl: number) => t("upgrades.left_is_lava.tooltip", { lvl }),
- fullHelp: t("upgrades.left_is_lava.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 300,
- id: "right_is_lava",
- gift: true,
- max: 1,
- name: t("upgrades.right_is_lava.name"),
- help: (lvl: number) => t("upgrades.right_is_lava.tooltip", { lvl }),
- fullHelp: t("upgrades.right_is_lava.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 400,
- id: "top_is_lava",
- gift: true,
- max: 1,
- name: t("upgrades.top_is_lava.name"),
- help: (lvl: number) => t("upgrades.top_is_lava.tooltip", { lvl }),
- fullHelp: t("upgrades.top_is_lava.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 4000,
- id: "hot_start",
- gift: true,
- max: 3,
- name: t("upgrades.hot_start.name"),
- help: (lvl: number) =>
- t("upgrades.hot_start.tooltip", {
- start: lvl * 30 + 1,
- loss: lvl,
- }),
- fullHelp: t("upgrades.hot_start.verbose_description"),
- },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 200,
+ id: "left_is_lava",
+ gift: true,
+ max: 1,
+ name: t("upgrades.left_is_lava.name"),
+ help: (lvl: number) => t("upgrades.left_is_lava.tooltip", { lvl }),
+ fullHelp: t("upgrades.left_is_lava.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 300,
+ id: "right_is_lava",
+ gift: true,
+ max: 1,
+ name: t("upgrades.right_is_lava.name"),
+ help: (lvl: number) => t("upgrades.right_is_lava.tooltip", { lvl }),
+ fullHelp: t("upgrades.right_is_lava.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 400,
+ id: "top_is_lava",
+ gift: true,
+ max: 1,
+ name: t("upgrades.top_is_lava.name"),
+ help: (lvl: number) => t("upgrades.top_is_lava.tooltip", { lvl }),
+ fullHelp: t("upgrades.top_is_lava.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 4000,
+ id: "hot_start",
+ gift: true,
+ max: 3,
+ name: t("upgrades.hot_start.name"),
+ help: (lvl: number) =>
+ t("upgrades.hot_start.tooltip", {
+ start: lvl * 30 + 1,
+ loss: lvl,
+ }),
+ fullHelp: t("upgrades.hot_start.verbose_description"),
+ },
- {
- category: categories.combo,
- requires: "",
- threshold: 2000,
- id: "picky_eater",
- gift: true,
- max: 1,
- name: t("upgrades.picky_eater.name"),
- help: (lvl: number) => t("upgrades.picky_eater.tooltip", { lvl }),
- fullHelp: t("upgrades.picky_eater.verbose_description"),
- },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 2000,
+ id: "picky_eater",
+ gift: true,
+ max: 1,
+ name: t("upgrades.picky_eater.name"),
+ help: (lvl: number) => t("upgrades.picky_eater.tooltip", { lvl }),
+ fullHelp: t("upgrades.picky_eater.verbose_description"),
+ },
- {
- category: categories.combo,
- requires: "",
- threshold: 3000,
- id: "compound_interest",
- gift: true,
- max: 1,
- name: t("upgrades.compound_interest.name"),
- help: (lvl: number) => t("upgrades.compound_interest.tooltip", { lvl }),
- fullHelp: t("upgrades.compound_interest.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 150000,
- gift: true,
- id: "side_kick",
- max: 3,
- name: t("upgrades.side_kick.name"),
- help: (lvl: number) =>
- t("upgrades.side_kick.tooltip", { lvl, loss: lvl * 2 }),
- fullHelp: t("upgrades.side_kick.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 150000,
- gift: true,
- id: "side_flip",
- max: 3,
- name: t("upgrades.side_flip.name"),
- help: (lvl: number) =>
- t("upgrades.side_flip.tooltip", { lvl, loss: lvl * 2 }),
- fullHelp: t("upgrades.side_flip.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 135000,
- // a bit too hard when starting up
- gift: false,
- id: "reach",
- max: 1,
- name: t("upgrades.reach.name"),
- help: (lvl: number) => t("upgrades.reach.tooltip", { lvl }),
- fullHelp: t("upgrades.reach.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "multiball",
- threshold: 245000,
- gift: false,
- id: "happy_family",
- max: 1,
- name: t("upgrades.happy_family.name"),
- help: () => t("upgrades.happy_family.tooltip"),
- fullHelp: t("upgrades.happy_family.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 165000,
- gift: false,
- id: "addiction",
- max: 7,
- name: t("upgrades.addiction.name"),
- help: (lvl: number) =>
- t("upgrades.addiction.tooltip", { lvl, delay: (5 / lvl).toFixed(2) }),
- fullHelp: t("upgrades.addiction.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 90000,
- gift: true,
- id: "nbricks",
- max: 3,
- name: t("upgrades.nbricks.name"),
- help: (lvl: number) => t("upgrades.nbricks.tooltip", { lvl }),
- fullHelp: t("upgrades.nbricks.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 230000,
- gift: false,
- id: "three_cushion",
- max: 1,
- name: t("upgrades.three_cushion.name"),
- help: (lvl: number) =>
- t("upgrades.three_cushion.tooltip", { max: lvl * 3 }),
- fullHelp: t("upgrades.three_cushion.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 115000,
- gift: true,
- id: "trampoline",
- max: 1,
- name: t("upgrades.trampoline.name"),
- help: (lvl: number) => t("upgrades.trampoline.tooltip", { lvl }),
- fullHelp: t("upgrades.trampoline.verbose_description"),
- },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 3000,
+ id: "compound_interest",
+ gift: true,
+ max: 1,
+ name: t("upgrades.compound_interest.name"),
+ help: (lvl: number) => t("upgrades.compound_interest.tooltip", { lvl }),
+ fullHelp: t("upgrades.compound_interest.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 150000,
+ gift: true,
+ id: "side_kick",
+ max: 3,
+ name: t("upgrades.side_kick.name"),
+ help: (lvl: number) =>
+ t("upgrades.side_kick.tooltip", { lvl, loss: lvl * 2 }),
+ fullHelp: t("upgrades.side_kick.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 150000,
+ gift: true,
+ id: "side_flip",
+ max: 3,
+ name: t("upgrades.side_flip.name"),
+ help: (lvl: number) =>
+ t("upgrades.side_flip.tooltip", { lvl, loss: lvl * 2 }),
+ fullHelp: t("upgrades.side_flip.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 135000,
+ // a bit too hard when starting up
+ gift: false,
+ id: "reach",
+ max: 1,
+ name: t("upgrades.reach.name"),
+ help: (lvl: number) => t("upgrades.reach.tooltip", { lvl }),
+ fullHelp: t("upgrades.reach.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "multiball",
+ threshold: 245000,
+ gift: false,
+ id: "happy_family",
+ max: 1,
+ name: t("upgrades.happy_family.name"),
+ help: () => t("upgrades.happy_family.tooltip"),
+ fullHelp: t("upgrades.happy_family.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 165000,
+ gift: false,
+ id: "addiction",
+ max: 7,
+ name: t("upgrades.addiction.name"),
+ help: (lvl: number) =>
+ t("upgrades.addiction.tooltip", { lvl, delay: (5 / lvl).toFixed(2) }),
+ fullHelp: t("upgrades.addiction.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 90000,
+ gift: true,
+ id: "nbricks",
+ max: 3,
+ name: t("upgrades.nbricks.name"),
+ help: (lvl: number) => t("upgrades.nbricks.tooltip", { lvl }),
+ fullHelp: t("upgrades.nbricks.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 230000,
+ gift: false,
+ id: "three_cushion",
+ max: 1,
+ name: t("upgrades.three_cushion.name"),
+ help: (lvl: number) =>
+ t("upgrades.three_cushion.tooltip", { max: lvl * 3 }),
+ fullHelp: t("upgrades.three_cushion.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 115000,
+ gift: true,
+ id: "trampoline",
+ max: 1,
+ name: t("upgrades.trampoline.name"),
+ help: (lvl: number) => t("upgrades.trampoline.tooltip", { lvl }),
+ fullHelp: t("upgrades.trampoline.verbose_description"),
+ },
- {
- category: categories.combo,
- requires: "",
- threshold: 105000,
- gift: true,
- id: "zen",
- max: 1,
- name: t("upgrades.zen.name"),
- help: (lvl: number) => t("upgrades.zen.tooltip", { lvl }),
- fullHelp: t("upgrades.zen.verbose_description"),
- },
- {
- category: categories.combo,
- requires: "",
- threshold: 70000,
- gift: true,
- id: "asceticism",
- max: 1,
- name: t("upgrades.asceticism.name"),
- help: (lvl: number) => t("upgrades.asceticism.tooltip", { combo: lvl * 3 }),
- fullHelp: t("upgrades.asceticism.verbose_description"),
- },
- // Regular
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 105000,
+ gift: true,
+ id: "zen",
+ max: 1,
+ name: t("upgrades.zen.name"),
+ help: (lvl: number) => t("upgrades.zen.tooltip", { lvl }),
+ fullHelp: t("upgrades.zen.verbose_description"),
+ },
+ {
+ category: categories.combo,
+ requires: "",
+ threshold: 70000,
+ gift: true,
+ id: "asceticism",
+ max: 1,
+ name: t("upgrades.asceticism.name"),
+ help: (lvl: number) =>
+ t("upgrades.asceticism.tooltip", { combo: lvl * 3 }),
+ fullHelp: t("upgrades.asceticism.verbose_description"),
+ },
+ // Regular
- {
- category: categories.simple,
- requires: "",
- threshold: 15000,
- gift: false,
- id: "pierce_color",
- max: 4,
- name: t("upgrades.pierce_color.name"),
- help: (lvl: number) => t("upgrades.pierce_color.tooltip", { lvl }),
- fullHelp: t("upgrades.pierce_color.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 1500,
- id: "pierce",
- gift: false,
- max: 3,
- name: t("upgrades.pierce.name"),
- help: (lvl: number) => t("upgrades.pierce.tooltip", { count: 3 * lvl }),
- fullHelp: t("upgrades.pierce.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 800,
- id: "multiball",
- gift: true,
- max: 6,
- name: t("upgrades.multiball.name"),
- help: (lvl: number) => t("upgrades.multiball.tooltip", { count: lvl + 1 }),
- fullHelp: t("upgrades.multiball.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "multiball",
- threshold: 21000,
- gift: false,
- id: "ball_repulse_ball",
- max: 3,
- name: t("upgrades.ball_repulse_ball.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.ball_repulse_ball.tooltip")
- : t("upgrades.ball_repulse_ball.help_plural"),
- fullHelp: t("upgrades.ball_repulse_ball.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "multiball",
- threshold: 25000,
- gift: false,
- id: "ball_attract_ball",
- max: 3,
- name: t("upgrades.ball_attract_ball.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.ball_attract_ball.tooltip")
- : t("upgrades.ball_attract_ball.help_plural"),
- fullHelp: t("upgrades.ball_attract_ball.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 30000,
- gift: false,
- id: "puck_repulse_ball",
- max: 2,
- name: t("upgrades.puck_repulse_ball.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.puck_repulse_ball.tooltip")
- : t("upgrades.puck_repulse_ball.help_plural"),
- fullHelp: t("upgrades.puck_repulse_ball.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 35000,
- gift: false,
- id: "wind",
- max: 3,
- name: t("upgrades.wind.name"),
- help: (lvl: number) =>
- lvl == 1 ? t("upgrades.wind.tooltip") : t("upgrades.wind.help_plural"),
- fullHelp: t("upgrades.wind.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 65000,
- gift: false,
- id: "helium",
- max: 3,
- name: t("upgrades.helium.name"),
- help: (lvl: number) => t("upgrades.helium.tooltip"),
- fullHelp: t("upgrades.helium.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 200000,
- gift: false,
- id: "bricks_attract_coins",
- max: 3,
- name: t("upgrades.bricks_attract_coins.name"),
- help: (lvl: number) => t("upgrades.bricks_attract_coins.tooltip", { lvl }),
- fullHelp: t("upgrades.bricks_attract_coins.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 240000,
- gift: false,
- id: "wrap_left",
- max: 1,
- name: t("upgrades.wrap_left.name"),
- help: () => t("upgrades.wrap_left.tooltip"),
- fullHelp: t("upgrades.wrap_left.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 245000,
- gift: false,
- id: "wrap_right",
- max: 1,
- name: t("upgrades.wrap_right.name"),
- help: () => t("upgrades.wrap_right.tooltip"),
- fullHelp: t("upgrades.wrap_right.verbose_description"),
- },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 15000,
+ gift: false,
+ id: "pierce_color",
+ max: 4,
+ name: t("upgrades.pierce_color.name"),
+ help: (lvl: number) => t("upgrades.pierce_color.tooltip", { lvl }),
+ fullHelp: t("upgrades.pierce_color.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 1500,
+ id: "pierce",
+ gift: false,
+ max: 3,
+ name: t("upgrades.pierce.name"),
+ help: (lvl: number) => t("upgrades.pierce.tooltip", { count: 3 * lvl }),
+ fullHelp: t("upgrades.pierce.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 800,
+ id: "multiball",
+ gift: true,
+ max: 6,
+ name: t("upgrades.multiball.name"),
+ help: (lvl: number) =>
+ t("upgrades.multiball.tooltip", { count: lvl + 1 }),
+ fullHelp: t("upgrades.multiball.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "multiball",
+ threshold: 21000,
+ gift: false,
+ id: "ball_repulse_ball",
+ max: 3,
+ name: t("upgrades.ball_repulse_ball.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.ball_repulse_ball.tooltip")
+ : t("upgrades.ball_repulse_ball.help_plural"),
+ fullHelp: t("upgrades.ball_repulse_ball.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "multiball",
+ threshold: 25000,
+ gift: false,
+ id: "ball_attract_ball",
+ max: 3,
+ name: t("upgrades.ball_attract_ball.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.ball_attract_ball.tooltip")
+ : t("upgrades.ball_attract_ball.help_plural"),
+ fullHelp: t("upgrades.ball_attract_ball.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 30000,
+ gift: false,
+ id: "puck_repulse_ball",
+ max: 2,
+ name: t("upgrades.puck_repulse_ball.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.puck_repulse_ball.tooltip")
+ : t("upgrades.puck_repulse_ball.help_plural"),
+ fullHelp: t("upgrades.puck_repulse_ball.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 35000,
+ gift: false,
+ id: "wind",
+ max: 3,
+ name: t("upgrades.wind.name"),
+ help: (lvl: number) =>
+ lvl == 1 ? t("upgrades.wind.tooltip") : t("upgrades.wind.help_plural"),
+ fullHelp: t("upgrades.wind.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 65000,
+ gift: false,
+ id: "helium",
+ max: 3,
+ name: t("upgrades.helium.name"),
+ help: (lvl: number) => t("upgrades.helium.tooltip"),
+ fullHelp: t("upgrades.helium.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 200000,
+ gift: false,
+ id: "bricks_attract_coins",
+ max: 3,
+ name: t("upgrades.bricks_attract_coins.name"),
+ help: (lvl: number) =>
+ t("upgrades.bricks_attract_coins.tooltip", { lvl }),
+ fullHelp: t("upgrades.bricks_attract_coins.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 240000,
+ gift: false,
+ id: "wrap_left",
+ max: 1,
+ name: t("upgrades.wrap_left.name"),
+ help: () => t("upgrades.wrap_left.tooltip"),
+ fullHelp: t("upgrades.wrap_left.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 245000,
+ gift: false,
+ id: "wrap_right",
+ max: 1,
+ name: t("upgrades.wrap_right.name"),
+ help: () => t("upgrades.wrap_right.tooltip"),
+ fullHelp: t("upgrades.wrap_right.verbose_description"),
+ },
- {
- category: categories.simple,
- requires: "",
- threshold: 45000,
- gift: false,
- id: "respawn",
- max: 4,
- name: t("upgrades.respawn.name"),
- help: (lvl: number) =>
- t("upgrades.respawn.tooltip", {
- percent: Math.floor(100 * comboKeepingRate(lvl)),
- delay: (3 / lvl).toFixed(2),
- }),
- fullHelp: t("upgrades.respawn.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 55000,
- gift: false,
- id: "double_or_nothing",
- max: 3,
- name: t("upgrades.double_or_nothing.name"),
- help: (lvl: number) =>
- t("upgrades.double_or_nothing.tooltip", {
- percent: lvl * 10,
- multiplier: 1 + lvl,
- }),
- fullHelp: t("upgrades.double_or_nothing.verbose_description"),
- },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 45000,
+ gift: false,
+ id: "respawn",
+ max: 4,
+ name: t("upgrades.respawn.name"),
+ help: (lvl: number) =>
+ t("upgrades.respawn.tooltip", {
+ percent: Math.floor(100 * comboKeepingRate(lvl)),
+ delay: (3 / lvl).toFixed(2),
+ }),
+ fullHelp: t("upgrades.respawn.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 55000,
+ gift: false,
+ id: "double_or_nothing",
+ max: 3,
+ name: t("upgrades.double_or_nothing.name"),
+ help: (lvl: number) =>
+ t("upgrades.double_or_nothing.tooltip", {
+ percent: lvl * 10,
+ multiplier: 1 + lvl,
+ }),
+ fullHelp: t("upgrades.double_or_nothing.verbose_description"),
+ },
- {
- category: categories.advanced,
- requires: "",
- threshold: 75000,
- gift: false,
- id: "unbounded",
- max: 3,
- name: t("upgrades.unbounded.name"),
- help: (lvl: number) => t("upgrades.unbounded.tooltip", { lvl }),
- fullHelp: t("upgrades.unbounded.verbose_description"),
- },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 75000,
+ gift: false,
+ id: "unbounded",
+ max: 3,
+ name: t("upgrades.unbounded.name"),
+ help: (lvl: number) => t("upgrades.unbounded.tooltip", { lvl }),
+ fullHelp: t("upgrades.unbounded.verbose_description"),
+ },
- {
- category: categories.advanced,
- requires: "",
- threshold: 95000,
- gift: false,
- id: "etherealcoins",
- max: 1,
- name: t("upgrades.etherealcoins.name"),
- help: (lvl: number) => t("upgrades.etherealcoins.tooltip"),
- fullHelp: t("upgrades.etherealcoins.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "multiball",
- threshold: 100000,
- gift: false,
- id: "shocks",
- max: 1,
- name: t("upgrades.shocks.name"),
- help: (lvl: number) => t("upgrades.shocks.tooltip"),
- fullHelp: t("upgrades.shocks.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "extra_life",
- threshold: 110000,
- gift: false,
- id: "sacrifice",
- max: 1,
- name: t("upgrades.sacrifice.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.sacrifice.help_l1")
- : t("upgrades.sacrifice.help_over", { lvl }),
- fullHelp: t("upgrades.sacrifice.verbose_description"),
- },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 95000,
+ gift: false,
+ id: "etherealcoins",
+ max: 1,
+ name: t("upgrades.etherealcoins.name"),
+ help: (lvl: number) => t("upgrades.etherealcoins.tooltip"),
+ fullHelp: t("upgrades.etherealcoins.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "multiball",
+ threshold: 100000,
+ gift: false,
+ id: "shocks",
+ max: 1,
+ name: t("upgrades.shocks.name"),
+ help: (lvl: number) => t("upgrades.shocks.tooltip"),
+ fullHelp: t("upgrades.shocks.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "extra_life",
+ threshold: 110000,
+ gift: false,
+ id: "sacrifice",
+ max: 1,
+ name: t("upgrades.sacrifice.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.sacrifice.help_l1")
+ : t("upgrades.sacrifice.help_over", { lvl }),
+ fullHelp: t("upgrades.sacrifice.verbose_description"),
+ },
- {
- category: categories.advanced,
- requires: "",
- threshold: 120000,
- gift: false,
- id: "ghost_coins",
- max: 3,
- name: t("upgrades.ghost_coins.name"),
- help: (lvl: number) => t("upgrades.ghost_coins.tooltip", { lvl }),
- fullHelp: t("upgrades.ghost_coins.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 125000,
- gift: false,
- id: "forgiving",
- max: 1,
- name: t("upgrades.forgiving.name"),
- help: (lvl: number) => t("upgrades.forgiving.tooltip"),
- fullHelp: t("upgrades.forgiving.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 130000,
- gift: false,
- id: "ball_attracts_coins",
- max: 3,
- name: t("upgrades.ball_attracts_coins.name"),
- help: (lvl: number) => t("upgrades.ball_attracts_coins.tooltip"),
- fullHelp: t("upgrades.ball_attracts_coins.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 145000,
- gift: false,
- id: "clairvoyant",
- max: 1,
- name: t("upgrades.clairvoyant.name"),
- help: (lvl: number) => t("upgrades.clairvoyant.tooltip"),
- fullHelp: t("upgrades.clairvoyant.verbose_description"),
- },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 120000,
+ gift: false,
+ id: "ghost_coins",
+ max: 3,
+ name: t("upgrades.ghost_coins.name"),
+ help: (lvl: number) => t("upgrades.ghost_coins.tooltip", { lvl }),
+ fullHelp: t("upgrades.ghost_coins.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 125000,
+ gift: false,
+ id: "forgiving",
+ max: 1,
+ name: t("upgrades.forgiving.name"),
+ help: (lvl: number) => t("upgrades.forgiving.tooltip"),
+ fullHelp: t("upgrades.forgiving.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 130000,
+ gift: false,
+ id: "ball_attracts_coins",
+ max: 3,
+ name: t("upgrades.ball_attracts_coins.name"),
+ help: (lvl: number) => t("upgrades.ball_attracts_coins.tooltip"),
+ fullHelp: t("upgrades.ball_attracts_coins.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 145000,
+ gift: false,
+ id: "clairvoyant",
+ max: 1,
+ name: t("upgrades.clairvoyant.name"),
+ help: (lvl: number) => t("upgrades.clairvoyant.tooltip"),
+ fullHelp: t("upgrades.clairvoyant.verbose_description"),
+ },
- {
- category: categories.advanced,
- requires: "",
- threshold: 155000,
- gift: false,
- id: "implosions",
- max: 1,
- name: t("upgrades.implosions.name"),
- help: (lvl: number) => t("upgrades.implosions.tooltip"),
- fullHelp: t("upgrades.implosions.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 160000,
- gift: false,
- id: "corner_shot",
- max: 1,
- name: t("upgrades.corner_shot.name"),
- help: (lvl: number) => t("upgrades.corner_shot.tooltip"),
- fullHelp: t("upgrades.corner_shot.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 175000,
- gift: false,
- id: "limitless",
- max: 1,
- name: t("upgrades.limitless.name"),
- help: (lvl: number) => t("upgrades.limitless.tooltip", { lvl }),
- fullHelp: t("upgrades.limitless.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 185000,
- gift: false,
- id: "trickledown",
- max: 1,
- name: t("upgrades.trickledown.name"),
- help: (lvl: number) => t("upgrades.trickledown.tooltip", { lvl }),
- fullHelp: t("upgrades.trickledown.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 190000,
- gift: false,
- id: "transparency",
- max: 3,
- name: t("upgrades.transparency.name"),
- help: (lvl: number) =>
- t("upgrades.transparency.tooltip", { lvl, percent: lvl * 50 }),
- fullHelp: t("upgrades.transparency.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 195000,
- gift: false,
- id: "superhot",
- max: 3,
- name: t("upgrades.superhot.name"),
- help: (lvl: number) => t("upgrades.superhot.tooltip", { lvl }),
- fullHelp: t("upgrades.superhot.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 205000,
- gift: false,
- id: "rainbow",
- max: 7,
- name: t("upgrades.rainbow.name"),
- help: (lvl: number) => t("upgrades.rainbow.tooltip", { lvl }),
- fullHelp: t("upgrades.rainbow.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "metamorphosis",
- threshold: 210000,
- gift: false,
- id: "hypnosis",
- max: 1,
- name: t("upgrades.hypnosis.name"),
- help: (lvl: number) => t("upgrades.hypnosis.tooltip", { lvl }),
- fullHelp: t("upgrades.hypnosis.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 215000,
- gift: false,
- id: "bricks_attract_ball",
- max: 1,
- name: t("upgrades.bricks_attract_ball.name"),
- help: (lvl: number) =>
- t("upgrades.bricks_attract_ball.tooltip", { count: lvl * 3 }),
- fullHelp: t("upgrades.bricks_attract_ball.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 220000,
- gift: false,
- id: "buoy",
- max: 3,
- name: t("upgrades.buoy.name"),
- help: (lvl: number) => t("upgrades.buoy.tooltip", { duration: lvl * 0.5 }),
- fullHelp: t("upgrades.buoy.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 225000,
- gift: false,
- id: "ottawa_treaty",
- max: 1,
- name: t("upgrades.ottawa_treaty.name"),
- help: () => t("upgrades.ottawa_treaty.tooltip"),
- fullHelp: t("upgrades.ottawa_treaty.verbose_description"),
- },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 155000,
+ gift: false,
+ id: "implosions",
+ max: 1,
+ name: t("upgrades.implosions.name"),
+ help: (lvl: number) => t("upgrades.implosions.tooltip"),
+ fullHelp: t("upgrades.implosions.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 160000,
+ gift: false,
+ id: "corner_shot",
+ max: 1,
+ name: t("upgrades.corner_shot.name"),
+ help: (lvl: number) => t("upgrades.corner_shot.tooltip"),
+ fullHelp: t("upgrades.corner_shot.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 175000,
+ gift: false,
+ id: "limitless",
+ max: 1,
+ name: t("upgrades.limitless.name"),
+ help: (lvl: number) => t("upgrades.limitless.tooltip", { lvl }),
+ fullHelp: t("upgrades.limitless.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 185000,
+ gift: false,
+ id: "trickledown",
+ max: 1,
+ name: t("upgrades.trickledown.name"),
+ help: (lvl: number) => t("upgrades.trickledown.tooltip", { lvl }),
+ fullHelp: t("upgrades.trickledown.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 190000,
+ gift: false,
+ id: "transparency",
+ max: 3,
+ name: t("upgrades.transparency.name"),
+ help: (lvl: number) =>
+ t("upgrades.transparency.tooltip", { lvl, percent: lvl * 50 }),
+ fullHelp: t("upgrades.transparency.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 195000,
+ gift: false,
+ id: "superhot",
+ max: 3,
+ name: t("upgrades.superhot.name"),
+ help: (lvl: number) => t("upgrades.superhot.tooltip", { lvl }),
+ fullHelp: t("upgrades.superhot.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 205000,
+ gift: false,
+ id: "rainbow",
+ max: 7,
+ name: t("upgrades.rainbow.name"),
+ help: (lvl: number) => t("upgrades.rainbow.tooltip", { lvl }),
+ fullHelp: t("upgrades.rainbow.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "metamorphosis",
+ threshold: 210000,
+ gift: false,
+ id: "hypnosis",
+ max: 1,
+ name: t("upgrades.hypnosis.name"),
+ help: (lvl: number) => t("upgrades.hypnosis.tooltip", { lvl }),
+ fullHelp: t("upgrades.hypnosis.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 215000,
+ gift: false,
+ id: "bricks_attract_ball",
+ max: 1,
+ name: t("upgrades.bricks_attract_ball.name"),
+ help: (lvl: number) =>
+ t("upgrades.bricks_attract_ball.tooltip", { count: lvl * 3 }),
+ fullHelp: t("upgrades.bricks_attract_ball.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 220000,
+ gift: false,
+ id: "buoy",
+ max: 3,
+ name: t("upgrades.buoy.name"),
+ help: (lvl: number) =>
+ t("upgrades.buoy.tooltip", { duration: lvl * 0.5 }),
+ fullHelp: t("upgrades.buoy.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 225000,
+ gift: false,
+ id: "ottawa_treaty",
+ max: 1,
+ name: t("upgrades.ottawa_treaty.name"),
+ help: () => t("upgrades.ottawa_treaty.tooltip"),
+ fullHelp: t("upgrades.ottawa_treaty.verbose_description"),
+ },
+
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 235000,
+ gift: false,
+ id: "sticky_coins",
+ max: 1,
+ name: t("upgrades.sticky_coins.name"),
+ help: (lvl: number) => t("upgrades.sticky_coins.tooltip"),
+ fullHelp: t("upgrades.sticky_coins.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 0,
+ id: "base_combo",
+ gift: true,
+ max: 7,
+ name: t("upgrades.base_combo.name"),
+ help: (lvl: number) =>
+ t("upgrades.base_combo.tooltip", { coins: 1 + lvl * 3 }),
+ fullHelp: t("upgrades.base_combo.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 0,
+ gift: false,
+ id: "viscosity",
+ max: 3,
+ name: t("upgrades.viscosity.name"),
+ help: () => t("upgrades.viscosity.tooltip"),
+ fullHelp: t("upgrades.viscosity.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 700,
+ gift: false,
+ id: "coin_magnet",
+ max: 3,
+ name: t("upgrades.coin_magnet.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.coin_magnet.tooltip")
+ : t("upgrades.coin_magnet.help_plural"),
+ fullHelp: t("upgrades.coin_magnet.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 1000,
+ gift: false,
+ id: "smaller_puck",
+ max: 2,
+ name: t("upgrades.smaller_puck.name"),
+ help: (lvl: number) =>
+ t("upgrades.smaller_puck.tooltip", { percent: 50 * lvl }),
+ fullHelp: t("upgrades.smaller_puck.verbose_description"),
+ },
+ {
+ category: categories.advanced,
+ requires: "",
+ threshold: 2500,
+ gift: false,
+ id: "metamorphosis",
+ max: 1,
+ name: t("upgrades.metamorphosis.name"),
+ help: (lvl: number) => t("upgrades.metamorphosis.tooltip", { lvl }),
+ fullHelp: t("upgrades.metamorphosis.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 6000,
+ id: "sapper",
+ gift: false,
+ max: 7,
+ name: t("upgrades.sapper.name"),
+ help: (lvl: number) =>
+ lvl == 1
+ ? t("upgrades.sapper.tooltip")
+ : t("upgrades.sapper.help_plural", { lvl }),
+ fullHelp: t("upgrades.sapper.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 9000,
+ id: "bigger_explosions",
+ gift: false,
+ max: 1,
+ name: t("upgrades.bigger_explosions.name"),
+ help: (lvl: number) => t("upgrades.bigger_explosions.tooltip"),
+ fullHelp: t("upgrades.bigger_explosions.verbose_description"),
+ },
+ {
+ category: categories.simple,
+ requires: "",
+ threshold: 13000,
+ gift: false,
+ adventure: false,
+ id: "extra_levels",
+ max: 3,
+ name: t("upgrades.extra_levels.name"),
+ help: (lvl: number) =>
+ t("upgrades.extra_levels.tooltip", { count: lvl + 7 }),
+ fullHelp: t("upgrades.extra_levels.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 170000,
+ gift: false,
+ id: "fountain_toss",
+ max: 7,
+ name: t("upgrades.fountain_toss.name"),
+ help: () => t("upgrades.fountain_toss.tooltip"),
+ fullHelp: t("upgrades.fountain_toss.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 180000,
+ gift: false,
+ id: "minefield",
+ max: 3,
+ name: t("upgrades.minefield.name"),
+ help: (lvl: number) => t("upgrades.minefield.tooltip", { lvl }),
+ fullHelp: t("upgrades.minefield.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 18000,
+ gift: false,
+ id: "soft_reset",
+ max: 3,
+ name: t("upgrades.soft_reset.name"),
+ help: (lvl: number) =>
+ t("upgrades.soft_reset.tooltip", {
+ percent: Math.round(comboKeepingRate(lvl) * 100),
+ }),
+ fullHelp: t("upgrades.soft_reset.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 80000,
+ gift: false,
+ id: "shunt",
+ max: 3,
+ name: t("upgrades.shunt.name"),
+ help: (lvl: number) =>
+ t("upgrades.shunt.tooltip", {
+ percent: Math.round(comboKeepingRate(lvl) * 100),
+ }),
+ fullHelp: t("upgrades.shunt.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 140000,
+ gift: true,
+ id: "passive_income",
+ max: 4,
+ name: t("upgrades.passive_income.name"),
+ help: (lvl: number) =>
+ t("upgrades.passive_income.tooltip", { time: lvl * 0.25, lvl }),
+ fullHelp: t("upgrades.passive_income.verbose_description"),
+ },
+ {
+ category: categories.combo_boost,
+ requires: "",
+ threshold: 40000,
+ gift: false,
+ id: "sturdy_bricks",
+ max: 4,
+ name: t("upgrades.sturdy_bricks.name"),
+ help: (lvl: number) =>
+ t("upgrades.sturdy_bricks.tooltip", { lvl, percent: lvl * 50 }),
+ fullHelp: t("upgrades.sturdy_bricks.verbose_description"),
+ },
+ ] as const
- {
- category: categories.advanced,
- requires: "",
- threshold: 235000,
- gift: false,
- id: "sticky_coins",
- max: 1,
- name: t("upgrades.sticky_coins.name"),
- help: (lvl: number) => t("upgrades.sticky_coins.tooltip"),
- fullHelp: t("upgrades.sticky_coins.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 0,
- id: "base_combo",
- gift: true,
- max: 7,
- name: t("upgrades.base_combo.name"),
- help: (lvl: number) =>
- t("upgrades.base_combo.tooltip", { coins: 1 + lvl * 3 }),
- fullHelp: t("upgrades.base_combo.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 0,
- gift: false,
- id: "viscosity",
- max: 3,
- name: t("upgrades.viscosity.name"),
- help: () => t("upgrades.viscosity.tooltip"),
- fullHelp: t("upgrades.viscosity.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 700,
- gift: false,
- id: "coin_magnet",
- max: 3,
- name: t("upgrades.coin_magnet.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.coin_magnet.tooltip")
- : t("upgrades.coin_magnet.help_plural"),
- fullHelp: t("upgrades.coin_magnet.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 1000,
- gift: false,
- id: "smaller_puck",
- max: 2,
- name: t("upgrades.smaller_puck.name"),
- help: (lvl: number) =>
- t("upgrades.smaller_puck.tooltip", { percent: 50 * lvl }),
- fullHelp: t("upgrades.smaller_puck.verbose_description"),
- },
- {
- category: categories.advanced,
- requires: "",
- threshold: 2500,
- gift: false,
- id: "metamorphosis",
- max: 1,
- name: t("upgrades.metamorphosis.name"),
- help: (lvl: number) => t("upgrades.metamorphosis.tooltip", { lvl }),
- fullHelp: t("upgrades.metamorphosis.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 6000,
- id: "sapper",
- gift: false,
- max: 7,
- name: t("upgrades.sapper.name"),
- help: (lvl: number) =>
- lvl == 1
- ? t("upgrades.sapper.tooltip")
- : t("upgrades.sapper.help_plural", { lvl }),
- fullHelp: t("upgrades.sapper.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 9000,
- id: "bigger_explosions",
- gift: false,
- max: 1,
- name: t("upgrades.bigger_explosions.name"),
- help: (lvl: number) => t("upgrades.bigger_explosions.tooltip"),
- fullHelp: t("upgrades.bigger_explosions.verbose_description"),
- },
- {
- category: categories.simple,
- requires: "",
- threshold: 13000,
- gift: false,
- adventure: false,
- id: "extra_levels",
- max: 3,
- name: t("upgrades.extra_levels.name"),
- help: (lvl: number) =>
- t("upgrades.extra_levels.tooltip", { count: lvl + 7 }),
- fullHelp: t("upgrades.extra_levels.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 170000,
- gift: false,
- id: "fountain_toss",
- max: 7,
- name: t("upgrades.fountain_toss.name"),
- help: () => t("upgrades.fountain_toss.tooltip"),
- fullHelp: t("upgrades.fountain_toss.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 180000,
- gift: false,
- id: "minefield",
- max: 3,
- name: t("upgrades.minefield.name"),
- help: (lvl: number) => t("upgrades.minefield.tooltip", { lvl }),
- fullHelp: t("upgrades.minefield.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 18000,
- gift: false,
- id: "soft_reset",
- max: 3,
- name: t("upgrades.soft_reset.name"),
- help: (lvl: number) =>
- t("upgrades.soft_reset.tooltip", {
- percent: Math.round(comboKeepingRate(lvl) * 100),
- }),
- fullHelp: t("upgrades.soft_reset.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 80000,
- gift: false,
- id: "shunt",
- max: 3,
- name: t("upgrades.shunt.name"),
- help: (lvl: number) =>
- t("upgrades.shunt.tooltip", {
- percent: Math.round(comboKeepingRate(lvl) * 100),
- }),
- fullHelp: t("upgrades.shunt.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 140000,
- gift: true,
- id: "passive_income",
- max: 4,
- name: t("upgrades.passive_income.name"),
- help: (lvl: number) =>
- t("upgrades.passive_income.tooltip", { time: lvl * 0.25, lvl }),
- fullHelp: t("upgrades.passive_income.verbose_description"),
- },
- {
- category: categories.combo_boost,
- requires: "",
- threshold: 40000,
- gift: false,
- id: "sturdy_bricks",
- max: 4,
- name: t("upgrades.sturdy_bricks.name"),
- help: (lvl: number) =>
- t("upgrades.sturdy_bricks.tooltip", { lvl, percent: lvl * 50 }),
- fullHelp: t("upgrades.sturdy_bricks.verbose_description"),
- },
-].sort((a,b)=>(a.category-b.category) || (a.threshold-b.threshold)) as const;