This commit is contained in:
Renan LE CARO 2025-04-20 21:14:35 +02:00
parent 9716235531
commit 0a1d9dfe2f
18 changed files with 2391 additions and 1981 deletions

View file

@ -22,6 +22,14 @@ Other translation are very welcome, contact me if you'd like to submit one.
# Changelog
## To do
## Done
- level editor : removed the conditions on bricks count, level name and credits to be able to copy the code
- shadow around ball when there are many coins : enabled in basic mode too
- hot start : after reset, if you raise the combo again, only start ticking down after a whole second.
- new perk : ottawa treaty, breaking a brick near a bomb disarms the bomb
- shocks now doesn't add ball speed at level 1
- creative mode UI rework
- compound_interest : combo resets as soon as coin passes the paddle line
- added bombs to implosion and kaboom starter levels
- toast an error if storage is blocked
@ -320,7 +328,7 @@ Other translation are very welcome, contact me if you'd like to submit one.
- cash out : double last level's gains
- snowball : Combo resets every 0.1s . +1 combo for each combo gained Since last reset.
- Chain reaction : +lvl*lvl combo per brick broken by an explosion, combo resets after explosion is over
- catching a coin changes the color of the balls
- coins stained by balls
- fast pause : pause delay divided by {{lvl}} (helps with teleport)
- [colin] Capital - les vies non perdues à la fin du niveau rapportent un bonus de points

163
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

@ -116,7 +116,7 @@ export async function openCreativeModePerksPicker() {
});
setSettingValue("creativeModePerks", creativeModePerks);
setSettingValue("creativeModeLevel", '')
} else if (choice === "play") {
} else if (choice === "play" || ("bricks" in choice && choice.name==getSettingValue("creativeModeLevel", ''))) {
if (await confirmRestart(gameState)) {
restart({
perks: creativeModePerks,
@ -131,6 +131,8 @@ export async function openCreativeModePerksPicker() {
creativeModePerks[choice.id] =
((creativeModePerks[choice.id] || 0) + 1) %
(choice.max + 1 + (creativeModePerks.limitless || 0));
setSettingValue("creativeModePerks", creativeModePerks);
}
}
}

View file

@ -1341,8 +1341,22 @@
{
"color": "#115988",
"size": 21,
"bricks": "__________________________________________________yy_______________yy__yy__yy___________yy__yy__yy____________yy__yy_yy_________y__yy__yy_yy________yyy_yyy_yy_yy_________yy__yy_yyyyy__________yy_yyyyyyyy___yyy____yyyyygggyyy__yyy______yyygBBBgyy_yyy________ygBBBBBgyyyy_________ygBBBBBgyyy__________yygBBBgyyyy___________yygBgyyyy____________yyyByyyy_____________yyyyByy_______________yyByy_________________r_________________________________",
"bricks": "__________________________________________________yy_______________yy__yy__yy___________yy__yy__yy____________yy__yy_yy_________y__yy__yy_yy________yyy_yyy_yy_yy_________yy__yy_yyyyy__________yy_yyyyyyyy___yyy____yyyyygggyyy__yyy______yyygBBBgyy_yyy________ygBBBBBgyyyy__W______ygBBBBBgyyy__________yygBBBgyyyy___________yygBgyyyy____________yyyByyyy_____________yyyyByy_______________yyByy_________________r_________________________________",
"name": "A Very Dangerous High-Five",
"credit": "Suggested by Noodlemire. A unique shape, fun to bounce the ball between fingers. The palm was initially boring on its own, so I gave it a big bomb. It adds a distinct feeling between the top and bottom halves."
},
{
"name": "icon:buoy",
"size": 7,
"bricks": "___b______b_____bbb__abbbbbaaatttaaaaataaaaaaaaaa",
"svg": null,
"color": ""
},
{
"name": "icon:ottawa_treaty",
"size": 8,
"bricks": "BBtWWtBBBttWWttBtWWtttWtttWWWWtttttWWtttttWWWtttBWWtWttBBBtttWBB",
"svg": null,
"color": ""
}
]

View file

@ -5,7 +5,6 @@ import { gameState, pause, restart } from "./game";
import {
currentLevelInfo,
describeLevel,
findLast,
pickedUpgradesHTMl,
reasonLevelIsLocked,
} from "./game_utils";
@ -98,6 +97,8 @@ export function gameOver(title: string, intro: string) {
help: "",
},
`<div id="level-recording-container"></div>`,
pickedUpgradesHTMl(gameState),
unlocksInfo,
getHistograms(gameState),
],

File diff suppressed because it is too large Load diff

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "الطوب يجذب العملات المعدنية",
"upgrades.bricks_attract_coins.tooltip": "يساعدهم على البقاء هناك",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "",
"upgrades.buoy.tooltip": "",
"upgrades.buoy.verbose_description": "",
"upgrades.clairvoyant.name": "مستبصر",
"upgrades.clairvoyant.tooltip": "شاهد المستويات القادمة، نقاط الصحة للطوب واتجاه الكرة",
"upgrades.clairvoyant.verbose_description": "يساعدك على اختيار الترقيات المناسبة وفهم كيفية عمل الطوب المتين. يُضيف المستويان 2 و3 معلومات إضافية حول فائدة مشكوك فيها (متوفرة في وضع الحلقة).",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "خيار إضافي",
"upgrades.one_more_choice.tooltip": "ستوفر عمليات رفع المستوى الإضافية {{lvl}} خيارًا إضافيًا في القائمة",
"upgrades.one_more_choice.verbose_description": "ستحتوي كل قائمة ترقية على خيار إضافي. هذا لا يزيد من عدد الترقيات المتاحة.",
"upgrades.ottawa_treaty.name": "",
"upgrades.ottawa_treaty.tooltip": "",
"upgrades.ottawa_treaty.verbose_description": "",
"upgrades.passive_income.name": "الدخل السلبي",
"upgrades.passive_income.tooltip": "+{{lvl}} مجموعة / لبنة، ما لم يتم تحريك المجداف في آخر {{time}}ثانية، ثم يتم إعادة تعيينه بدلاً من ذلك",
"upgrades.passive_income.verbose_description": "يمكن لبعض الامتيازات أن تساعد الكرات على القيام بما تريد دون الحاجة إلى القيام بأي شيء.",

View file

@ -9617,6 +9617,116 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>buoy</name>
<children>
<concept_node>
<name>name</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>tooltip</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>verbose_description</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>clairvoyant</name>
<children>
@ -12217,6 +12327,116 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>ottawa_treaty</name>
<children>
<concept_node>
<name>name</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>tooltip</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>verbose_description</name>
<description/>
<comment/>
<translations>
<translation>
<language>ar-LB</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-CL</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>passive_income</name>
<children>

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "Ziegelsteine ziehen Münzen an",
"upgrades.bricks_attract_coins.tooltip": "Hilft ihnen, dort oben zu bleiben",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "",
"upgrades.buoy.tooltip": "",
"upgrades.buoy.verbose_description": "",
"upgrades.clairvoyant.name": "Hellsichtig",
"upgrades.clairvoyant.tooltip": "Sehen Sie die nächsten Levels, die HP der Steine und die Ballrichtung",
"upgrades.clairvoyant.verbose_description": "Hilft dir, die richtigen Upgrades auszuwählen und zu verstehen, was es mit den robusten Steinen auf sich hat. Level 2 und 3 bringen zusätzliches Wissen von zweifelhaftem Nutzen (erreichbar im Loop-Modus)",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "Extra Auswahl",
"upgrades.one_more_choice.tooltip": "Weitere Stufenaufstiege bieten {{lvl}} weitere Option(en) in der Liste",
"upgrades.one_more_choice.verbose_description": "Jedes Upgrade-Menü wird eine weitere Option enthalten. Erhöht nicht die Anzahl der Upgrades, die Sie auswählen können.",
"upgrades.ottawa_treaty.name": "",
"upgrades.ottawa_treaty.tooltip": "",
"upgrades.ottawa_treaty.verbose_description": "",
"upgrades.passive_income.name": "Passives Einkommen",
"upgrades.passive_income.tooltip": "+{{lvl}} Combo / Brick, es sei denn, das Paddel hat sich in den letzten {{time}}s bewegt, dann wird es stattdessen zurückgesetzt",
"upgrades.passive_income.verbose_description": "Einige Vergünstigungen können den Bällen helfen, das zu tun, was du willst, ohne dass du etwas tun musst.",

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "Bricks attract coins",
"upgrades.bricks_attract_coins.tooltip": "Helps them stay up there",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "Buoy",
"upgrades.buoy.tooltip": "Coins float for {{duration}} seconds on the bottom line. ",
"upgrades.buoy.verbose_description": "Effect is most visible in mobile mode",
"upgrades.clairvoyant.name": "Clairvoyant",
"upgrades.clairvoyant.tooltip": "See upcoming levels, bricks HP and ball direction",
"upgrades.clairvoyant.verbose_description": "Helps you pick the right upgrades and understand what's going on with sturdy bricks. Level 2 and 3 bring additional knowledge of dubious utility (reachable in loop mode)",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "Extra choice",
"upgrades.one_more_choice.tooltip": "Further level ups will offer {{lvl}} more option(s) in the list",
"upgrades.one_more_choice.verbose_description": "Every upgrade menu will have one more option. Doesn't increase the number of upgrades you can pick.",
"upgrades.ottawa_treaty.name": "Ottawa treaty",
"upgrades.ottawa_treaty.tooltip": "Breaking a brick near a bomb disarms it",
"upgrades.ottawa_treaty.verbose_description": "The nearby bomb will be replaced by a colored block. If you have sapper, the ball will loose its sapper effect until next bounce. Only one bomb can be replaced at a time.",
"upgrades.passive_income.name": "Passive income",
"upgrades.passive_income.tooltip": "+{{lvl}} combo / brick, unless the paddle moved in the last {{time}}s, then it resets instead",
"upgrades.passive_income.verbose_description": "Some perks can help the balls do what you want without needing to do anything.",

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "Los ladrillos atraen monedas",
"upgrades.bricks_attract_coins.tooltip": "Les ayuda a permanecer allí arriba.",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "",
"upgrades.buoy.tooltip": "",
"upgrades.buoy.verbose_description": "",
"upgrades.clairvoyant.name": "Perspicaz",
"upgrades.clairvoyant.tooltip": "Revela los niveles, el PV de los ladrillos y la dirección de las balas",
"upgrades.clairvoyant.verbose_description": "Te ayuda a elegir las mejoras adecuadas y a entender qué ocurre con los \"ladrillos macizos\". Los niveles 2 y 3 (en modo bucle) proporcionan información adicional de dudosa utilidad.",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "La respuesta D",
"upgrades.one_more_choice.tooltip": "1 opción de mejora adicional disponible hasta el final del juego",
"upgrades.one_more_choice.verbose_description": "Cada menú de mejoras tendrá una opción adicional. Esto no aumenta el número de mejoras que puede elegir, pero le ayuda a crear el perfil ideal. \"Respuesta D\" es una referencia a un sketch clásico.",
"upgrades.ottawa_treaty.name": "",
"upgrades.ottawa_treaty.tooltip": "",
"upgrades.ottawa_treaty.verbose_description": "",
"upgrades.passive_income.name": "Ingresos pasivos",
"upgrades.passive_income.tooltip": "+{{lvl}} combo / ladrillo, a menos que la raqueta se haya movido en los últimos {{time}} segundos, en cuyo caso se pierde el combo.",
"upgrades.passive_income.verbose_description": "Algunas mejoras hacen que las pelotas se muevan sin necesidad de poner la raqueta en movimiento.",

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "Briques attirent les pièces",
"upgrades.bricks_attract_coins.tooltip": "Aide à garder les pièces en suspension",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "",
"upgrades.buoy.tooltip": "",
"upgrades.buoy.verbose_description": "",
"upgrades.clairvoyant.name": "Clairvoyant",
"upgrades.clairvoyant.tooltip": "Révèle les niveaux, PV des briques et direction des balles",
"upgrades.clairvoyant.verbose_description": "Vous aide à choisir les bonnes améliorations et à comprendre ce qu'il se passe avec \"briques solides\". Les niveaux 2 et 3 (en mode loop) amènent des informations complémentaires d'une utilité douteuse. ",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "La réponse D",
"upgrades.one_more_choice.tooltip": "1 choix supplémentaire d'amélioration proposé jusqu'à la fin de la partie",
"upgrades.one_more_choice.verbose_description": "Chaque menu d'amélioration comportera une option supplémentaire. Cela n'augmente pas le nombre d'améliorations que vous pouvez choisir, mais vous aide à créer le profile idéal. \"La réponse D\" est une référence à un sketch classique. ",
"upgrades.ottawa_treaty.name": "",
"upgrades.ottawa_treaty.tooltip": "",
"upgrades.ottawa_treaty.verbose_description": "",
"upgrades.passive_income.name": "Revenu passif",
"upgrades.passive_income.tooltip": "+{{lvl}} combo / brique, sauf si la raquette à bougé dans les {{time}} dernières secondes, combo perdu dans ce cas",
"upgrades.passive_income.verbose_description": "Certaines amélioration font bouger les balles sans avoir besoin de mettre la raquette en mouvement.",

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "Кирпичи притягивают монеты",
"upgrades.bricks_attract_coins.tooltip": "Помогает им оставаться на вершине",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "",
"upgrades.buoy.tooltip": "",
"upgrades.buoy.verbose_description": "",
"upgrades.clairvoyant.name": "Ясновидящий",
"upgrades.clairvoyant.tooltip": "Просматривайте предстоящие уровни, количество кирпичей и направление движения мяча",
"upgrades.clairvoyant.verbose_description": "Поможет выбрать правильные апгрейды и понять, что происходит с прочными кирпичами. Уровни 2 и 3 дают дополнительные знания сомнительной полезности (достигаются в режиме цикла)",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "Дополнительный выбор",
"upgrades.one_more_choice.tooltip": "При дальнейшем повышении уровня будет предложено на {{lvl}} больше вариантов в списке",
"upgrades.one_more_choice.verbose_description": "В каждом меню апгрейдов появится еще одна опция. Это не увеличивает количество апгрейдов, которые вы можете выбрать.",
"upgrades.ottawa_treaty.name": "",
"upgrades.ottawa_treaty.tooltip": "",
"upgrades.ottawa_treaty.verbose_description": "",
"upgrades.passive_income.name": "Пассивный доход",
"upgrades.passive_income.tooltip": "+{{lvl}} комбо/кирпич, если только паддл не двигался в течение последних {{time}}с, тогда он сбрасывается.",
"upgrades.passive_income.verbose_description": "Некоторые привилегии могут помочь шарам делать то, что вы хотите, без необходимости что-либо предпринимать.",

View file

@ -269,6 +269,9 @@
"upgrades.bricks_attract_coins.name": "Tuğlalar madeni paraları çeker",
"upgrades.bricks_attract_coins.tooltip": "Onların orada kalmalarına yardımcı olur",
"upgrades.bricks_attract_coins.verbose_description": "",
"upgrades.buoy.name": "",
"upgrades.buoy.tooltip": "",
"upgrades.buoy.verbose_description": "",
"upgrades.clairvoyant.name": "Durugörü sahibi",
"upgrades.clairvoyant.tooltip": "Yaklaşan seviyeleri, tuğla HP'sini ve top yönünü görün",
"upgrades.clairvoyant.verbose_description": "Doğru yükseltmeleri seçmenize ve sağlam tuğlalarla neler olup bittiğini anlamanıza yardımcı olur. Seviye 2 ve 3, şüpheli fayda hakkında ek bilgi getirir (döngü modunda erişilebilir)",
@ -340,6 +343,9 @@
"upgrades.one_more_choice.name": "Ekstra seçenek",
"upgrades.one_more_choice.tooltip": "Daha fazla seviye atlama, listede {{lvl}} daha fazla seçenek sunacak",
"upgrades.one_more_choice.verbose_description": "Her yükseltme menüsü bir seçeneğe daha sahip olacak. Seçebileceğiniz yükseltme sayısını artırmaz.",
"upgrades.ottawa_treaty.name": "",
"upgrades.ottawa_treaty.tooltip": "",
"upgrades.ottawa_treaty.verbose_description": "",
"upgrades.passive_income.name": "Pasif gelir",
"upgrades.passive_income.tooltip": "+{{lvl}} kombo / tuğla, kürek son {{time}}saniyede hareket etmediği sürece, bunun yerine sıfırlanır",
"upgrades.passive_income.verbose_description": "Bazı özellikler, topların hiçbir şey yapmanıza gerek kalmadan istediğinizi yapmasına yardımcı olabilir.",

View file

@ -165,10 +165,7 @@ export async function editRawLevelList(nth: number, color = "W") {
text: t("editor.editing.copy"),
value: "copy",
help: t("editor.editing.copy_help"),
disabled:
!level.name ||
!level.credit ||
bricks.filter((b) => b !== "_").length < 6,
},
{
text: t("editor.editing.bigger"),
@ -253,14 +250,14 @@ export async function editRawLevelList(nth: number, color = "W") {
return;
}
if (action === "copy") {
let text = "```\n[" + level.name?.replace(/\[|\]/gi, " ") + "]";
let text = "```\n[" + (level.name||'unnamed level')?.replace(/\[|\]/gi, " ") + "]";
bricks.forEach((b, bi) => {
if (!(bi % level.size)) text += "\n";
text += b;
});
text +=
"\n[" +
(level.credit?.replace(/\[|\]/gi, " ") || "Missing credits!") +
(level.credit?.replace(/\[|\]/gi, " ") || "Missing credits") +
"]\n```";
navigator.clipboard.writeText(text);
// return

View file

@ -302,22 +302,20 @@ export function render(gameState: GameState) {
});
startWork("render:ball shade");
// Black shadow around balls
if (!isOptionOn("basic")) {
ctx.globalCompositeOperation = "source-over";
gameState.balls.forEach((ball) => {
ctx.globalAlpha =
Math.min(0.8, liveCount(gameState.coins) / 20) *
(1 - ballTransparency(ball, gameState));
ctx.globalCompositeOperation = "source-over";
gameState.balls.forEach((ball) => {
ctx.globalAlpha =
Math.min(0.8, liveCount(gameState.coins) / 20) *
(1 - ballTransparency(ball, gameState));
drawBall(
ctx,
level.color || "#000",
gameState.ballSize * 6,
ball.x,
ball.y,
);
});
}
drawBall(
ctx,
level.color || "#000",
gameState.ballSize * 6,
ball.x,
ball.y,
);
});
startWork("render:bricks");
ctx.globalCompositeOperation = "source-over";
renderAllBricks();

1
src/types.d.ts vendored
View file

@ -84,6 +84,7 @@ export type Coin = {
destroyed?: boolean;
collidedLastFrame?: boolean;
metamorphosisPoints: number;
floatingTime:number;
};
export type Ball = {
x: number;

View file

@ -825,4 +825,25 @@ export const rawUpgrades = [
t("upgrades.bricks_attract_ball.tooltip", { count: lvl * 3 }),
fullHelp: t("upgrades.bricks_attract_ball.verbose_description"),
},
{
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"),
},
{
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"),
},
] as const;