This commit is contained in:
Renan LE CARO 2025-03-23 22:19:28 +01:00
parent f3790b3334
commit a3ad3686f3
11 changed files with 121 additions and 102 deletions

View file

@ -11,8 +11,8 @@ android {
applicationId = "me.lecaro.breakout" applicationId = "me.lecaro.breakout"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 29045721 versionCode = 29046079
versionName = "29045721" versionName = "29046079"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true

File diff suppressed because one or more lines are too long

12
dist/index.html vendored
View file

@ -1368,7 +1368,7 @@ const upgrades = (0, _upgrades.rawUpgrades).map((u)=>({
})); }));
},{"./data/palette.json":"ktRBU","./data/levels.json":"8JSUc","./data/version.json":"iyP6E","./upgrades":"1u3Dx","./getLevelBackground":"7OIPf","./levelIcon":"6rQoT","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"iyP6E":[function(require,module,exports,__globalThis) { },{"./data/palette.json":"ktRBU","./data/levels.json":"8JSUc","./data/version.json":"iyP6E","./upgrades":"1u3Dx","./getLevelBackground":"7OIPf","./levelIcon":"6rQoT","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"iyP6E":[function(require,module,exports,__globalThis) {
module.exports = JSON.parse("\"29045721\""); module.exports = JSON.parse("\"29046079\"");
},{}],"1u3Dx":[function(require,module,exports,__globalThis) { },{}],"1u3Dx":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
@ -2426,10 +2426,10 @@ function pickedUpgradesHTMl(gameState) {
return list; return list;
} }
function levelsListHTMl(gameState) { function levelsListHTMl(gameState) {
if (!gameState.perks.clairvoyant) return ''; if (!gameState.perks.clairvoyant) return "";
let list = ""; let list = "";
for(let i = 0; i < max_levels(gameState); i++)list += `<span style="opacity: ${i >= gameState.currentLevel ? 1 : 0.2}">${(0, _loadGameData.icons)[gameState.runLevels[i].name]}</span>`; for(let i = 0; i < max_levels(gameState); i++)list += `<span style="opacity: ${i >= gameState.currentLevel ? 1 : 0.2}">${(0, _loadGameData.icons)[gameState.runLevels[i].name]}</span>`;
return `<p>${(0, _i18N.t)('score_panel.upcoming_levels')}</p><p>${list}</p>`; return `<p>${(0, _i18N.t)("score_panel.upcoming_levels")}</p><p>${list}</p>`;
} }
function currentLevelInfo(gameState) { function currentLevelInfo(gameState) {
return gameState.runLevels[gameState.currentLevel % gameState.runLevels.length]; return gameState.runLevels[gameState.currentLevel % gameState.runLevels.length];
@ -2711,7 +2711,7 @@ function explodeBrick(gameState, index, ball, isExplosion) {
if (!color) return; if (!color) return;
if (color === "black") { if (color === "black") {
const x = (0, _gameUtils.brickCenterX)(gameState, index), y = (0, _gameUtils.brickCenterY)(gameState, index); const x = (0, _gameUtils.brickCenterX)(gameState, index), y = (0, _gameUtils.brickCenterY)(gameState, index);
setBrick(gameState, index, ''); setBrick(gameState, index, "");
explosionAt(gameState, index, x, y, ball); explosionAt(gameState, index, x, y, ball);
} else if (color) { } else if (color) {
// Even if it bounces we don't want to count that as a miss // Even if it bounces we don't want to count that as a miss
@ -2855,8 +2855,8 @@ async function setLevel(gameState, l) {
(0, _render.background).src = "data:image/svg+xml;UTF8," + lvl.svg; (0, _render.background).src = "data:image/svg+xml;UTF8," + lvl.svg;
} }
function setBrick(gameState, index, color) { function setBrick(gameState, index, color) {
gameState.bricks[index] = color || ''; gameState.bricks[index] = color || "";
gameState.brickHP[index] = color === 'black' && 1 || color && 1 + gameState.perks.sturdy_bricks || 0; gameState.brickHP[index] = color === "black" && 1 || color && 1 + gameState.perks.sturdy_bricks || 0;
} }
function rainbowColor() { function rainbowColor() {
return `hsl(${Math.round((0, _game.gameState).levelTime / 4) * 2 % 360},100%,70%)`; return `hsl(${Math.round((0, _game.gameState).levelTime / 4) * 2 % 360},100%,70%)`;

View file

@ -1,5 +1,5 @@
// The version of the cache. // The version of the cache.
const VERSION = "29045721"; const VERSION = "29046079";
// The name of the cache // The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`; const CACHE_NAME = `breakout-71-${VERSION}`;

View file

@ -1 +1 @@
"29045721" "29046079"

View file

@ -14,7 +14,8 @@ import {
import { getAudioContext, playPendingSounds } from "./sounds"; import { getAudioContext, playPendingSounds } from "./sounds";
import { import {
currentLevelInfo, currentLevelInfo,
getRowColIndex, levelsListHTMl, getRowColIndex,
levelsListHTMl,
max_levels, max_levels,
pickedUpgradesHTMl, pickedUpgradesHTMl,
} from "./game_utils"; } from "./game_utils";
@ -992,7 +993,7 @@ restart(
telekinesis: 2, telekinesis: 2,
yoyo: 2, yoyo: 2,
metamorphosis: 1, metamorphosis: 1,
implosions:1 implosions: 1,
}, },
} }
: {}, : {},

View file

@ -49,7 +49,7 @@ import {
} from "./game"; } from "./game";
import { stopRecording } from "./recording"; import { stopRecording } from "./recording";
import { isOptionOn } from "./options"; import { isOptionOn } from "./options";
import {use} from "react"; import { use } from "react";
export function setMousePos(gameState: GameState, x: number) { export function setMousePos(gameState: GameState, x: number) {
// Sets the puck position, and updates the ball position if they are supposed to follow it // Sets the puck position, and updates the ball position if they are supposed to follow it
@ -98,7 +98,7 @@ export function resetBalls(gameState: GameState) {
sx: 0, sx: 0,
sy: 0, sy: 0,
piercePoints: gameState.perks.pierce*3, piercePoints: gameState.perks.pierce * 3,
hitSinceBounce: 0, hitSinceBounce: 0,
brokenSinceBounce: 0, brokenSinceBounce: 0,
hitItem: [], hitItem: [],
@ -149,15 +149,21 @@ export function normalizeGameState(gameState: GameState) {
(gameState.gameZoneWidth / 12) * (gameState.gameZoneWidth / 12) *
(3 - gameState.perks.smaller_puck + gameState.perks.bigger_puck); (3 - gameState.perks.smaller_puck + gameState.perks.bigger_puck);
let minX = gameState.perks.corner_shot && gameState.levelTime? gameState.offsetXRoundedDown - gameState.puckWidth / 2 : gameState.offsetXRoundedDown + gameState.puckWidth / 2 let minX =
gameState.perks.corner_shot && gameState.levelTime
? gameState.offsetXRoundedDown - gameState.puckWidth / 2
: gameState.offsetXRoundedDown + gameState.puckWidth / 2;
let maxX = gameState.perks.corner_shot && gameState.levelTime? gameState.offsetXRoundedDown + let maxX =
gameState.gameZoneWidthRoundedUp + gameState.perks.corner_shot && gameState.levelTime
gameState.puckWidth / 2 : gameState.offsetXRoundedDown + ? gameState.offsetXRoundedDown +
gameState.gameZoneWidthRoundedUp - gameState.gameZoneWidthRoundedUp +
gameState.puckWidth / 2 gameState.puckWidth / 2
: gameState.offsetXRoundedDown +
gameState.gameZoneWidthRoundedUp -
gameState.puckWidth / 2;
gameState.puckPosition = clamp(gameState.puckPosition,minX,maxX) gameState.puckPosition = clamp(gameState.puckPosition, minX, maxX);
if (gameState.ballStickToPuck) { if (gameState.ballStickToPuck) {
putBallsAtPuck(gameState); putBallsAtPuck(gameState);
@ -254,17 +260,9 @@ export function spawnImplosion(
count = 1; count = 1;
} }
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const dx=((Math.random() - 0.5) * gameState.brickWidth) / 2 const dx = ((Math.random() - 0.5) * gameState.brickWidth) / 2;
const dy=((Math.random() - 0.5) * gameState.brickWidth) / 2 const dy = ((Math.random() - 0.5) * gameState.brickWidth) / 2;
makeParticle( makeParticle(gameState, x - dx * 10, y - dy * 10, dx, dy, color, false);
gameState,
x -dx*10 ,
y -dy*10,
dx,
dy,
color,
false,
);
} }
} }
@ -286,8 +284,8 @@ export function explosionAt(
const i = getRowColIndex(gameState, row + dy, col + dx); const i = getRowColIndex(gameState, row + dy, col + dx);
if (gameState.bricks[i] && i !== -1) { if (gameState.bricks[i] && i !== -1) {
// Study bricks resist explosions too // Study bricks resist explosions too
gameState.brickHP[i]-- gameState.brickHP[i]--;
if (gameState.brickHP<=0) { if (gameState.brickHP <= 0) {
explodeBrick(gameState, i, ball, true); explodeBrick(gameState, i, ball, true);
} }
} }
@ -295,34 +293,34 @@ export function explosionAt(
} }
} }
const factor = gameState.perks.implosions ? -1:1 const factor = gameState.perks.implosions ? -1 : 1;
// Blow nearby coins // Blow nearby coins
forEachLiveOne(gameState.coins, (c) => { forEachLiveOne(gameState.coins, (c) => {
const dx = c.x - x; const dx = c.x - x;
const dy = c.y - y; const dy = c.y - y;
const d2 = Math.max(gameState.brickWidth, Math.abs(dx) + Math.abs(dy)); const d2 = Math.max(gameState.brickWidth, Math.abs(dx) + Math.abs(dy));
c.vx += ((dx / d2) * 10 * size) / c.weight * factor; c.vx += (((dx / d2) * 10 * size) / c.weight) * factor;
c.vy += ((dy / d2) * 10 * size) / c.weight* factor; c.vy += (((dy / d2) * 10 * size) / c.weight) * factor;
}); });
gameState.lastExplosion = Date.now(); gameState.lastExplosion = Date.now();
makeLight(gameState, x, y, "white", gameState.brickWidth * 2, 150); makeLight(gameState, x, y, "white", gameState.brickWidth * 2, 150);
if(gameState.perks.implosions){ if (gameState.perks.implosions) {
spawnImplosion( spawnImplosion(
gameState, gameState,
7 * (1 + gameState.perks.bigger_explosions), 7 * (1 + gameState.perks.bigger_explosions),
x, x,
y, y,
"white") "white",
}else{ );
} else {
spawnExplosion( spawnExplosion(
gameState, gameState,
7 * (1 + gameState.perks.bigger_explosions), 7 * (1 + gameState.perks.bigger_explosions),
x, x,
y, y,
"white", "white",
); );
} }
gameState.runStatistics.bricks_broken++; gameState.runStatistics.bricks_broken++;
@ -336,7 +334,7 @@ export function explodeBrick(
gameState: GameState, gameState: GameState,
index: number, index: number,
ball: Ball, ball: Ball,
isExplosion: boolean isExplosion: boolean,
) { ) {
const color = gameState.bricks[index]; const color = gameState.bricks[index];
if (!color) return; if (!color) return;
@ -344,7 +342,7 @@ export function explodeBrick(
if (color === "black") { if (color === "black") {
const x = brickCenterX(gameState, index), const x = brickCenterX(gameState, index),
y = brickCenterY(gameState, index); y = brickCenterY(gameState, index);
setBrick(gameState, index, '') setBrick(gameState, index, "");
explosionAt(gameState, index, x, y, ball); explosionAt(gameState, index, x, y, ball);
} else if (color) { } else if (color) {
// Even if it bounces we don't want to count that as a miss // Even if it bounces we don't want to count that as a miss
@ -353,7 +351,7 @@ export function explodeBrick(
const x = brickCenterX(gameState, index), const x = brickCenterX(gameState, index),
y = brickCenterY(gameState, index); y = brickCenterY(gameState, index);
setBrick( gameState,index,""); setBrick(gameState, index, "");
let coinsToSpawn = gameState.combo; let coinsToSpawn = gameState.combo;
if (gameState.perks.sturdy_bricks) { if (gameState.perks.sturdy_bricks) {
@ -413,11 +411,11 @@ export function explodeBrick(
gameState.perks.nbricks + gameState.perks.nbricks +
gameState.perks.unbounded; gameState.perks.unbounded;
if(gameState.perks.side_kick) { if (gameState.perks.side_kick) {
if(Math.abs(ball.vx) > Math.abs(ball.vy)){ if (Math.abs(ball.vx) > Math.abs(ball.vy)) {
gameState.combo += gameState.perks.side_kick gameState.combo += gameState.perks.side_kick;
}else { } else {
decreaseCombo(gameState, gameState.perks.side_kick, ball.x,ball.y) decreaseCombo(gameState, gameState.perks.side_kick, ball.x, ball.y);
} }
} }
@ -593,9 +591,9 @@ export async function setLevel(gameState: GameState, l: number) {
empty(gameState.particles); empty(gameState.particles);
empty(gameState.lights); empty(gameState.lights);
empty(gameState.texts); empty(gameState.texts);
gameState.bricks = [] gameState.bricks = [];
for(let i=0;i<lvl.size*lvl.size;i++){ for (let i = 0; i < lvl.size * lvl.size; i++) {
setBrick(gameState, i,lvl.bricks[i]) setBrick(gameState, i, lvl.bricks[i]);
} }
// Balls color will depend on most common brick color sometimes // Balls color will depend on most common brick color sometimes
@ -606,12 +604,14 @@ export async function setLevel(gameState: GameState, l: number) {
background.src = "data:image/svg+xml;UTF8," + lvl.svg; background.src = "data:image/svg+xml;UTF8," + lvl.svg;
} }
function setBrick(gameState:GameState, index:number, color:string){ function setBrick(gameState: GameState, index: number, color: string) {
gameState.bricks[index] = color||''; gameState.bricks[index] = color || "";
gameState.brickHP[index] = (color === 'black' && 1) ||(color && 1+gameState.perks.sturdy_bricks)||0 gameState.brickHP[index] =
(color === "black" && 1) ||
(color && 1 + gameState.perks.sturdy_bricks) ||
0;
} }
export function rainbowColor(): colorString { export function rainbowColor(): colorString {
return `hsl(${(Math.round(gameState.levelTime / 4) * 2) % 360},100%,70%)`; return `hsl(${(Math.round(gameState.levelTime / 4) * 2) % 360},100%,70%)`;
} }
@ -722,7 +722,6 @@ export function attract(gameState: GameState, a: Ball, b: Ball, power: number) {
} }
export function coinBrickHitCheck(gameState: GameState, coin: Coin) { export function coinBrickHitCheck(gameState: GameState, coin: Coin) {
// Make ball/coin bonce, and return bricks that were hit // Make ball/coin bonce, and return bricks that were hit
const radius = coin.size / 2; const radius = coin.size / 2;
const { x, y, previousX, previousY } = coin; const { x, y, previousX, previousY } = coin;
@ -734,8 +733,7 @@ export function coinBrickHitCheck(gameState: GameState, coin: Coin) {
typeof hhit == "undefined" && typeof hhit == "undefined" &&
hitsSomething(x, y, radius)) || hitsSomething(x, y, radius)) ||
undefined; undefined;
if(!gameState.perks.ghost_coins){ if (!gameState.perks.ghost_coins) {
if (typeof vhit !== "undefined" || typeof chit !== "undefined") { if (typeof vhit !== "undefined" || typeof chit !== "undefined") {
coin.y = coin.previousY; coin.y = coin.previousY;
coin.vy *= -1; coin.vy *= -1;
@ -1004,7 +1002,10 @@ export function gameStateTick(
} }
} }
if ((!gameState.perks.ghost_coins && typeof hitBrick !== "undefined") || hitBorder) { if (
(!gameState.perks.ghost_coins && typeof hitBrick !== "undefined") ||
hitBorder
) {
coin.vx *= 0.8; coin.vx *= 0.8;
coin.vy *= 0.8; coin.vy *= 0.8;
coin.sa *= 0.9; coin.sa *= 0.9;
@ -1445,11 +1446,11 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
// respawns with full hp // respawns with full hp
setBrick(gameState, index, color); setBrick(gameState, index, color);
} }
// gameState.bricks[index] = color; // gameState.bricks[index] = color;
}); });
} }
ball.hitItem = []; ball.hitItem = [];
if (!ball.hitSinceBounce && gameState.bricks.find(i=>i)) { if (!ball.hitSinceBounce && gameState.bricks.find((i) => i)) {
gameState.runStatistics.misses++; gameState.runStatistics.misses++;
if (gameState.perks.forgiving) { if (gameState.perks.forgiving) {
const loss = Math.floor( const loss = Math.floor(
@ -1475,7 +1476,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
ball.hitSinceBounce = 0; ball.hitSinceBounce = 0;
ball.brokenSinceBounce = 0; ball.brokenSinceBounce = 0;
ball.sapperUses = 0; ball.sapperUses = 0;
ball.piercePoints = gameState.perks.pierce*3; ball.piercePoints = gameState.perks.pierce * 3;
} }
const lostOnSides = const lostOnSides =
@ -1509,20 +1510,26 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
const hitBrick = vhit ?? hhit ?? chit; const hitBrick = vhit ?? hhit ?? chit;
if (typeof hitBrick !== "undefined") { if (typeof hitBrick !== "undefined") {
ball.hitSinceBounce++; ball.hitSinceBounce++;
let pierce = false; let pierce = false;
let damage= 1+(shouldPierceByColor(gameState, vhit, hhit, chit) ? gameState.perks.pierce_color :0) let damage =
1 +
(shouldPierceByColor(gameState, vhit, hhit, chit)
? gameState.perks.pierce_color
: 0);
gameState.brickHP[hitBrick]-=damage gameState.brickHP[hitBrick] -= damage;
const used = Math.min(ball.piercePoints, Math.max(1,gameState.brickHP[hitBrick])) const used = Math.min(
gameState.brickHP[hitBrick]-=used ball.piercePoints,
ball.piercePoints-=used Math.max(1, gameState.brickHP[hitBrick]),
);
gameState.brickHP[hitBrick] -= used;
ball.piercePoints -= used;
if(gameState.brickHP[hitBrick]<0){ if (gameState.brickHP[hitBrick] < 0) {
gameState.brickHP[hitBrick]=0 gameState.brickHP[hitBrick] = 0;
pierce=true pierce = true;
} }
if (typeof vhit !== "undefined" || typeof chit !== "undefined") { if (typeof vhit !== "undefined" || typeof chit !== "undefined") {
if (!pierce) { if (!pierce) {
@ -1547,14 +1554,14 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
initialBrickColor !== "black" && // don't replace a brick that bounced with sturdy_bricks initialBrickColor !== "black" && // don't replace a brick that bounced with sturdy_bricks
!gameState.bricks[hitBrick] !gameState.bricks[hitBrick]
) { ) {
setBrick(gameState, hitBrick, "black") setBrick(gameState, hitBrick, "black");
ball.sapperUses++; ball.sapperUses++;
} }
} }
} }
if (!isOptionOn("basic")) { if (!isOptionOn("basic")) {
const remainingPierce = ball.piercePoints; const remainingPierce = ball.piercePoints;
const remainingSapper = ball.sapperUses < gameState.perks.sapper; const remainingSapper = ball.sapperUses < gameState.perks.sapper;
const extraCombo = gameState.combo - 1; const extraCombo = gameState.combo - 1;
if ( if (

View file

@ -1,6 +1,6 @@
import { Ball, GameState, PerkId, PerksMap } from "./types"; import { Ball, GameState, PerkId, PerksMap } from "./types";
import { icons, upgrades } from "./loadGameData"; import { icons, upgrades } from "./loadGameData";
import {t} from "./i18n/i18n"; import { t } from "./i18n/i18n";
export function getMajorityValue(arr: string[]): string { export function getMajorityValue(arr: string[]): string {
const count: { [k: string]: number } = {}; const count: { [k: string]: number } = {};
@ -66,12 +66,12 @@ export function pickedUpgradesHTMl(gameState: GameState) {
return list; return list;
} }
export function levelsListHTMl(gameState: GameState) { export function levelsListHTMl(gameState: GameState) {
if(!gameState.perks.clairvoyant) return '' if (!gameState.perks.clairvoyant) return "";
let list = ""; let list = "";
for (let i=0;i<max_levels(gameState);i++) { for (let i = 0; i < max_levels(gameState); i++) {
list += `<span style="opacity: ${i>=gameState.currentLevel ? 1:0.2}">${icons[gameState.runLevels[i].name]}</span>` ; list += `<span style="opacity: ${i >= gameState.currentLevel ? 1 : 0.2}">${icons[gameState.runLevels[i].name]}</span>`;
} }
return `<p>${t('score_panel.upcoming_levels')}</p><p>${list}</p>`; return `<p>${t("score_panel.upcoming_levels")}</p><p>${list}</p>`;
} }
export function currentLevelInfo(gameState: GameState) { export function currentLevelInfo(gameState: GameState) {

View file

@ -303,9 +303,11 @@ export function render(gameState: GameState) {
} else { } else {
drawText( drawText(
ctx, ctx,
comboTextWidth > gameState.puckWidth ? gameState.combo.toString() : comboText, comboTextWidth > gameState.puckWidth
? gameState.combo.toString()
: comboText,
"#000", "#000",
comboTextWidth > gameState.puckWidth ? 12:20, comboTextWidth > gameState.puckWidth ? 12 : 20,
gameState.puckPosition, gameState.puckPosition,
gameState.gameZoneHeight - gameState.puckHeight / 2, gameState.gameZoneHeight - gameState.puckHeight / 2,
false, false,
@ -387,7 +389,8 @@ export function renderAllBricks() {
gameState.perks.picky_eater && gameState.perks.picky_eater &&
!isOptionOn("basic"); !isOptionOn("basic");
const clairVoyance= gameState.perks.clairvoyant && gameState.brickHP.reduce((a,b)=>a+b,0) const clairVoyance =
gameState.perks.clairvoyant && gameState.brickHP.reduce((a, b) => a + b, 0);
const newKey = const newKey =
gameState.gameZoneWidth + gameState.gameZoneWidth +
@ -400,7 +403,8 @@ export function renderAllBricks() {
gameState.ballsColor + gameState.ballsColor +
"_" + "_" +
gameState.perks.pierce_color + gameState.perks.pierce_color +
"_"+ clairVoyance; "_" +
clairVoyance;
if (newKey !== cachedBricksRenderKey) { if (newKey !== cachedBricksRenderKey) {
cachedBricksRenderKey = newKey; cachedBricksRenderKey = newKey;
@ -429,11 +433,18 @@ export function renderAllBricks() {
redBorderOnBricksWithWrongColor) || redBorderOnBricksWithWrongColor) ||
redBecauseOfReach; redBecauseOfReach;
canctx.globalCompositeOperation = "source-over"; canctx.globalCompositeOperation = "source-over";
drawBrick(canctx, color, (redBorder && "red") || color, x, y); drawBrick(canctx, color, (redBorder && "red") || color, x, y);
if(gameState.brickHP[index]>1 && gameState.perks.clairvoyant){ if (gameState.brickHP[index] > 1 && gameState.perks.clairvoyant) {
canctx.globalCompositeOperation="destination-out" canctx.globalCompositeOperation = "destination-out";
drawText(canctx, gameState.brickHP[index].toString(), "white", gameState.puckHeight, x,y ) drawText(
canctx,
gameState.brickHP[index].toString(),
"white",
gameState.puckHeight,
x,
y,
);
} }
if (color === "black") { if (color === "black") {

View file

@ -277,7 +277,7 @@ export const rawUpgrades = [
id: "pierce_color", id: "pierce_color",
max: 4, max: 4,
name: t("upgrades.pierce_color.name"), name: t("upgrades.pierce_color.name"),
help: (lvl: number) => t("upgrades.pierce_color.help",{lvl}), help: (lvl: number) => t("upgrades.pierce_color.help", { lvl }),
fullHelp: t("upgrades.pierce_color.fullHelp"), fullHelp: t("upgrades.pierce_color.fullHelp"),
}, },
{ {
@ -594,7 +594,7 @@ export const rawUpgrades = [
id: "side_kick", id: "side_kick",
max: 3, max: 3,
name: t("upgrades.side_kick.name"), name: t("upgrades.side_kick.name"),
help: (lvl: number) => t("upgrades.side_kick.help",{lvl}), help: (lvl: number) => t("upgrades.side_kick.help", { lvl }),
fullHelp: t("upgrades.side_kick.fullHelp"), fullHelp: t("upgrades.side_kick.fullHelp"),
}, },
{ {