This commit is contained in:
Renan LE CARO 2025-03-29 11:24:45 +01:00
parent 39b326a15b
commit e08c1e7b9e
13 changed files with 1214 additions and 1886 deletions

View file

@ -1,71 +0,0 @@
import { t } from "./i18n/i18n";
import { Debuff } from "./types";
export const debuffs = [
{
id: "deadly_coins",
max: 20,
name: (lvl: number) => t("debuffs.deadly_coins.help", { lvl }),
help: (lvl: number) => t("debuffs.deadly_coins.help", { lvl }),
},
{
id: "frozen_coins",
max: 20,
name: (lvl: number) => t("debuffs.frozen_coins.help", { lvl }),
help: (lvl: number) => t("debuffs.frozen_coins.help", { lvl }),
},
{
id: "more_bombs",
max: 20,
name: (lvl: number) => t("debuffs.more_bombs.help", { lvl }),
help: (lvl: number) => t("debuffs.more_bombs.help", { lvl }),
},
{
id: "banned",
max: 50,
name: (lvl: number, banned: string) =>
t("debuffs.banned.description", { lvl, banned }),
help: (lvl: number, perk: string) =>
t("debuffs.banned.help", { lvl, perk }),
},
{
id: "interference",
max: 20,
name: (lvl: number) => t("debuffs.interference.help", { lvl }),
help: (lvl: number) => t("debuffs.interference.help", { lvl }),
},
{
id: "fragility",
max: 5,
name: (lvl: number) => t("debuffs.fragility.help", { percent: lvl * 20 }),
help: (lvl: number) => t("debuffs.fragility.help", { percent: lvl * 20 }),
},
{
id: "sturdiness",
max: 5,
name: (lvl: number) => t("debuffs.sturdiness.help", { lvl }),
help: (lvl: number) => t("debuffs.sturdiness.help", { lvl }),
},
] as const as Debuff[];
/*
Possible challenges :
- exclusion : one of your current perks (except the kept one) is banned
- fireworks : some bricks are explosive, you're not told which ones
- ball creates a draft behind itself that blows coins in odd patterns
- downward wind
- side wind
- add red anti-coins that apply downgrades
- destroy your combo
- hurt your score
- behave like heavier coins.
- deactivate a perk for this level
- reduce your number of coins
- destroy all coins on screen
- lowers your combo
- reduce your choice for your next perk
*/

View file

@ -15,7 +15,6 @@ import { getAudioContext, playPendingSounds } from "./sounds";
import {
bannedUpgradesHTMl,
currentLevelInfo,
debuffsHTMl,
getRowColIndex,
levelsListHTMl,
max_levels,
@ -447,6 +446,13 @@ document.addEventListener("visibilitychange", () => {
async function openScorePanel() {
pause(true);
const banned = upgrades
.filter((u) => gameState.bannedPerks[u.id])
.map((u) => u.name)
.join(", ");
const cb = await asyncAlert({
title: gameState.loop
? t("score_panel.title_looped", {
@ -465,9 +471,9 @@ async function openScorePanel() {
gameState.isCreativeModeRun ? `<p>${t("score_panel.test_run")}</p>` : "",
pickedUpgradesHTMl(gameState),
levelsListHTMl(gameState),
debuffsHTMl(gameState),
gameState.rerolls?
t('score_panel.rerolls_count', {rerolls:gameState.rerolls}):''
t('score_panel.rerolls_count', {rerolls:gameState.rerolls}):'',
banned && t('score_panel.banned',{banned})
],
allowClose: true,
});
@ -1010,31 +1016,12 @@ restart(
(window.location.search.includes("stressTest") && {
level: "Bird",
perks: {
sapper: 5,
bigger_explosions: 20,
// // unbounded: 1,
// // pierce_color: 1,
// pierce: 1,
// streak_shots: 1,
// multiball: 6,
base_combo: 7,
telekinesis: 2,
yoyo: 2,
pierce: 10,
// metamorphosis: 1,
// implosions: 1,
// sturdy_bricks:5
coin_magnet: 2,
extra_life: 3,
pierce:1,
sapper:1,
bigger_explosions:6,
telekinesis:2
},
levelsPerLoop:2,
debuffs: {
// fragility:3
// deadly_coins: 20,
// frozen_coins: 20,
// interference:20,
},
}) ||
{},
);

View file

@ -3,9 +3,6 @@ import {
BallLike,
Coin,
colorString,
Debuff,
DebuffId,
Debuffs,
GameState,
LightFlash,
ParticleFlash,
@ -17,7 +14,7 @@ import {
import {
brickCenterX,
brickCenterY,
clamp,
clamp, comboKeepingRate,
countBricksAbove,
countBricksBelow,
currentLevelInfo,
@ -57,11 +54,10 @@ import { stopRecording } from "./recording";
import { isOptionOn } from "./options";
import { isPremium } from "./premium";
import { getRunLevels } from "./newGameState";
import { debuffs } from "./debuffs";
import { requiredAsyncAlert } from "./asyncAlert";
export function setMousePos(gameState: GameState, x: number) {
gameState.desiredPuckPosition = x;
gameState.puckPosition = x;
// Sets the puck position, and updates the ball position if they are supposed to follow it
gameState.needsRender = true;
}
@ -148,9 +144,9 @@ export function normalizeGameState(gameState: GameState) {
gameState.perks.slow_down * 2,
);
gameState.puckWidth =
gameState.puckWidth =Math.max(gameState.ballSize,
(gameState.gameZoneWidth / 12) *
(3 - gameState.perks.smaller_puck + gameState.perks.bigger_puck);
Math.min(12,3 - gameState.perks.smaller_puck + gameState.perks.bigger_puck));
let minX =
gameState.perks.corner_shot && gameState.levelTime
@ -166,10 +162,6 @@ export function normalizeGameState(gameState: GameState) {
gameState.gameZoneWidthRoundedUp -
gameState.puckWidth / 2;
if (gameState.puckFrozenUntil < gameState.levelTime || !gameState.levelTime) {
// Frozen, ignore
gameState.puckPosition = gameState.desiredPuckPosition;
}
gameState.puckPosition = clamp(gameState.puckPosition, minX, maxX);
@ -204,7 +196,7 @@ export function resetCombo(
if (prev > gameState.combo && gameState.perks.soft_reset) {
gameState.combo += Math.floor(
((prev - gameState.combo) * (gameState.perks.soft_reset * 10)) / 100,
(prev - gameState.combo) * comboKeepingRate(gameState.perks.soft_reset)
);
}
const lost = Math.max(0, prev - gameState.combo);
@ -349,15 +341,6 @@ export function explosionAt(
if (gameState.perks.zen) {
resetCombo(gameState, x, y);
}
if (gameState.debuffs.fragility) {
resetCombo(gameState, x, y);
forEachLiveOne(gameState.coins, (coin, index) => {
// Also destroys cursed coins
if (Math.random() < gameState.debuffs.fragility / 5) {
destroy(gameState.coins, index);
}
});
}
}
export function explodeBrick(
@ -442,7 +425,7 @@ export function explodeBrick(
gameState.perks.right_is_lava +
gameState.perks.top_is_lava +
gameState.perks.picky_eater +
gameState.perks.asceticism +
gameState.perks.asceticism*3 +
gameState.perks.zen +
gameState.perks.passive_income +
gameState.perks.nbricks +
@ -613,49 +596,38 @@ export async function gotoNextLoop(gameState: GameState) {
}
const userPerks = upgrades.filter((u) => gameState.perks[u.id]);
const { keep, debuff, targetPerk } = await requiredAsyncAlert<{
keep: PerkId;
debuff: DebuffId;
targetPerk: PerkId;
}>({
const keep = await requiredAsyncAlert<PerkId>({
title: t("loop.title", { loop: gameState.loop }),
content: [
t("loop.instructions"),
comboText,
...userPerks.map((u) => {
const randomDebuff =
sample(debuffs.filter((d) => gameState.debuffs[d.id] < d.max)) ||
sample(debuffs);
const targetPerk = sample(userPerks.filter((tp) => tp.id !== u.id));
...userPerks
.filter(u=>u.id!=='instant_upgrade')
.map((u) => {
return {
text:
u.name +
t("level_up.upgrade_perk_to_level", {
level: gameState.perks[u.id],
level: gameState.perks[u.id]+1,
}),
help: randomDebuff.help(
gameState.debuffs[randomDebuff.id] + 1,
targetPerk.name,
),
icon: u.icon,
value: {
keep: u.id,
debuff: randomDebuff.id,
targetPerk: targetPerk.id,
},
value: u.id,
help: u.help(gameState.perks[u.id]+1),
};
}),
],
});
userPerks.forEach(u=>{
if(u.id!==keep){
gameState.bannedPerks[u.id]=1
}
})
Object.assign(gameState.perks, makeEmptyPerksMap(upgrades), {
[keep]: gameState.perks[keep],
});
gameState.debuffs[debuff]++;
if (debuff == "banned") {
gameState.bannedPerks[targetPerk]++;
}
await setLevel(gameState, 0);
}
@ -684,7 +656,6 @@ export async function setLevel(gameState: GameState, l: number) {
gameState.levelStartScore = gameState.score;
gameState.levelSpawnedCoins = 0;
gameState.levelMisses = 0;
gameState.puckFrozenUntil = 0;
gameState.runStatistics.levelsPlayed++;
// Reset combo silently
@ -694,7 +665,7 @@ export async function setLevel(gameState: GameState, l: number) {
gameState.combo += Math.round(
Math.max(
0,
((finalCombo - gameState.combo) * 20 * gameState.perks.shunt) / 100,
(finalCombo - gameState.combo) * comboKeepingRate(gameState.perks.shunt) ,
),
);
}
@ -714,19 +685,6 @@ export async function setLevel(gameState: GameState, l: number) {
setBrick(gameState, i, lvl.bricks[i]);
}
if (gameState.debuffs.more_bombs) {
let attemps = 0;
let changed = 0;
while (attemps < 100 && changed < gameState.debuffs.more_bombs) {
attemps++;
const index = Math.floor(Math.random() * gameState.bricks.length);
if (gameState.bricks[index] && gameState.bricks[index] !== "black") {
gameState.bricks[index] = "black";
gameState.brickHP[index] = 1;
changed++;
}
}
}
// Balls color will depend on most common brick color sometimes
resetBalls(gameState);
gameState.needsRender = true;
@ -740,7 +698,7 @@ function setBrick(gameState: GameState, index: number, color: string) {
gameState.brickHP[index] =
(color === "black" && 1) ||
(color &&
1 + gameState.perks.sturdy_bricks + gameState.debuffs.sturdiness) ||
1 + gameState.perks.sturdy_bricks ) ||
0;
}
@ -902,12 +860,6 @@ export function bordersHitCheck(
coin.previousY = coin.y;
coin.x += coin.vx * delta;
coin.y += coin.vy * delta;
// coin.sx ||= 0;
// coin.sy ||= 0;
// coin.sx += coin.previousX - coin.x;
// coin.sy += coin.previousY - coin.y;
// coin.sx *= 0.9;
// coin.sy *= 0.9;
if (gameState.perks.wind) {
coin.vx +=
@ -932,7 +884,7 @@ export function bordersHitCheck(
coin.vx *= -1;
hhit = 1;
}
if (coin.y < radius) {
if (coin.y < radius && gameState.perks.unbounded<2) {
coin.y = radius + (radius - coin.y);
coin.vy *= -1;
vhit = 1;
@ -1059,9 +1011,7 @@ export function gameStateTick(
const ratio =
1 -
((coin.color === "crimson" || coin.color === "LightSkyBlue"
? 3
: gameState.perks.viscosity) *
( gameState.perks.viscosity *
0.03 +
0.005) *
frames;
@ -1082,7 +1032,7 @@ export function gameStateTick(
gameState.perks.helium > 0 &&
Math.abs(coin.x - gameState.puckPosition) * 2 >
gameState.puckWidth + coin.size;
coin.vy += frames * coin.weight * 0.8 * (flip ? -1 : 1);
coin.vy += frames * coin.weight * 0.8 * (flip ? -gameState.perks.helium : 1);
if (flip && !isOptionOn("basic") && Math.random() < 0.1) {
makeParticle(
gameState,
@ -1098,20 +1048,6 @@ export function gameStateTick(
}
}
if (coin.color === "crimson" && !isOptionOn("basic")) {
const angle = Math.random() * Math.PI * 2;
makeParticle(
gameState,
coin.x,
coin.y,
Math.cos(angle) * gameState.baseSpeed * 2,
Math.sin(angle) * gameState.baseSpeed * 2,
"red",
true,
5,
250,
);
}
const speed = (Math.abs(coin.vx) + Math.abs(coin.vy)) * 10;
const hitBorder = bordersHitCheck(gameState, coin, coin.size / 2, frames);
@ -1125,20 +1061,7 @@ export function gameStateTick(
// a bit of margin to be nice , negative in case it's a negative coin
gameState.puckHeight * (coin.points ? 1 : -1)
) {
if (coin.color === "crimson") {
if (gameState.perks.extra_life && gameState.balls.length) {
justLostALife(gameState, gameState.balls[0], coin.x, coin.y);
} else {
gameOver(
t("gameOver.because_cursed_coin"),
t("gameOver.because_cursed_coin_intro"),
);
}
}
if (coin.color === "LightSkyBlue") {
gameState.puckFrozenUntil = gameState.levelTime + 500;
schedulGameSound(gameState, "freeze", coin.x, 1);
}
addToScore(gameState, coin);
destroy(gameState.coins, coinIndex);
@ -1150,7 +1073,9 @@ export function gameStateTick(
} else if (
gameState.perks.unbounded &&
(coin.x < -gameState.gameZoneWidth / 2 ||
coin.x > gameState.canvasWidth + gameState.gameZoneWidth / 2)
coin.x > gameState.canvasWidth + gameState.gameZoneWidth / 2
|| coin.y < -gameState.gameZoneWidth
)
) {
// Out of bound on sides
destroy(gameState.coins, coinIndex);
@ -1162,11 +1087,11 @@ export function gameStateTick(
gameState.bricks[hitBrick] &&
coin.color !== gameState.bricks[hitBrick] &&
gameState.bricks[hitBrick] !== "black" &&
!coin.coloredABrick
coin.metamorphosisPoints
) {
// Not using setbrick because we don't want to reset HP
gameState.bricks[hitBrick] = coin.color;
coin.coloredABrick = true;
coin.metamorphosisPoints --;
schedulGameSound(gameState, "colorChange", coin.x, 0.3);
}
@ -1393,16 +1318,14 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
ball.vx +=
((gameState.puckPosition - ball.x) / 1000) *
delta *
gameState.perks.telekinesis *
interferenceFactor(gameState);
gameState.perks.telekinesis
}
if (isYoyoActive(gameState, ball)) {
speedLimitDampener += 3;
ball.vx +=
((gameState.puckPosition - ball.x) / 1000) *
delta *
gameState.perks.yoyo *
interferenceFactor(gameState);
gameState.perks.yoyo
}
if (
ball.vx * ball.vx + ball.vy * ball.vy <
@ -1606,9 +1529,16 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
const lostOnSides =
(gameState.perks.unbounded && ball.x < -gameState.gameZoneWidth / 2) ||
ball.x > gameState.canvasWidth + gameState.gameZoneWidth / 2;
const lostInTheSky = (gameState.perks.unbounded>1 &&
ball.y < -gameState.gameZoneWidth / 2
)
if (
gameState.running &&
(ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 || lostOnSides)
(ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 || lostOnSides
||lostInTheSky
)
) {
ball.destroyed = true;
gameState.runStatistics.balls_lost++;
@ -1766,21 +1696,7 @@ function makeCoin(
points = 1,
) {
let weight = 0.8 + Math.random() * 0.2 + Math.min(2, points * 0.01);
if (
y < (gameState.gameZoneWidth * 2) / 3 &&
gameState.debuffs.deadly_coins * points > Math.random() * 10000
) {
points = 0;
color = "crimson";
vx = 0;
vy = 0;
schedulGameSound(gameState, "void", x, 0.5);
weight = 1;
} else if (gameState.debuffs.frozen_coins * points > Math.random() * 10000) {
color = "LightSkyBlue";
schedulGameSound(gameState, "freeze", x, 0.5);
weight = 1;
}
append(gameState.coins, (p: Partial<Coin>) => {
p.x = x;
p.y = y;
@ -1797,16 +1713,10 @@ function makeCoin(
p.sa = Math.random() - 0.5;
p.points = points;
p.weight = weight;
p.metamorphosisPoints=gameState.perks.metamorphosis
});
}
export function interferenceFactor(gameState: GameState) {
if (!gameState.debuffs.interference) return 1;
const cycleLength = (7 + gameState.debuffs.interference) * 1000;
const position = gameState.levelTime % cycleLength;
return position > 7000 ? -1 : 1;
}
function makeParticle(
gameState: GameState,
x: number,

View file

@ -1,7 +1,6 @@
import { Ball, GameState, PerkId, PerksMap } from "./types";
import { icons, upgrades } from "./loadGameData";
import { t } from "./i18n/i18n";
import { debuffs } from "./debuffs";
export function getMajorityValue(arr: string[]): string {
const count: { [k: string]: number } = {};
@ -75,20 +74,6 @@ export function pickedUpgradesHTMl(gameState: GameState) {
return ` <p>${t("score_panel.upgrades_picked")}</p> <p>${list}</p>`;
}
export function debuffsHTMl(gameState: GameState): string {
const banned = upgrades
.filter((u) => gameState.bannedPerks[u.id])
.map((u) => u.name)
.join(", ");
let list = debuffs
.filter((d) => gameState.debuffs[d.id])
.map((d) => d.name(gameState.debuffs[d.id], banned))
.join(" ");
if (!list) return "";
return `<p>${t("score_panel.bebuffs_list")} ${list}</p>`;
}
export function levelsListHTMl(gameState: GameState) {
if (!gameState.perks.clairvoyant) return "";
let list = "";
@ -204,3 +189,8 @@ export function countBricksBelow(gameState: GameState, index: number) {
}
return count;
}
export function comboKeepingRate(level:number){
if(level<=0) return 0
return 1-1/(1+level)*1.5
}

View file

@ -84,199 +84,9 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>debuffs</name>
<children>
<folder_node>
<name>banned</name>
<children>
<concept_node>
<name>description</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>deadly_coins</name>
<children>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>fragility</name>
<children>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>frozen_coins</name>
<children>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>interference</name>
<children>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>more_bombs</name>
<children>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>sturdiness</name>
<children>
<concept_node>
<name>help</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
</children>
</folder_node>
<folder_node>
<name>gameOver</name>
<children>
<concept_node>
<name>because_cursed_coin</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>because_cursed_coin_intro</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>cumulative_total</name>
<description/>
@ -2083,7 +1893,7 @@
<name>score_panel</name>
<children>
<concept_node>
<name>bebuffs_list</name>
<name>banned</name>
<description/>
<comment/>
<translations>
@ -3980,21 +3790,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>help_plural</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>true</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>name</name>
<description/>
@ -4640,21 +4435,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>help_plural</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>true</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>name</name>
<description/>
@ -4870,6 +4650,21 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>help_no_ceiling</name>
<description/>
<comment/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>true</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>name</name>
<description/>

View file

@ -3,16 +3,6 @@
"confirmRestart.text": "You're about to start a new run, is that really what you wanted ?",
"confirmRestart.title": "Start a new run ?",
"confirmRestart.yes": "Restart game",
"debuffs.banned.description": "{{lvl}} banned perk(s) : {{banned}}.",
"debuffs.banned.help": "{{perk}} is banned for this run.",
"debuffs.deadly_coins.help": "{{lvl}} ou of 10 000 coins spawn deadly, blinking red. Game over if you catch them, unless you had an extra life to spare.",
"debuffs.fragility.help": "Explosions destroy {{percent}}% of coins and reset combo.",
"debuffs.frozen_coins.help": "{{lvl}} coins out of 10000 spawn frozen, and will lock the puck for 0.5s if caught.",
"debuffs.interference.help": "Telekinesis and yo-yo glitch for {{lvl}}s every 7s.",
"debuffs.more_bombs.help": "{{lvl}} bricks replaced by bombs.",
"debuffs.sturdiness.help": "All bricks have +{{lvl}} HP",
"gameOver.because_cursed_coin": "Game over",
"gameOver.because_cursed_coin_intro": "You cough a cursed coin (bright red coins) and didn't have a extra life to spare. ",
"gameOver.cumulative_total": "Your total cumulative score went from {{startTs}} to {{endTs}}.",
"gameOver.lost.summary": "You dropped the ball after catching {{score}} coins.",
"gameOver.lost.title": "Game Over",
@ -50,7 +40,7 @@
"level_up.unlocked_perk": " (Perk)",
"level_up.upgrade_perk_to_level": " lvl {{level}}",
"loop.converted_rerolls": "Your {{n}} leftover re-rolls where converted to +{{n}} base combo.",
"loop.instructions": "All your perks will be erased except one that you can pick below. Each option comes with an additional hazard will appear on all levels going forward. ",
"loop.instructions": "All perks you have now will be banned for the rest of the run, except the one that you pick below. ",
"loop.no_rerolls": "You didn't have any leftover re-rolls, so your base combo stayed the same. ",
"loop.title": "Starting loop {{loop}}",
"main_menu.basic": "Basic graphics",
@ -130,7 +120,7 @@
"sandbox.start": "Start test run",
"sandbox.title": "Sandbox mode",
"sandbox.unlocks_at": "Unlocks at total score {{score}}",
"score_panel.bebuffs_list": "De-buffs :",
"score_panel.banned": "Banned perks : {{banned}}",
"score_panel.rerolls_count": "You have accumulated {{rerolls}} rerolls",
"score_panel.test_run": "This is a test run, score is not recorded permanently",
"score_panel.title": "{{score}} points at level {{level}}/{{max}} ",
@ -143,7 +133,7 @@
"unlocks.title": "You unlocked {{percentUnlock}}% of the game.",
"unlocks.unlocks_at": "Unlocks at total score {{threshold}}.",
"upgrades.asceticism.fullHelp": "You'll need to store the coins somewhere while your combo climbs. ",
"upgrades.asceticism.help": "+1 combo / brick, com resets on coin catch",
"upgrades.asceticism.help": "+{{combo}} combo / brick, combo resets on coin catch",
"upgrades.asceticism.name": "Asceticism",
"upgrades.ball_attract_ball.fullHelp": "Balls that are more than half a screen width away will start attracting each other. \n\nThe attraction force is stronger when they are furthest away from each other.\n\nRainbow particles will fly to symbolize the attraction force. This perk is only offered if you have more than one ball already.",
"upgrades.ball_attract_ball.help": "Balls attract balls",
@ -173,7 +163,7 @@
"upgrades.coin_magnet.help_plural": "Stronger effect on the coins",
"upgrades.coin_magnet.name": "Coins magnet",
"upgrades.compound_interest.fullHelp": "Your combo will grow by one every time you break a brick, spawning more and more coin with every brick you break. \n\nBe sure however to catch every one of those coins with your puck, as any lost coin will reset your combo. \n\nOnce your combo is above the minimum, the bottom of the play area will have a red line to remind you that coins should not go there.\n\nThis perk combines with other combo perks, the combo will rise faster but reset more easily.",
"upgrades.compound_interest.help": "+1 combo per brick broken, resets on coin lost",
"upgrades.compound_interest.help": "+{{lvl}} combo per brick broken, resets on coin lost",
"upgrades.compound_interest.name": "Compound interest",
"upgrades.concave_puck.fullHelp": "Balls starts the level going straight up, and bounces with less angle.",
"upgrades.concave_puck.help": " Helps with aiming straight up",
@ -210,10 +200,10 @@
"upgrades.instant_upgrade.help": "-1 choice until run end.",
"upgrades.instant_upgrade.name": "+2 upgrades now",
"upgrades.left_is_lava.fullHelp": "Whenever you break a brick, your combo will increase by one, so you'll get one more coin from all the next bricks you break.\n\nHowever, your combo will reset as soon as your ball hits the left side . \n\nAs soon as your combo rises, the left side becomes red to remind you that you should avoid hitting them. \n\nThe effect stacks with other combo perks, combo rises faster with more upgrades but will also reset if any of the reset conditions are met.",
"upgrades.left_is_lava.help": "+1 combo per brick broken, resets on left side hit",
"upgrades.left_is_lava.help": "+{{lvl}} combo per brick broken, resets on left side hit",
"upgrades.left_is_lava.name": "Avoid left side",
"upgrades.metamorphosis.fullHelp": "With this perk, coins will be of the color of the brick they come from, and will color the first brick they touch in the same color. Coins spawn with the speed of the ball that broke them, which means you can aim a bit in the direction of the bricks you want to \"paint\".",
"upgrades.metamorphosis.help": "Coins stain the bricks they touch",
"upgrades.metamorphosis.help": "Each coins can stain {{lvl}} brick(s) with its color",
"upgrades.metamorphosis.name": "Metamorphosis",
"upgrades.multiball.fullHelp": "As soon as you drop the ball in Breakout 71, you loose. \n\nWith this perk, you get two balls, and so you can afford to lose one. \n\nThe lost balls come back on the next level. \n\nHaving more than one balls makes some further perks available, and of course clears the level faster.",
"upgrades.multiball.help": "Start every levels with {{count}} balls.",
@ -228,7 +218,7 @@
"upgrades.passive_income.help": "+{{lvl}} combo / brick, unless the puck moved in the last {{time}}s, then it resets instead",
"upgrades.passive_income.name": "Passive income",
"upgrades.picky_eater.fullHelp": "Whenever you break a brick the same color as your ball, your combo increases by one. \nIf it's a different color, the ball takes that new color, but the combo resets.\nThe bricks with the right color will get a white border. \nOnce you get a combo higher than your minimum, the bricks of the wrong color will get a red halo. \nIf you have more than one ball, they all change color whenever one of them hits a brick.",
"upgrades.picky_eater.help": "+1 combo per brick broken, resets on ball color change",
"upgrades.picky_eater.help": "+{{lvl}} combo per brick broken, resets on ball color change",
"upgrades.picky_eater.name": "Picky eater",
"upgrades.pierce.fullHelp": "The ball normally bounces as soon as it touches something. With this perk, it will continue its trajectory for up to 3 bricks broken. \nAfter that, it will bounce on the 4th brick, and you'll need to touch the puck to reset the counter.",
"upgrades.pierce.help": "Ball pierces {{count}} bricks after a puck bounce",
@ -243,12 +233,11 @@
"upgrades.reach.fullHelp": "Try to lock the ball up to earn more combo",
"upgrades.reach.help": "+{{lvl}} combo / bricks , lowest brick of a pile resets combo",
"upgrades.reach.name": "Top down",
"upgrades.respawn.fullHelp": "After breaking two or more bricks, when the ball hits the puck, the first brick will be put back in place, provided that space is free and the brick wasn't a bomb.\n\nSome particle effect will let you know where bricks will appear. Leveling this up lets you re-spawn up to 4 bricks at a time, but there should always be at least one destroyed.",
"upgrades.respawn.help": "The first brick hit of two+ will re-spawn",
"upgrades.respawn.help_plural": "More bricks can re-spawn",
"upgrades.respawn.fullHelp": "Some particle effect will let you know where bricks will appear. ",
"upgrades.respawn.help": "{{percent}} of bricks re-spawn after {{lvl}}s.",
"upgrades.respawn.name": "Re-spawn",
"upgrades.right_is_lava.fullHelp": "Whenever you break a brick, your combo will increase by one, so you'll get one more coin from all the next bricks you break.\n\nHowever, your combo will reset as soon as your ball hits the right side . \n\nAs soon as your combo rises, the right side becomes red to remind you that you should avoid hitting them\n\nThe effect stacks with other combo perks, combo rises faster with more upgrades but will also reset if any\nof the reset conditions are met.",
"upgrades.right_is_lava.help": "+1 combo per brick broken, resets on right side hit",
"upgrades.right_is_lava.help": "+{{lvl}} combo per brick broken, resets on right side hit",
"upgrades.right_is_lava.name": "Avoid right side",
"upgrades.sacrifice.fullHelp": "This might get the combo pretty high",
"upgrades.sacrifice.help": "Loosing a life clears all bricks",
@ -284,21 +273,21 @@
"upgrades.streak_shots.help": "More coins if you break many bricks at once.",
"upgrades.streak_shots.name": "Single puck hit streak",
"upgrades.sturdy_bricks.fullHelp": "With level one of this perk, the ball has a 20% chance to bounce harmlessly on bricks, \n but generates 10% more coins when it does break one. \n This +10% is not shown in the combo number. At level 4 the ball has 80% chance of bouncing and brings 40% more coins.",
"upgrades.sturdy_bricks.help": "Bricks sometimes resist hits but drop more coins.",
"upgrades.sturdy_bricks.help_plural": "Bricks resist more and drop more coins",
"upgrades.sturdy_bricks.help": "+{{lvl}} bricks HP, +{{percent}}% coins spawned when broken",
"upgrades.sturdy_bricks.name": "Sturdy bricks",
"upgrades.telekinesis.fullHelp": "Right after the ball hits your puck, you'll be able to direct it left and right by moving your puck. \n\n\nThe effect stops when the ball hits a brick and resets the next time it touches the puck. It also does nothing when the ball is going downward after bouncing at the top.",
"upgrades.telekinesis.help": "Puck controls the ball's trajectory",
"upgrades.telekinesis.help_plural": "Stronger effect on the ball",
"upgrades.telekinesis.name": "Telekinesis",
"upgrades.top_is_lava.fullHelp": "Whenever you break a brick, your combo will increase by one. However, your combo will reset as soon as your ball hit the top of the screen. \n\nWhen your combo is above the minimum, a red bar will appear at the top to remind you that you should avoid hitting it. \n\nThe effect stacks with other combo perks.",
"upgrades.top_is_lava.help": "More coins if you don't touch the top.",
"upgrades.top_is_lava.help": "+{{lvl}} combo per brick, reset when the top is hit",
"upgrades.top_is_lava.name": "Sky is the limit",
"upgrades.trampoline.fullHelp": "One of the rare combo upgrades that don't add a reset condition",
"upgrades.trampoline.help": "+{{lvl}} combo per puck bounce,-{{lvl}} combo per ceiling bounce",
"upgrades.trampoline.name": "Trampoline",
"upgrades.unbounded.fullHelp": "I hope you've found a way to keep your ball on screen",
"upgrades.unbounded.help": "+1 combo per brick, no more sides to keep the ball in game, danger",
"upgrades.unbounded.help": "+{{lvl}} combo per brick, no more sides to keep the ball in game, danger",
"upgrades.unbounded.help_no_ceiling": "+{{lvl}} combo per brick, no more sides or ceiling",
"upgrades.unbounded.name": "Unbounded",
"upgrades.viscosity.fullHelp": "Coins normally accelerate with gravity and explosions to pretty high speeds. \n\nThis perk constantly makes them slow down, as if they were in some sort of viscous liquid. \n\nThis makes catching them easier, and combines nicely with perks that influence the coin's movement.",
"upgrades.viscosity.help": "Slower coin fall",

View file

@ -3,16 +3,6 @@
"confirmRestart.text": "Vous êtes sur le point de commencer une nouvelle partie, est-ce vraiment ce que vous vouliez ?",
"confirmRestart.title": "Démarrer une nouvelle partie ?",
"confirmRestart.yes": "Commencer une nouvelle partie",
"debuffs.banned.description": "{{lvl}} amélioration(s) bannie(s) : {{banned}}.",
"debuffs.banned.help": "{{perk}} est banni pour cette course.",
"debuffs.deadly_coins.help": "{{lvl}} pièces sur 10000 apparaissent maudites et clignotent en rouge. La partie est terminée si vous les attrapez, sauf si vous avez une vie en stock.",
"debuffs.fragility.help": "Les explosions détruisent {{percent}}% des pièces et réinitialisent le combo.",
"debuffs.frozen_coins.help": "{{lvl}} pièces sur 10000 apparaît gelée, et glace le palet pendant 0.5 si vous l'attrapez. ",
"debuffs.interference.help": "Télékinésie et problème de yo-yo pendant {{lvl}}s toutes les 7 s.",
"debuffs.more_bombs.help": "{{lvl}} briques remplacées par des bombes.",
"debuffs.sturdiness.help": "Toutes les briques résistent à +{{lvl}} chocs",
"gameOver.because_cursed_coin": "Jeu terminé",
"gameOver.because_cursed_coin_intro": "Vous avez craché une pièce maudite (pièces rouge vif) et vous n'aviez pas de vie supplémentaire à revendre.",
"gameOver.cumulative_total": "Votre score total cumulé est passé de {{startTs}} à {{endTs}}.",
"gameOver.lost.summary": "Vous avez fait tomber la balle après avoir attrapé {{score}} pièces.",
"gameOver.lost.title": "Balle perdue",
@ -50,9 +40,9 @@
"level_up.unlocked_perk": " (Amélioration)",
"level_up.upgrade_perk_to_level": " niveau {{level}}",
"loop.converted_rerolls": "Vos {{n}} relances restantes ont été converties en +{{n}} combo de base.",
"loop.instructions": "Tous vos avantages seront supprimés, sauf un que vous pouvez choisir ci-dessous. Chaque option comporte un danger supplémentaire qui apparaîtra à tous les niveaux.",
"loop.no_rerolls": "Vous n'aviez plus de relances, donc votre combo de base est resté le même.",
"loop.title": "Boucle de départ {{loop}}",
"loop.instructions": "Tous vos avantages seront bannis pour la suite de la partie, sauf celui que vous choisirez ci-dessous.",
"loop.no_rerolls": "Vous n'aviez plus de re-rolls, donc votre combo de base est resté le même.",
"loop.title": "Début de la boucle n°{{loop}}",
"main_menu.basic": "Graphismes simplifiés",
"main_menu.basic_help": "Meilleures performances.",
"main_menu.colorful_coins": "Pièces colorées",
@ -130,7 +120,7 @@
"sandbox.start": "Démarrer la partie de test",
"sandbox.title": "Mode bac à sable",
"sandbox.unlocks_at": "Déverrouillé à partir d'un score total de {{score}}",
"score_panel.bebuffs_list": "Handicapes : ",
"score_panel.banned": "Améliorations bannies : {{banned}}",
"score_panel.rerolls_count": "Vous avez accumulé {{rerolls}} rerolls",
"score_panel.test_run": "Il s'agit d'une partie d'essai, le score n'est pas enregistré.",
"score_panel.title": "{{score}} points au niveau {{level}}/{{max}} ",
@ -143,7 +133,7 @@
"unlocks.title": "Vous avez débloqué {{percentUnlock}}% du jeu.",
"unlocks.unlocks_at": "Déverrouillé au score total {{threshold}}.",
"upgrades.asceticism.fullHelp": "Il faudra trouver un moyen de stocker les pièces pendant que le combo grandis. ",
"upgrades.asceticism.help": "+1 combo par brique cassée, RAZ quand une pièce est attrapée",
"upgrades.asceticism.help": "+{{combo}} combo par brique cassée, RAZ quand une pièce est attrapée",
"upgrades.asceticism.name": "Ascétisme",
"upgrades.ball_attract_ball.fullHelp": "Les balles qui sont éloignées de plus d'une demi-largeur d'écran commencent à s'attirer. La force d'attraction est plus forte lorsque les balles sont plus éloignées l'une de l'autre. Des particules arc-en-ciel voleront pour symboliser la force d'attraction. Cet avantage n'est offert que si vous avez déjà plus d'une balle en jeu.",
"upgrades.ball_attract_ball.help": "Les balles attirent les balles",
@ -173,7 +163,7 @@
"upgrades.coin_magnet.help_plural": "Effet plus marqué sur les pièces",
"upgrades.coin_magnet.name": "Aimant pour pièces",
"upgrades.compound_interest.fullHelp": "Votre combo augmentera d'une unité à chaque fois que vous casserez une brique, générant de plus en plus de pièces à chaque fois que vous casserez une brique. Veillez cependant à attraper chacune de ces pièces avec votre palet, car toute pièce perdue remettra votre combo à zéro. \n \nSi votre combinaison est supérieure au minimum, une ligne rouge s'affichera au bas de la zone de jeu pour vous le rappeler que les pièces ne doivent pas aller à cet endroit.\n\nCet avantage se combine avec d'autres avantages de combo, le combo augmentera plus rapidement mais se réinitialisera plus souvent.",
"upgrades.compound_interest.help": "+1 combo par brique cassée, remise à zéro quand une pièce est perdu",
"upgrades.compound_interest.help": "+{{lvl}} combo par brique cassée, remise à zéro quand une pièce est perdu",
"upgrades.compound_interest.name": "Intérêts",
"upgrades.concave_puck.fullHelp": " Les balles démarrent verticalement en début de niveau, et rebondi sur le palet de manière plus verticale et inversée.",
"upgrades.concave_puck.help": "Aide à éviter les bords.",
@ -210,10 +200,10 @@
"upgrades.instant_upgrade.help": "-1 choix jusqu'à la fin de la course.",
"upgrades.instant_upgrade.name": "+2 améliorations maintenant",
"upgrades.left_is_lava.fullHelp": "Chaque fois que vous cassez une brique, votre combo augmente d'une unité, ce qui vous permet d'obtenir une pièce de plus à chaque fois que vous cassez une brique.\n\nCependant, votre combinaison se réinitialise dès que votre balle touche le côté gauche.\n\nDès que votre combo augmente, le côté gauche devient rouge pour vous rappeler que vous devez éviter de le frapper.\n\nL'effet se cumule avec d'autres avantages de combo, le combo augmente plus rapidement avec plus d'améliorations, mais il se réinitialise également si l'une ou l'autre des conditions de réinitialisation est remplie. ",
"upgrades.left_is_lava.help": "Plus de pièces si vous ne touchez pas le côté gauche.",
"upgrades.left_is_lava.help": "+{{lvl}} combo par brique, RAZ en touchant le bord gauche",
"upgrades.left_is_lava.name": "Éviter le côté gauche",
"upgrades.metamorphosis.fullHelp": "Avec cette amélioration, les pièces seront de la couleur de la brique d'où elles proviennent et coloreront la première brique qu'elles toucheront. \n\nLes pièces apparaissent à la vitesse de la balle qui les a cassées, ce qui signifie que vous pouvez viser un peu dans la direction des briques que vous voulez \"peindre\".",
"upgrades.metamorphosis.help": "Les pièces de monnaie tachent les briques qu'elles touchent",
"upgrades.metamorphosis.help": "Chaque pièces peut tacher {{lvl}} brique(s) avec sa couleur",
"upgrades.metamorphosis.name": "Métamorphose",
"upgrades.multiball.fullHelp": "Dès que vous laissez tomber la balle dans Breakout 71, vous perdez. \n\nAvec cet avantage, vous obtenez deux balles, et vous pouvez donc vous permettre d'en perdre une.\n\nLes balles perdues reviennent au niveau suivant. \n\nLe fait d'avoir plus d'une balle permet d'obtenir d'autres avantages et, bien sûr, de franchir le niveau plus rapidement.",
"upgrades.multiball.help": "Chaque niveau commence avec {{count}} balles.",
@ -228,7 +218,7 @@
"upgrades.passive_income.help": "+{{lvl}} combo / brique, sauf si le palet à bougé dans les {{time}} dernières secondes, RAZ dans ce cas",
"upgrades.passive_income.name": "Revenu passif",
"upgrades.picky_eater.fullHelp": "Chaque fois que vous cassez une brique de la même couleur que votre balle, votre combo augmente d'une unité.\n\nS'il s'agit d'une couleur différente, la balle adopte cette nouvelle couleur, mais la combinaison est réinitialisée.\n\nLes briques de la mauvaise couleur sont entourées en rouge.\n\nSi vous avez plus d'une balle, elles changent toutes de couleur lorsque l'une d'entre elles touche une brique.",
"upgrades.picky_eater.help": "Plus de pièces si vous cassez les briques couleur par couleur.",
"upgrades.picky_eater.help": "+{{lvl}} combo par brique cassée la couleur de la balle, RAZ sinon",
"upgrades.picky_eater.name": "Mangeur par couleur",
"upgrades.pierce.fullHelp": "Normalement , la balle rebondit dès qu'elle touche une brique. Avec cette caractéristique, elle continuera sa trajectoire jusqu'à 3 briques cassées.\n\nAprès cela, elle rebondira sur la quatrième brique et vous devez toucher le palet pour remettre le compteur à zéro.",
"upgrades.pierce.help": "La balle perce {{count}} briques après chaque rebond sur le palet",
@ -243,12 +233,11 @@
"upgrades.reach.fullHelp": "Essayez de bloquer la balle au dessus des briques pour plus de combo",
"upgrades.reach.help": "+{{lvl}} combo / brique, la plus basse d'une colonne RAZ le combo",
"upgrades.reach.name": "Attaque aérienne",
"upgrades.respawn.fullHelp": "Après avoir cassé deux briques ou plus, lorsque la balle touche le palet, la première brique est remise en place, à condition que l'espace soit libre et que la brique ne soit pas une bombe.\n\nDes effets de particules vous indiqueront où les briques apparaîtront. \n\nEn montant en niveau, vous pouvez faire réapparaître jusqu'à 4 briques à la fois, mais il doit toujours y en avoir au moins une qui reste détruite.",
"upgrades.respawn.help": "Certaines briques réapparaissent après avoir été détruites.",
"upgrades.respawn.help_plural": "Plus de briques peuvent réapparaître",
"upgrades.respawn.fullHelp": "Des effets de particules vous indiqueront où les briques apparaîtront. ",
"upgrades.respawn.help": "{{percent}} des briques réapparaissent après {{lvl}}s.",
"upgrades.respawn.name": "Réapparition ",
"upgrades.right_is_lava.fullHelp": "Chaque fois que vous cassez une brique, votre combo augmente d'une unité, ce qui vous permet d'obtenir une pièce de plus à chaque fois que vous cassez les briques suivantes.\n\nCependant, votre combinaison se réinitialise dès que votre balle touche le côté droit de la zone de jeu.\n\nDès que votre combo augmente, le côté droit devient rouge pour vous rappeler que vous devez éviter de le frapper.\n\nL'effet se cumule avec d'autres avantages de combo, le combo augmente plus rapidement avec plus d'améliorations, mais il se réinitialise également si l'une des conditions de réinitialisation est remplie.",
"upgrades.right_is_lava.help": "Plus de pièces si vous ne touchez pas le côté droit.",
"upgrades.right_is_lava.help": "+{{lvl}} combo par brique, RAZ en cas de choc avec le coté droit",
"upgrades.right_is_lava.name": "Éviter le côté droit",
"upgrades.sacrifice.fullHelp": "Le combo pourrait monter assez haut ",
"upgrades.sacrifice.help": "Perdre une vie détruit toutes les briques",
@ -284,21 +273,21 @@
"upgrades.streak_shots.help": "Plus de pièces si vous cassez plusieurs briques à la fois.",
"upgrades.streak_shots.name": "Séquence de destruction",
"upgrades.sturdy_bricks.fullHelp": "Avec le niveau 1 de cette compétence, la balle a 20 % de chances de rebondir sans casser les briques, mais génère 10% de pièces en plus lorsqu'elle en casse une.\n\nCe +10% n'est pas indiqué dans le nombre de combos. Au niveau 4, la balle a 80 % de chances de rebondir et rapporte 40 % de pièces en plus.",
"upgrades.sturdy_bricks.help": "Les briques résistent parfois aux coups mais font tomber plus de pièces.",
"upgrades.sturdy_bricks.help_plural": "Les briques résistent davantage et font tomber plus de pièces",
"upgrades.sturdy_bricks.help": "+{{lvl}} points de vie des briques, +{{percent}}% pièces quand elles sont détruites",
"upgrades.sturdy_bricks.name": "Briques solides",
"upgrades.telekinesis.fullHelp": "Dès que la balle touche votre palet, vous pouvez la diriger vers la gauche ou la droite en déplaçant votre palet.\n\nL'effet s'arrête lorsque la balle touche une brique et se réinitialise la prochaine fois qu'elle touche le palet. Il ne fait rien non plus lorsque la balle descend après avoir rebondi au sommet.",
"upgrades.telekinesis.help": "Contrôler la trajectoire de la balle",
"upgrades.telekinesis.help_plural": "Effet plus fort sur la balle",
"upgrades.telekinesis.name": "Télékinésie",
"upgrades.top_is_lava.fullHelp": "Chaque fois que vous cassez une brique, votre combo augmente d'une unité. Cependant, votre combo sera réinitialisé dès que votre balle atteindra le haut de l'écran.\n\nLorsque votre combo est supérieur au minimum, une barre rouge apparaît en haut de l'écran pour vous rappeler que vous devez éviter de la frapper.\n\nCet effet s'ajoute aux autres avantages du combo.",
"upgrades.top_is_lava.help": "Plus de pièces si vous ne touchez pas le haut de la zone de jeu",
"upgrades.top_is_lava.help": "+{{lvl}} combo par brique, RAZ en cas de rebond au plafond",
"upgrades.top_is_lava.name": "Icare ",
"upgrades.trampoline.fullHelp": "Une des rares améliorations à ne pas avoir de condition de remise à zéro",
"upgrades.trampoline.help": "+{{lvl}} combo à chaque rebond d'une balle sur le palet,-{{lvl}} combo à chaque rebond au plafond",
"upgrades.trampoline.name": "Trampoline",
"upgrades.unbounded.fullHelp": "J'espère que vous avez prévu un moyen de récupérer vos balles",
"upgrades.unbounded.help": "+1 combo par brique, plus de cotés pour garder la balle en jeu, danger",
"upgrades.unbounded.help": "+{{lvl}} combo par brique, plus de cotés pour garder la balle en jeu, danger",
"upgrades.unbounded.help_no_ceiling": "+{{lvl}} combo par brique, plus de cotés ou de plafond",
"upgrades.unbounded.name": "Libérée, délivrée",
"upgrades.viscosity.fullHelp": "Les pièces accélèrent normalement avec la gravité et les explosions pour atteindre des vitesses assez élevées. \n\nCette compétence les ralentit constamment, comme si elles se trouvaient dans une sorte de liquide visqueux.\n\nCela permet de les attraper plus facilement et se combine bien avec les améliorations qui influencent le mouvement de la pièce.",
"upgrades.viscosity.help": "Chute plus lente des pièces",

View file

@ -1,4 +1,4 @@
import { DebuffsMap, GameState, RunParams } from "./types";
import { GameState, RunParams } from "./types";
import { getTotalScore } from "./settings";
import { allLevels, upgrades } from "./loadGameData";
import {
@ -9,7 +9,6 @@ import {
} from "./game_utils";
import { dontOfferTooSoon, resetBalls } from "./gameStateMutators";
import { isOptionOn } from "./options";
import { debuffs } from "./debuffs";
export function getRunLevels(totalScoreAtRunStart: number, params: RunParams) {
const firstLevel = params?.level
@ -41,7 +40,6 @@ export function newGameState(params: RunParams): GameState {
upgradesOfferedFor: -1,
perks,
bannedPerks: makeEmptyPerksMap(upgrades),
debuffs: { ...emptyDebuffsMap(), ...(params?.debuffs || {}) },
puckWidth: 200,
baseSpeed: 12,
combo: 1,
@ -51,7 +49,6 @@ export function newGameState(params: RunParams): GameState {
ballStickToPuck: true,
puckPosition: 400,
lastPuckPosition: 400,
desiredPuckPosition: 400,
lastPuckMove: 0,
pauseTimeout: null,
canvasWidth: 0,
@ -112,7 +109,6 @@ export function newGameState(params: RunParams): GameState {
rerolls: 0,
loop: 0,
baseCombo: 1,
puckFrozenUntil: 0,
levelsPerLoop: params?.levelsPerLoop ?? 7,
};
resetBalls(gameState);
@ -133,8 +129,4 @@ export function newGameState(params: RunParams): GameState {
return gameState;
}
export function emptyDebuffsMap(): DebuffsMap {
const map = {};
debuffs.forEach((d) => (map[d.id] = 0));
return map as DebuffsMap;
}

File diff suppressed because it is too large Load diff

19
src/types.d.ts vendored
View file

@ -1,6 +1,5 @@
import { rawUpgrades } from "./upgrades";
import { options } from "./options";
import { debuffs } from "./debuffs";
export type colorString = string;
@ -84,7 +83,7 @@ export type Coin = {
weight: number;
destroyed?: boolean;
collidedLastFrame?: boolean;
coloredABrick?: boolean;
metamorphosisPoints:number;
};
export type Ball = {
x: number;
@ -156,18 +155,6 @@ export type PerksMap = {
[k in PerkId]: number;
};
type Debuff = {
id: DebuffId;
max: number;
name: (lvl: number, banned: string) => string;
help: (lvl: number, perk: string) => string;
};
export type DebuffId = (typeof debuffs)[number]["id"];
export type DebuffsMap = {
[k in DebuffId]: number;
};
export type ReusableArray<T> = {
// All items below that index should not be destroyed
indexMin: number;
@ -213,7 +200,6 @@ export type GameState = {
// perks the user currently has
perks: PerksMap;
bannedPerks: PerksMap;
debuffs: DebuffsMap;
// Base speed of the ball in pixels/tick
baseSpeed: number;
// Score multiplier
@ -290,8 +276,6 @@ export type GameState = {
rerolls: number;
loop: number;
baseCombo: number;
puckFrozenUntil: number;
desiredPuckPosition: number;
levelsPerLoop:number;
};
@ -299,7 +283,6 @@ export type RunParams = {
level?: string;
levelToAvoid?: string;
perks?: Partial<PerksMap>;
debuffs?: Partial<DebuffsMap>;
levelsPerLoop?:number;
};
export type OptionDef = {

View file

@ -1,4 +1,5 @@
import { t } from "./i18n/i18n";
import {comboKeepingRate} from "./game_utils";
export const rawUpgrades = [
{
@ -47,7 +48,7 @@ export const rawUpgrades = [
id: "slow_down",
max: 2,
name: t("upgrades.slow_down.name"),
help: () => t("upgrades.slow_down.help"),
help: (lvl:number) => t("upgrades.slow_down.help",{ lvl }),
fullHelp: t("upgrades.slow_down.fullHelp"),
},
{
@ -82,7 +83,7 @@ export const rawUpgrades = [
max: 1,
name: t("upgrades.left_is_lava.name"),
help: () => t("upgrades.left_is_lava.help"),
help: (lvl:number) => t("upgrades.left_is_lava.help",{ lvl }),
fullHelp: t("upgrades.left_is_lava.fullHelp"),
},
{
@ -93,7 +94,7 @@ export const rawUpgrades = [
giftable: true,
max: 1,
name: t("upgrades.right_is_lava.name"),
help: () => t("upgrades.right_is_lava.help"),
help: (lvl:number) => t("upgrades.right_is_lava.help",{ lvl }),
fullHelp: t("upgrades.right_is_lava.fullHelp"),
},
{
@ -104,7 +105,7 @@ export const rawUpgrades = [
giftable: true,
max: 1,
name: t("upgrades.top_is_lava.name"),
help: () => t("upgrades.top_is_lava.help"),
help: (lvl:number) => t("upgrades.top_is_lava.help",{ lvl }),
fullHelp: t("upgrades.top_is_lava.fullHelp"),
},
{
@ -193,7 +194,7 @@ export const rawUpgrades = [
giftable: true,
max: 1,
name: t("upgrades.picky_eater.name"),
help: (lvl: number) => t("upgrades.picky_eater.help"),
help: (lvl: number) => t("upgrades.picky_eater.help",{lvl}),
fullHelp: t("upgrades.picky_eater.fullHelp"),
},
{
@ -204,7 +205,7 @@ export const rawUpgrades = [
id: "metamorphosis",
max: 1,
name: t("upgrades.metamorphosis.name"),
help: (lvl: number) => t("upgrades.metamorphosis.help"),
help: (lvl: number) => t("upgrades.metamorphosis.help",{lvl}),
fullHelp: t("upgrades.metamorphosis.fullHelp"),
},
{
@ -215,12 +216,11 @@ export const rawUpgrades = [
giftable: true,
max: 1,
name: t("upgrades.compound_interest.name"),
help: (lvl: number) => t("upgrades.compound_interest.help"),
help: (lvl: number) => t("upgrades.compound_interest.help",{lvl}),
fullHelp: t("upgrades.compound_interest.fullHelp"),
},
{
requires: "",
threshold: 7000,
id: "hot_start",
giftable: true,
@ -283,13 +283,12 @@ export const rawUpgrades = [
},
{
requires: "",
threshold: 18000,
giftable: false,
id: "soft_reset",
max: 9,
max: 3,
name: t("upgrades.soft_reset.name"),
help: (lvl: number) => t("upgrades.soft_reset.help", { percent: 10 * lvl }),
help: (lvl: number) => t("upgrades.soft_reset.help", { percent: Math.round(comboKeepingRate(lvl) * 100)}),
fullHelp: t("upgrades.soft_reset.fullHelp"),
},
{
@ -353,9 +352,10 @@ export const rawUpgrades = [
max: 4,
name: t("upgrades.sturdy_bricks.name"),
help: (lvl: number) =>
lvl == 1
? t("upgrades.sturdy_bricks.help")
: t("upgrades.sturdy_bricks.help_plural"),
// lvl == 1
t("upgrades.sturdy_bricks.help",{lvl, percent:lvl*10}),
// ?
// : t("upgrades.sturdy_bricks.help_plural"),
fullHelp: t("upgrades.sturdy_bricks.fullHelp"),
},
{
@ -367,12 +367,11 @@ export const rawUpgrades = [
max: 4,
name: t("upgrades.respawn.name"),
help: (lvl: number) =>
lvl == 1 ? t("upgrades.respawn.help") : t("upgrades.respawn.help_plural"),
t("upgrades.respawn.help",{percent:Math.floor(100*comboKeepingRate(lvl)),lvl}),
fullHelp: t("upgrades.respawn.fullHelp"),
},
{
requires: "",
threshold: 50000,
giftable: false,
id: "one_more_choice",
@ -423,7 +422,7 @@ export const rawUpgrades = [
id: "asceticism",
max: 1,
name: t("upgrades.asceticism.name"),
help: (lvl: number) => t("upgrades.asceticism.help"),
help: (lvl: number) => t("upgrades.asceticism.help",{combo:lvl*3}),
fullHelp: t("upgrades.asceticism.fullHelp"),
},
{
@ -434,7 +433,9 @@ export const rawUpgrades = [
id: "unbounded",
max: 1,
name: t("upgrades.unbounded.name"),
help: (lvl: number) => t("upgrades.unbounded.help"),
help: (lvl: number) => lvl > 1 ?
t("upgrades.unbounded.help_no_ceiling",{lvl}):
t("upgrades.unbounded.help",{lvl}),
fullHelp: t("upgrades.unbounded.fullHelp"),
},
{
@ -445,7 +446,7 @@ export const rawUpgrades = [
id: "shunt",
max: 3,
name: t("upgrades.shunt.name"),
help: (lvl: number) => t("upgrades.shunt.help", { percent: lvl * 20 }),
help: (lvl: number) => t("upgrades.shunt.help", { percent: Math.round(comboKeepingRate(lvl) * 100) }),
fullHelp: t("upgrades.shunt.fullHelp"),
},
{