mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 12:15:06 -04:00
wip
This commit is contained in:
parent
8099ced71b
commit
a8e9fc6cb6
13 changed files with 2879 additions and 2783 deletions
|
@ -28,11 +28,13 @@ Some upgrades currently are not really useful
|
||||||
# Changelog
|
# Changelog
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
- bricks attract balls
|
|
||||||
- rework unbounded to just add padding around bricks
|
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- superhot: fixed particles durations and level duration
|
||||||
|
- bricks aattract coins : less powerfull
|
||||||
|
- bricks attract balls
|
||||||
|
- unbounded nerf : just adds padding around bricks, not combo add
|
||||||
- don't tell user to get -100 points to unlock level
|
- don't tell user to get -100 points to unlock level
|
||||||
- display colored coins when there's hypnosis or rainbow enabled
|
- display colored coins when there's hypnosis or rainbow enabled
|
||||||
|
|
||||||
|
|
162
dist/index.html
vendored
162
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -868,7 +868,7 @@
|
||||||
{
|
{
|
||||||
"name": "icon:unbounded",
|
"name": "icon:unbounded",
|
||||||
"size": 9,
|
"size": 9,
|
||||||
"bricks": "rrWWWWWrrrr_____rrrrtttttrrrrttt__rrrr____yrrrr_____rrrr___y_yWrr_____rrrrWWW__ry",
|
"bricks": "WWWWWWWWWW_r_r_r_WWrtttttrWW_ttttt_WWr_____rWW_______WWr___W_rWW_______WWrWWW__rW",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -1404,5 +1404,12 @@
|
||||||
"bricks": "WrrrrrrrWrWWWWWrWrWrrrWrWrWrWrWrWrWWWrWrWrrrrrWrWWWWWWWrrrrrrrrr",
|
"bricks": "WrrrrrrrWrWWWWWrWrWrrrWrWrWrWrWrWrWWWrWrWrrrrrWrWWWWWWWrrrrrrrrr",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon:bricks_attract_ball",
|
||||||
|
"size": 8,
|
||||||
|
"bricks": "llW_____ll_v________p________bll____t_ll___G____lly_____ll_r____",
|
||||||
|
"svg": null,
|
||||||
|
"color": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
52
src/game.ts
52
src/game.ts
|
@ -134,39 +134,40 @@ export function pause(playerAskedForPause: boolean) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fitSize = () => {
|
export const fitSize = (gameState:GameState) => {
|
||||||
|
if(!gameState) throw new Error("Missign game state")
|
||||||
const past_off = gameState.offsetXRoundedDown,
|
const past_off = gameState.offsetXRoundedDown,
|
||||||
past_width = gameState.gameZoneWidthRoundedUp,
|
past_width = gameState.gameZoneWidthRoundedUp,
|
||||||
past_heigh = gameState.gameZoneHeight;
|
past_heigh = gameState.gameZoneHeight;
|
||||||
|
|
||||||
const { width, height } = gameCanvas.getBoundingClientRect();
|
const width= window.innerWidth, height=window.innerHeight
|
||||||
|
|
||||||
|
console.log('fitSize',width, height)
|
||||||
gameState.canvasWidth = width;
|
gameState.canvasWidth = width;
|
||||||
gameState.canvasHeight = height;
|
gameState.canvasHeight = height;
|
||||||
gameCanvas.width = width;
|
gameCanvas.width = width;
|
||||||
gameCanvas.height = height;
|
gameCanvas.height = height;
|
||||||
// ctx.fillStyle = currentLevelInfo(gameState)?.color || "black";
|
|
||||||
// ctx.globalAlpha = 1;
|
|
||||||
// ctx.fillRect(0, 0, width, height);
|
|
||||||
backgroundCanvas.width = width;
|
backgroundCanvas.width = width;
|
||||||
backgroundCanvas.height = height;
|
backgroundCanvas.height = height;
|
||||||
|
|
||||||
haloCanvas.width = width / haloScale;
|
haloCanvas.width = width / haloScale;
|
||||||
haloCanvas.height = height / haloScale;
|
haloCanvas.height = height / haloScale;
|
||||||
|
|
||||||
gameState.gameZoneHeight = isOptionOn("mobile-mode")
|
gameState.gameZoneHeight = isOptionOn("mobile-mode")
|
||||||
? (height * 80) / 100
|
? Math.floor(height * .80) : height;
|
||||||
: height;
|
|
||||||
const baseWidth = Math.round(
|
const baseWidth = Math.round(
|
||||||
Math.min(gameState.canvasWidth, gameState.gameZoneHeight * 0.73),
|
Math.min(gameState.canvasWidth , gameState.gameZoneHeight * (0.73 )* (gameState.gridSize+gameState.perks.unbounded*2 ) / gameState.gridSize),
|
||||||
);
|
);
|
||||||
gameState.brickWidth = Math.floor(baseWidth / gameState.gridSize / 2) * 2;
|
|
||||||
|
gameState.brickWidth = Math.floor(baseWidth / (gameState.gridSize+gameState.perks.unbounded*2) / 2) * 2;
|
||||||
|
|
||||||
gameState.gameZoneWidth = gameState.brickWidth * gameState.gridSize;
|
gameState.gameZoneWidth = gameState.brickWidth * gameState.gridSize;
|
||||||
gameState.offsetX = Math.floor(
|
gameState.offsetX = Math.floor(
|
||||||
(gameState.canvasWidth - gameState.gameZoneWidth) / 2,
|
(gameState.canvasWidth - gameState.gameZoneWidth) / 2,
|
||||||
);
|
);
|
||||||
gameState.offsetXRoundedDown = gameState.offsetX;
|
// Space between left side and border
|
||||||
if (gameState.offsetX < gameState.ballSize) gameState.offsetXRoundedDown = 0;
|
gameState.offsetXRoundedDown = gameState.offsetX - gameState.perks.unbounded*gameState.brickWidth;
|
||||||
|
if (gameState.offsetX < gameState.ballSize+gameState.perks.unbounded*2*gameState.brickWidth) gameState.offsetXRoundedDown = 0;
|
||||||
gameState.gameZoneWidthRoundedUp = width - 2 * gameState.offsetXRoundedDown;
|
gameState.gameZoneWidthRoundedUp = width - 2 * gameState.offsetXRoundedDown;
|
||||||
backgroundCanvas.title = "resized";
|
backgroundCanvas.title = "resized";
|
||||||
// Ensure puck stays within bounds
|
// Ensure puck stays within bounds
|
||||||
|
@ -200,14 +201,14 @@ export const fitSize = () => {
|
||||||
`${window.innerHeight * 0.01}px`,
|
`${window.innerHeight * 0.01}px`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
window.addEventListener("resize", fitSize);
|
window.addEventListener("resize", ()=>fitSize(gameState));
|
||||||
window.addEventListener("fullscreenchange", fitSize);
|
window.addEventListener("fullscreenchange", ()=>fitSize(gameState));
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
// Sometimes, the page changes size without triggering the event (when switching to fullscreen, closing debug panel...)
|
// Sometimes, the page changes size without triggering the event (when switching to fullscreen, closing debug panel...)
|
||||||
const { width, height } = gameCanvas.getBoundingClientRect();
|
const { width, height } = gameCanvas.getBoundingClientRect();
|
||||||
if (width !== gameState.canvasWidth || height !== gameState.canvasHeight)
|
if (width !== gameState.canvasWidth || height !== gameState.canvasHeight)
|
||||||
fitSize();
|
fitSize(gameState);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
export async function openUpgradesPicker(gameState: GameState) {
|
export async function openUpgradesPicker(gameState: GameState) {
|
||||||
|
@ -416,8 +417,8 @@ export function tick() {
|
||||||
normalizeGameState(gameState);
|
normalizeGameState(gameState);
|
||||||
|
|
||||||
if (gameState.running) {
|
if (gameState.running) {
|
||||||
gameState.levelTime += timeDeltaMs;
|
gameState.levelTime += timeDeltaMs*frames;
|
||||||
gameState.runStatistics.runTime += timeDeltaMs;
|
gameState.runStatistics.runTime += timeDeltaMs*frames;
|
||||||
gameStateTick(gameState, frames);
|
gameStateTick(gameState, frames);
|
||||||
}
|
}
|
||||||
if (gameState.running || gameState.needsRender) {
|
if (gameState.running || gameState.needsRender) {
|
||||||
|
@ -599,7 +600,7 @@ async function openSettingsMenu() {
|
||||||
help: options[key].help,
|
help: options[key].help,
|
||||||
value: () => {
|
value: () => {
|
||||||
toggleOption(key);
|
toggleOption(key);
|
||||||
fitSize();
|
fitSize(gameState);
|
||||||
applyFullScreenChoice();
|
applyFullScreenChoice();
|
||||||
openSettingsMenu();
|
openSettingsMenu();
|
||||||
},
|
},
|
||||||
|
@ -978,15 +979,24 @@ document.addEventListener("keyup", async (e) => {
|
||||||
export const gameState = newGameState({});
|
export const gameState = newGameState({});
|
||||||
|
|
||||||
export function restart(params: RunParams) {
|
export function restart(params: RunParams) {
|
||||||
// fitSize();
|
|
||||||
Object.assign(gameState, newGameState(params));
|
Object.assign(gameState, newGameState(params));
|
||||||
// Recompute brick size according to level
|
// Recompute brick size according to level
|
||||||
fitSize();
|
fitSize(gameState);
|
||||||
pauseRecording();
|
pauseRecording();
|
||||||
setLevel(gameState, 0);
|
setLevel(gameState, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
restart({});
|
restart(window.location.search.includes('stress')?{
|
||||||
|
|
||||||
|
perks:{
|
||||||
|
bricks_attract_ball:2,
|
||||||
|
superhot:1,
|
||||||
|
bricks_attract_coins:3,
|
||||||
|
hot_start:3,
|
||||||
|
pierce:3,
|
||||||
|
rainbow:3
|
||||||
|
}
|
||||||
|
}:{});
|
||||||
|
|
||||||
tick();
|
tick();
|
||||||
setupTooltips();
|
setupTooltips();
|
||||||
|
|
|
@ -30,25 +30,17 @@ import {
|
||||||
telekinesisEffectRate,
|
telekinesisEffectRate,
|
||||||
yoyoEffectRate,
|
yoyoEffectRate,
|
||||||
} from "./game_utils";
|
} from "./game_utils";
|
||||||
import { t } from "./i18n/i18n";
|
import {t} from "./i18n/i18n";
|
||||||
import { icons } from "./loadGameData";
|
import {icons} from "./loadGameData";
|
||||||
|
|
||||||
import { getCurrentMaxCoins, getCurrentMaxParticles } from "./settings";
|
import {getCurrentMaxCoins, getCurrentMaxParticles} from "./settings";
|
||||||
import { background } from "./render";
|
import {background} from "./render";
|
||||||
import { gameOver } from "./gameOver";
|
import {gameOver} from "./gameOver";
|
||||||
import {
|
import {brickIndex, fitSize, gameState, hasBrick, hitsSomething, openUpgradesPicker, pause,} from "./game";
|
||||||
brickIndex,
|
import {stopRecording} from "./recording";
|
||||||
fitSize,
|
import {isOptionOn} from "./options";
|
||||||
gameState,
|
import {clamp, comboKeepingRate} from "./pure_functions";
|
||||||
hasBrick,
|
import {addToTotalScore} from "./addToTotalScore";
|
||||||
hitsSomething,
|
|
||||||
openUpgradesPicker,
|
|
||||||
pause,
|
|
||||||
} from "./game";
|
|
||||||
import { stopRecording } from "./recording";
|
|
||||||
import { isOptionOn } from "./options";
|
|
||||||
import { clamp, comboKeepingRate } from "./pure_functions";
|
|
||||||
import { addToTotalScore } from "./addToTotalScore";
|
|
||||||
|
|
||||||
export function setMousePos(gameState: GameState, x: number) {
|
export function setMousePos(gameState: GameState, x: number) {
|
||||||
gameState.puckPosition = x;
|
gameState.puckPosition = x;
|
||||||
|
@ -136,18 +128,19 @@ export function normalizeGameState(gameState: GameState) {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const corner = gameState.levelTime ? gameState.perks.corner_shot : 0;
|
|
||||||
|
const corner = (gameState.levelTime ? gameState.perks.corner_shot * gameState.puckWidth : 0) - gameState.perks.unbounded * gameState.brickWidth;
|
||||||
|
|
||||||
let minX =
|
let minX =
|
||||||
gameState.offsetXRoundedDown +
|
gameState.offsetXRoundedDown +
|
||||||
gameState.puckWidth / 2 -
|
gameState.puckWidth / 2 -
|
||||||
gameState.puckWidth * corner;
|
corner;
|
||||||
|
|
||||||
let maxX =
|
let maxX =
|
||||||
gameState.offsetXRoundedDown +
|
gameState.offsetXRoundedDown +
|
||||||
gameState.gameZoneWidthRoundedUp -
|
gameState.gameZoneWidthRoundedUp -
|
||||||
gameState.puckWidth / 2 +
|
gameState.puckWidth / 2 +
|
||||||
gameState.puckWidth * corner;
|
corner;
|
||||||
|
|
||||||
gameState.puckPosition = clamp(gameState.puckPosition, minX, maxX);
|
gameState.puckPosition = clamp(gameState.puckPosition, minX, maxX);
|
||||||
|
|
||||||
|
@ -425,7 +418,7 @@ export function explodeBrick(
|
||||||
while (coinsToSpawn > 0) {
|
while (coinsToSpawn > 0) {
|
||||||
const points = Math.min(pointsPerCoin, coinsToSpawn);
|
const points = Math.min(pointsPerCoin, coinsToSpawn);
|
||||||
if (points < 0 || isNaN(points)) {
|
if (points < 0 || isNaN(points)) {
|
||||||
console.error({ points });
|
console.error({points});
|
||||||
debugger;
|
debugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,8 +453,7 @@ export function explodeBrick(
|
||||||
gameState.perks.asceticism * 3 +
|
gameState.perks.asceticism * 3 +
|
||||||
gameState.perks.zen +
|
gameState.perks.zen +
|
||||||
gameState.perks.passive_income +
|
gameState.perks.passive_income +
|
||||||
gameState.perks.addiction +
|
gameState.perks.addiction,
|
||||||
gameState.perks.unbounded,
|
|
||||||
ball.x,
|
ball.x,
|
||||||
ball.y,
|
ball.y,
|
||||||
);
|
);
|
||||||
|
@ -683,7 +675,7 @@ export async function setLevel(gameState: GameState, l: number) {
|
||||||
const lvl = currentLevelInfo(gameState);
|
const lvl = currentLevelInfo(gameState);
|
||||||
if (lvl.size !== gameState.gridSize) {
|
if (lvl.size !== gameState.gridSize) {
|
||||||
gameState.gridSize = lvl.size;
|
gameState.gridSize = lvl.size;
|
||||||
fitSize();
|
fitSize(gameState);
|
||||||
}
|
}
|
||||||
gameState.levelLostCoins += empty(gameState.coins);
|
gameState.levelLostCoins += empty(gameState.coins);
|
||||||
empty(gameState.particles);
|
empty(gameState.particles);
|
||||||
|
@ -691,6 +683,7 @@ export async function setLevel(gameState: GameState, l: number) {
|
||||||
empty(gameState.texts);
|
empty(gameState.texts);
|
||||||
empty(gameState.respawns);
|
empty(gameState.respawns);
|
||||||
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]);
|
||||||
}
|
}
|
||||||
|
@ -845,7 +838,7 @@ 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;
|
||||||
|
|
||||||
const vhit = hitsSomething(previousX, y, radius);
|
const vhit = hitsSomething(previousX, y, radius);
|
||||||
const hhit = hitsSomething(x, previousY, radius);
|
const hhit = hitsSomething(x, previousY, radius);
|
||||||
|
@ -912,8 +905,7 @@ export function bordersHitCheck(
|
||||||
hhit = 0;
|
hhit = 0;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
coin.x < gameState.offsetXRoundedDown + radius &&
|
coin.x < gameState.offsetXRoundedDown + radius
|
||||||
!gameState.perks.unbounded
|
|
||||||
) {
|
) {
|
||||||
coin.x =
|
coin.x =
|
||||||
gameState.offsetXRoundedDown +
|
gameState.offsetXRoundedDown +
|
||||||
|
@ -922,14 +914,13 @@ export function bordersHitCheck(
|
||||||
coin.vx *= -1;
|
coin.vx *= -1;
|
||||||
hhit = 1;
|
hhit = 1;
|
||||||
}
|
}
|
||||||
if (coin.y < radius && gameState.perks.unbounded < 2) {
|
if (coin.y < radius) {
|
||||||
coin.y = radius + (radius - coin.y);
|
coin.y = radius + (radius - coin.y);
|
||||||
coin.vy *= -1;
|
coin.vy *= -1;
|
||||||
vhit = 1;
|
vhit = 1;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
coin.x > gameState.canvasWidth - gameState.offsetXRoundedDown - radius &&
|
coin.x > gameState.canvasWidth - gameState.offsetXRoundedDown - radius
|
||||||
!gameState.perks.unbounded
|
|
||||||
) {
|
) {
|
||||||
coin.x =
|
coin.x =
|
||||||
gameState.canvasWidth -
|
gameState.canvasWidth -
|
||||||
|
@ -1028,7 +1019,7 @@ export function gameStateTick(
|
||||||
} else {
|
} else {
|
||||||
gameOver(
|
gameOver(
|
||||||
t("gameOver.win.title"),
|
t("gameOver.win.title"),
|
||||||
t("gameOver.win.summary", { score: gameState.score }),
|
t("gameOver.win.summary", {score: gameState.score}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (gameState.running || gameState.levelTime) {
|
} else if (gameState.running || gameState.levelTime) {
|
||||||
|
@ -1102,32 +1093,7 @@ export function gameStateTick(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.perks.bricks_attract_coins) {
|
if (gameState.perks.bricks_attract_coins) {
|
||||||
const row = Math.floor(coin.y / gameState.brickWidth);
|
goToNearestBrick(gameState, coin, gameState.perks.bricks_attract_coins * frames, 2,false)
|
||||||
const col = Math.floor(
|
|
||||||
(coin.x - gameState.offsetX) / gameState.brickWidth,
|
|
||||||
);
|
|
||||||
|
|
||||||
const size = 2;
|
|
||||||
for (let dcol = -size; dcol < size; dcol++) {
|
|
||||||
for (let drow = -size; drow < size; drow++) {
|
|
||||||
const index = getRowColIndex(gameState, row + drow, col + dcol);
|
|
||||||
if (gameState.bricks[index]) {
|
|
||||||
const dx =
|
|
||||||
brickCenterX(gameState, index) +
|
|
||||||
(clamp(dcol, -1, 1) * gameState.brickWidth) / 2 -
|
|
||||||
coin.x;
|
|
||||||
const dy =
|
|
||||||
brickCenterY(gameState, index) +
|
|
||||||
(clamp(drow, -1, 1) * gameState.brickWidth) / 2 -
|
|
||||||
coin.y;
|
|
||||||
const d = dx * dx + dy * dy;
|
|
||||||
coin.vx +=
|
|
||||||
(dx / d) * 80 * gameState.perks.bricks_attract_coins * frames;
|
|
||||||
coin.vy +=
|
|
||||||
(dy / d) * 100 * gameState.perks.bricks_attract_coins * frames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ratio =
|
const ratio =
|
||||||
|
@ -1210,15 +1176,6 @@ export function gameStateTick(
|
||||||
) {
|
) {
|
||||||
increaseCombo(gameState, 1, coin.x, gameState.gameZoneHeight - 20);
|
increaseCombo(gameState, 1, coin.x, gameState.gameZoneHeight - 20);
|
||||||
}
|
}
|
||||||
} else if (
|
|
||||||
gameState.perks.unbounded &&
|
|
||||||
(coin.x < -gameState.gameZoneWidth / 2 ||
|
|
||||||
coin.x > gameState.canvasWidth + gameState.gameZoneWidth / 2 ||
|
|
||||||
coin.y < -gameState.gameZoneWidth)
|
|
||||||
) {
|
|
||||||
// Out of bound on sides
|
|
||||||
gameState.levelLostCoins += coin.points;
|
|
||||||
destroy(gameState.coins, coinIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hitBrick = coinBrickHitCheck(gameState, coin);
|
const hitBrick = coinBrickHitCheck(gameState, coin);
|
||||||
|
@ -1343,7 +1300,7 @@ export function gameStateTick(
|
||||||
flash.x += flash.vx * frames;
|
flash.x += flash.vx * frames;
|
||||||
flash.y += flash.vy * frames;
|
flash.y += flash.vy * frames;
|
||||||
if (!flash.ethereal) {
|
if (!flash.ethereal) {
|
||||||
flash.vy += 0.5;
|
flash.vy += 0.5 * frames;
|
||||||
if (hasBrick(brickIndex(flash.x, flash.y))) {
|
if (hasBrick(brickIndex(flash.x, flash.y))) {
|
||||||
destroy(gameState.particles, index);
|
destroy(gameState.particles, index);
|
||||||
}
|
}
|
||||||
|
@ -1450,7 +1407,7 @@ export function gameStateTick(
|
||||||
setBrick(gameState, r.index, r.color);
|
setBrick(gameState, r.index, r.color);
|
||||||
destroy(gameState.respawns, ri);
|
destroy(gameState.respawns, ri);
|
||||||
} else {
|
} else {
|
||||||
const { index, color } = r;
|
const {index, color} = r;
|
||||||
const vertical = Math.random() > 0.5;
|
const vertical = Math.random() > 0.5;
|
||||||
const dx = Math.random() > 0.5 ? 1 : -1;
|
const dx = Math.random() > 0.5 ? 1 : -1;
|
||||||
const dy = Math.random() > 0.5 ? 1 : -1;
|
const dy = Math.random() > 0.5 ? 1 : -1;
|
||||||
|
@ -1486,7 +1443,7 @@ export function gameStateTick(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
||||||
ball.previousVX = ball.vx;
|
ball.previousVX = ball.vx;
|
||||||
ball.previousVY = ball.vy;
|
ball.previousVY = ball.vy;
|
||||||
|
|
||||||
|
@ -1501,7 +1458,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
speedLimitDampener += 3;
|
speedLimitDampener += 3;
|
||||||
ball.vx +=
|
ball.vx +=
|
||||||
((gameState.puckPosition - ball.x) / 1000) *
|
((gameState.puckPosition - ball.x) / 1000) *
|
||||||
delta *
|
frames *
|
||||||
gameState.perks.telekinesis *
|
gameState.perks.telekinesis *
|
||||||
telekinesisEffectRate(gameState, ball);
|
telekinesisEffectRate(gameState, ball);
|
||||||
}
|
}
|
||||||
|
@ -1510,10 +1467,16 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
|
|
||||||
ball.vx +=
|
ball.vx +=
|
||||||
((gameState.puckPosition - ball.x) / 1000) *
|
((gameState.puckPosition - ball.x) / 1000) *
|
||||||
delta *
|
frames *
|
||||||
gameState.perks.yoyo *
|
gameState.perks.yoyo *
|
||||||
yoyoEffectRate(gameState, ball);
|
yoyoEffectRate(gameState, ball);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ball.hitSinceBounce < gameState.perks.bricks_attract_ball * 3) {
|
||||||
|
goToNearestBrick(gameState, ball, gameState.perks.bricks_attract_ball * frames * 0.2,
|
||||||
|
2 + gameState.perks.bricks_attract_ball,Math.random()<0.5*frames)
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ball.vx * ball.vx + ball.vy * ball.vy <
|
ball.vx * ball.vx + ball.vy * ball.vy <
|
||||||
gameState.baseSpeed * gameState.baseSpeed * 2
|
gameState.baseSpeed * gameState.baseSpeed * 2
|
||||||
|
@ -1565,7 +1528,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
gameState,
|
gameState,
|
||||||
ball,
|
ball,
|
||||||
gameState.ballSize / 2,
|
gameState.ballSize / 2,
|
||||||
delta,
|
frames,
|
||||||
);
|
);
|
||||||
if (borderHitCode) {
|
if (borderHitCode) {
|
||||||
if (
|
if (
|
||||||
|
@ -1673,31 +1636,21 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
ball.piercePoints = gameState.perks.pierce * 3;
|
ball.piercePoints = gameState.perks.pierce * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (
|
if (
|
||||||
gameState.running &&
|
gameState.running && (ball.y > gameState.gameZoneHeight + gameState.ballSize / 2)
|
||||||
(ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 ||
|
|
||||||
lostOnSides ||
|
|
||||||
lostInTheSky)
|
|
||||||
) {
|
) {
|
||||||
ball.destroyed = true;
|
ball.destroyed = true;
|
||||||
gameState.runStatistics.balls_lost++;
|
gameState.runStatistics.balls_lost++;
|
||||||
if (!gameState.balls.find((b) => !b.destroyed)) {
|
if (!gameState.balls.find((b) => !b.destroyed)) {
|
||||||
gameOver(
|
gameOver(
|
||||||
t("gameOver.lost.title"),
|
t("gameOver.lost.title"),
|
||||||
t("gameOver.lost.summary", { score: gameState.score }),
|
t("gameOver.lost.summary", {score: gameState.score}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const radius = gameState.ballSize / 2;
|
const radius = gameState.ballSize / 2;
|
||||||
// Make ball/coin bonce, and return bricks that were hit
|
// Make ball/coin bonce, and return bricks that were hit
|
||||||
const { x, y, previousX, previousY } = ball;
|
const {x, y, previousX, previousY} = ball;
|
||||||
|
|
||||||
const vhit = hitsSomething(previousX, y, radius);
|
const vhit = hitsSomething(previousX, y, radius);
|
||||||
const hhit = hitsSomething(x, previousY, radius);
|
const hhit = hitsSomething(x, previousY, radius);
|
||||||
|
@ -1966,7 +1919,7 @@ export function append<T>(
|
||||||
makeItem(where.list[where.indexMin]);
|
makeItem(where.list[where.indexMin]);
|
||||||
where.indexMin++;
|
where.indexMin++;
|
||||||
} else {
|
} else {
|
||||||
const p = { destroyed: false };
|
const p = {destroyed: false};
|
||||||
makeItem(p);
|
makeItem(p);
|
||||||
where.list.push(p);
|
where.list.push(p);
|
||||||
}
|
}
|
||||||
|
@ -2007,3 +1960,44 @@ export function forEachLiveOne<T>(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goToNearestBrick(gameState: GameState, coin: Ball | Coin, strength, size = 2, particle=false) {
|
||||||
|
const row = Math.floor(coin.y / gameState.brickWidth);
|
||||||
|
const col = Math.floor(
|
||||||
|
(coin.x - gameState.offsetX) / gameState.brickWidth,
|
||||||
|
);
|
||||||
|
let vx = 0, vy = 0
|
||||||
|
for (let dcol = -size; dcol < size; dcol++) {
|
||||||
|
for (let drow = -size; drow < size; drow++) {
|
||||||
|
const index = getRowColIndex(gameState, row + drow, col + dcol);
|
||||||
|
if (gameState.bricks[index]) {
|
||||||
|
const dx =
|
||||||
|
brickCenterX(gameState, index) +
|
||||||
|
clamp(-dcol, -1, 1) * gameState.brickWidth / 2 -
|
||||||
|
coin.x;
|
||||||
|
const dy =
|
||||||
|
brickCenterY(gameState, index) +
|
||||||
|
clamp(-drow, -1, 1) * gameState.brickWidth / 2 -
|
||||||
|
coin.y;
|
||||||
|
const d2 = dx * dx + dy * dy;
|
||||||
|
vx += (dx / d2) * 20
|
||||||
|
vy += (dy / d2) * 20
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
coin.vx += vx * strength
|
||||||
|
coin.vy += vy * strength
|
||||||
|
const s2 = coin.vx * coin.vx + coin.vy * coin.vy
|
||||||
|
if (s2 > gameState.baseSpeed * gameState.baseSpeed * 2) {
|
||||||
|
coin.vx *= 0.95
|
||||||
|
coin.vy *= 0.95
|
||||||
|
}
|
||||||
|
|
||||||
|
if((vx ||vy) && particle){
|
||||||
|
makeParticle(gameState, coin.x, coin.y, -vx*2,-vy*2, rainbowColor(), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -170,6 +170,9 @@
|
||||||
"upgrades.bigger_puck.name": "مجداف أكبر",
|
"upgrades.bigger_puck.name": "مجداف أكبر",
|
||||||
"upgrades.bigger_puck.tooltip": "احصل على المزيد من العملات المعدنية بسهولة.",
|
"upgrades.bigger_puck.tooltip": "احصل على المزيد من العملات المعدنية بسهولة.",
|
||||||
"upgrades.bigger_puck.verbose_description": "يجعل المضرب الأكبر من السهل عدم تفويت الكرة والتقاط المزيد من العملات المعدنية، كما يساعد أيضًا على تحديد زاوية الارتدادات بدقة (تعتمد زاوية الكرة فقط على المكان الذي تصطدم فيه بالمضرب).",
|
"upgrades.bigger_puck.verbose_description": "يجعل المضرب الأكبر من السهل عدم تفويت الكرة والتقاط المزيد من العملات المعدنية، كما يساعد أيضًا على تحديد زاوية الارتدادات بدقة (تعتمد زاوية الكرة فقط على المكان الذي تصطدم فيه بالمضرب).",
|
||||||
|
"upgrades.bricks_attract_ball.name": "الطوب يجذب الكرات",
|
||||||
|
"upgrades.bricks_attract_ball.tooltip": "تتجه الكرة نحو أول {{count}} من الطوب التي ستصطدم بها.",
|
||||||
|
"upgrades.bricks_attract_ball.verbose_description": "يكون التأثير أقوى في المستويات الأعلى. كما أن عدد الطوب الذي يمكن أن يصيب قبل توقف التأثير يكون أكبر. ويعود التأثير إلى قوته عندما تصطدم الكرة بالقرص.",
|
||||||
"upgrades.bricks_attract_coins.name": "الطوب يجذب العملات المعدنية",
|
"upgrades.bricks_attract_coins.name": "الطوب يجذب العملات المعدنية",
|
||||||
"upgrades.bricks_attract_coins.tooltip": "يساعدهم على البقاء هناك",
|
"upgrades.bricks_attract_coins.tooltip": "يساعدهم على البقاء هناك",
|
||||||
"upgrades.bricks_attract_coins.verbose_description": "",
|
"upgrades.bricks_attract_coins.verbose_description": "",
|
||||||
|
@ -331,10 +334,9 @@
|
||||||
"upgrades.trickledown.name": "اقتصاد التسرب",
|
"upgrades.trickledown.name": "اقتصاد التسرب",
|
||||||
"upgrades.trickledown.tooltip": "تظهر العملات المعدنية في الجزء العلوي من الشاشة.",
|
"upgrades.trickledown.tooltip": "تظهر العملات المعدنية في الجزء العلوي من الشاشة.",
|
||||||
"upgrades.trickledown.verbose_description": "قد يساعدك هذا على وضع بعض العملات المعدنية جانبًا. ",
|
"upgrades.trickledown.verbose_description": "قد يساعدك هذا على وضع بعض العملات المعدنية جانبًا. ",
|
||||||
"upgrades.unbounded.help_no_ceiling": "+{{lvl}} مجموعة لكل لبنة، لا مزيد من الجوانب أو السقف",
|
|
||||||
"upgrades.unbounded.name": "غير محدود",
|
"upgrades.unbounded.name": "غير محدود",
|
||||||
"upgrades.unbounded.tooltip": "+{{lvl}} مجموعة لكل لبنة، لا مزيد من الجوانب لإبقاء الكرة في اللعبة، خطر",
|
"upgrades.unbounded.tooltip": "يضيف مساحة إلى يسار ويمين المستوى، ولكن مجدافك لا يمكنه الذهاب إلى هذا الحد.",
|
||||||
"upgrades.unbounded.verbose_description": "آمل أن تكون قد وجدت طريقة لإبقاء الكرة على الشاشة. لم تعد تُطبق عقوبات ضرب الجوانب. في المستوى ٢+، سيختفي السقف أيضًا. هذه ميزة متقدمة.",
|
"upgrades.unbounded.verbose_description": "قد يساعدك ترقية أخرى على توسيع مدى مجدافك.",
|
||||||
"upgrades.viscosity.name": "اللزوجة",
|
"upgrades.viscosity.name": "اللزوجة",
|
||||||
"upgrades.viscosity.tooltip": "انخفاض أبطأ في قيمة العملة",
|
"upgrades.viscosity.tooltip": "انخفاض أبطأ في قيمة العملة",
|
||||||
"upgrades.viscosity.verbose_description": "عادةً ما تتسارع العملات المعدنية بفعل الجاذبية والانفجارات إلى سرعات عالية جدًا.\n\nهذه الميزة تُبطئ سرعتها باستمرار، كما لو كانت في سائل لزج.\n\nهذا يُسهّل التقاطها، ويتكامل بشكل رائع مع الميزات التي تؤثر على حركة العملة.",
|
"upgrades.viscosity.verbose_description": "عادةً ما تتسارع العملات المعدنية بفعل الجاذبية والانفجارات إلى سرعات عالية جدًا.\n\nهذه الميزة تُبطئ سرعتها باستمرار، كما لو كانت في سائل لزج.\n\nهذا يُسهّل التقاطها، ويتكامل بشكل رائع مع الميزات التي تؤثر على حركة العملة.",
|
||||||
|
|
|
@ -4080,6 +4080,80 @@
|
||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>bricks_attract_ball</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>name</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>ar-LB</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>ru-RU</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>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>ru-RU</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>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>ru-RU</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>bricks_attract_coins</name>
|
<name>bricks_attract_coins</name>
|
||||||
<children>
|
<children>
|
||||||
|
@ -8041,29 +8115,6 @@
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>unbounded</name>
|
<name>unbounded</name>
|
||||||
<children>
|
<children>
|
||||||
<concept_node>
|
|
||||||
<name>help_no_ceiling</name>
|
|
||||||
<description/>
|
|
||||||
<comment/>
|
|
||||||
<translations>
|
|
||||||
<translation>
|
|
||||||
<language>ar-LB</language>
|
|
||||||
<approved>false</approved>
|
|
||||||
</translation>
|
|
||||||
<translation>
|
|
||||||
<language>en-US</language>
|
|
||||||
<approved>true</approved>
|
|
||||||
</translation>
|
|
||||||
<translation>
|
|
||||||
<language>fr-FR</language>
|
|
||||||
<approved>true</approved>
|
|
||||||
</translation>
|
|
||||||
<translation>
|
|
||||||
<language>ru-RU</language>
|
|
||||||
<approved>false</approved>
|
|
||||||
</translation>
|
|
||||||
</translations>
|
|
||||||
</concept_node>
|
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>name</name>
|
<name>name</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
@ -8102,7 +8153,7 @@
|
||||||
</translation>
|
</translation>
|
||||||
<translation>
|
<translation>
|
||||||
<language>fr-FR</language>
|
<language>fr-FR</language>
|
||||||
<approved>true</approved>
|
<approved>false</approved>
|
||||||
</translation>
|
</translation>
|
||||||
<translation>
|
<translation>
|
||||||
<language>ru-RU</language>
|
<language>ru-RU</language>
|
||||||
|
@ -8125,7 +8176,7 @@
|
||||||
</translation>
|
</translation>
|
||||||
<translation>
|
<translation>
|
||||||
<language>fr-FR</language>
|
<language>fr-FR</language>
|
||||||
<approved>true</approved>
|
<approved>false</approved>
|
||||||
</translation>
|
</translation>
|
||||||
<translation>
|
<translation>
|
||||||
<language>ru-RU</language>
|
<language>ru-RU</language>
|
||||||
|
|
|
@ -170,6 +170,9 @@
|
||||||
"upgrades.bigger_puck.name": "Bigger paddle",
|
"upgrades.bigger_puck.name": "Bigger paddle",
|
||||||
"upgrades.bigger_puck.tooltip": "Easily catch more coins.",
|
"upgrades.bigger_puck.tooltip": "Easily catch more coins.",
|
||||||
"upgrades.bigger_puck.verbose_description": "A bigger paddle makes it easier to never miss the ball and to catch more coins, and also to precisely angle the bounces (the ball's angle only depends on where it hits the paddle). ",
|
"upgrades.bigger_puck.verbose_description": "A bigger paddle makes it easier to never miss the ball and to catch more coins, and also to precisely angle the bounces (the ball's angle only depends on where it hits the paddle). ",
|
||||||
|
"upgrades.bricks_attract_ball.name": "Bricks attract balls",
|
||||||
|
"upgrades.bricks_attract_ball.tooltip": "Ball goes toward the first {{count}} bricks it will hit.",
|
||||||
|
"upgrades.bricks_attract_ball.verbose_description": "The effect is stronger at higher levels. The number of bricks that can hit before the effect stops is also higher. The effect rearms when the ball hits the puck.",
|
||||||
"upgrades.bricks_attract_coins.name": "Bricks attract coins",
|
"upgrades.bricks_attract_coins.name": "Bricks attract coins",
|
||||||
"upgrades.bricks_attract_coins.tooltip": "Helps them stay up there",
|
"upgrades.bricks_attract_coins.tooltip": "Helps them stay up there",
|
||||||
"upgrades.bricks_attract_coins.verbose_description": "",
|
"upgrades.bricks_attract_coins.verbose_description": "",
|
||||||
|
@ -331,10 +334,9 @@
|
||||||
"upgrades.trickledown.name": "Trickle down economics",
|
"upgrades.trickledown.name": "Trickle down economics",
|
||||||
"upgrades.trickledown.tooltip": "The coins appear at the top of the screen.",
|
"upgrades.trickledown.tooltip": "The coins appear at the top of the screen.",
|
||||||
"upgrades.trickledown.verbose_description": "It might help you put some coins aside.",
|
"upgrades.trickledown.verbose_description": "It might help you put some coins aside.",
|
||||||
"upgrades.unbounded.help_no_ceiling": "+{{lvl}} combo per brick, no more sides or ceiling",
|
"upgrades.unbounded.name": "Padding",
|
||||||
"upgrades.unbounded.name": "Unbounded",
|
"upgrades.unbounded.tooltip": "Adds space left and right of the level, but your paddle can't go that far. ",
|
||||||
"upgrades.unbounded.tooltip": "+{{lvl}} combo per brick, no more sides to keep the ball in game, danger",
|
"upgrades.unbounded.verbose_description": "Another upgrade might help you extends the reach of your paddle. ",
|
||||||
"upgrades.unbounded.verbose_description": "I hope you've found a way to keep your ball on screen. Penalties for hitting the sides no longer apply. At level 2+, the ceiling will also disappear. This is an advanced perk. ",
|
|
||||||
"upgrades.viscosity.name": "Viscosity",
|
"upgrades.viscosity.name": "Viscosity",
|
||||||
"upgrades.viscosity.tooltip": "Slower coin fall",
|
"upgrades.viscosity.tooltip": "Slower coin fall",
|
||||||
"upgrades.viscosity.verbose_description": "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.verbose_description": "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.",
|
||||||
|
|
|
@ -170,6 +170,9 @@
|
||||||
"upgrades.bigger_puck.name": "Raquette plus grande",
|
"upgrades.bigger_puck.name": "Raquette plus grande",
|
||||||
"upgrades.bigger_puck.tooltip": "Attrapez facilement plus de pièces.",
|
"upgrades.bigger_puck.tooltip": "Attrapez facilement plus de pièces.",
|
||||||
"upgrades.bigger_puck.verbose_description": "Une grande raquette permet de ne jamais rater la balle et d'attraper plus de pièces, ainsi que d'orienter précisément les rebonds. Cependant, une grande raquette est plus difficile à utiliser sur les côtés du niveau.",
|
"upgrades.bigger_puck.verbose_description": "Une grande raquette permet de ne jamais rater la balle et d'attraper plus de pièces, ainsi que d'orienter précisément les rebonds. Cependant, une grande raquette est plus difficile à utiliser sur les côtés du niveau.",
|
||||||
|
"upgrades.bricks_attract_ball.name": "Les briques attirent les balles",
|
||||||
|
"upgrades.bricks_attract_ball.tooltip": "La balle se dirige vers les {{count}} premières briques qu'elle touchera.",
|
||||||
|
"upgrades.bricks_attract_ball.verbose_description": "L'effet est plus fort à des niveaux plus élevés. Le nombre de briques pouvant être touchées avant que l'effet ne s'arrête est également plus élevé. L'effet se réarme lorsque la balle touche le palet.",
|
||||||
"upgrades.bricks_attract_coins.name": "Briques attirent les pièces",
|
"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.tooltip": "Aide à garder les pièces en suspension",
|
||||||
"upgrades.bricks_attract_coins.verbose_description": "",
|
"upgrades.bricks_attract_coins.verbose_description": "",
|
||||||
|
@ -331,10 +334,9 @@
|
||||||
"upgrades.trickledown.name": "Ruissellement",
|
"upgrades.trickledown.name": "Ruissellement",
|
||||||
"upgrades.trickledown.tooltip": "Les pièces apparaissent en haut de l'écran.",
|
"upgrades.trickledown.tooltip": "Les pièces apparaissent en haut de l'écran.",
|
||||||
"upgrades.trickledown.verbose_description": "Ça pourrait vous aider à mettre des pièces de coté. ",
|
"upgrades.trickledown.verbose_description": "Ça pourrait vous aider à mettre des pièces de coté. ",
|
||||||
"upgrades.unbounded.help_no_ceiling": "+{{lvl}} combo par brique, plus de cotés ou de plafond",
|
"upgrades.unbounded.name": "Besoin d'espace",
|
||||||
"upgrades.unbounded.name": "Libérée, délivrée",
|
"upgrades.unbounded.tooltip": "Plus d'espace autour des briques, mais la raquette ne peut pas aller aussi loin.",
|
||||||
"upgrades.unbounded.tooltip": "+{{lvl}} combo par brique, plus de cotés pour garder la balle en jeu, danger",
|
"upgrades.unbounded.verbose_description": "Une autre amélioration pourrait vous permettre d'étendre la portée de votre raquette.",
|
||||||
"upgrades.unbounded.verbose_description": "J'espère que vous avez trouvé un moyen de garder votre balle à l'écran. Au niveau 2+, le plafond disparaîtra également. Il s'agit d'un avantage avancé.",
|
|
||||||
"upgrades.viscosity.name": "Fluide visqueux ",
|
"upgrades.viscosity.name": "Fluide visqueux ",
|
||||||
"upgrades.viscosity.tooltip": "Chute plus lente des pièces",
|
"upgrades.viscosity.tooltip": "Chute plus lente des pièces",
|
||||||
"upgrades.viscosity.verbose_description": "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.verbose_description": "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.",
|
||||||
|
|
|
@ -170,6 +170,9 @@
|
||||||
"upgrades.bigger_puck.name": "Большое весло",
|
"upgrades.bigger_puck.name": "Большое весло",
|
||||||
"upgrades.bigger_puck.tooltip": "Легко поймать больше монет.",
|
"upgrades.bigger_puck.tooltip": "Легко поймать больше монет.",
|
||||||
"upgrades.bigger_puck.verbose_description": "Большее весло позволяет никогда не промахиваться по мячу и ловить больше монет, а также точно определять угол отскока (угол наклона мяча зависит только от того, куда он попадает при ударе о весло).",
|
"upgrades.bigger_puck.verbose_description": "Большее весло позволяет никогда не промахиваться по мячу и ловить больше монет, а также точно определять угол отскока (угол наклона мяча зависит только от того, куда он попадает при ударе о весло).",
|
||||||
|
"upgrades.bricks_attract_ball.name": "Кирпичи притягивают мячи",
|
||||||
|
"upgrades.bricks_attract_ball.tooltip": "Мяч летит к первым {{count}} кирпичам, которых он коснется.",
|
||||||
|
"upgrades.bricks_attract_ball.verbose_description": "Эффект сильнее на более высоких уровнях. Количество кирпичей, которые могут ударить до того, как эффект прекратится, также больше. Эффект возобновляется, когда мяч касается шайбы.",
|
||||||
"upgrades.bricks_attract_coins.name": "Кирпичи притягивают монеты",
|
"upgrades.bricks_attract_coins.name": "Кирпичи притягивают монеты",
|
||||||
"upgrades.bricks_attract_coins.tooltip": "Помогает им оставаться на вершине",
|
"upgrades.bricks_attract_coins.tooltip": "Помогает им оставаться на вершине",
|
||||||
"upgrades.bricks_attract_coins.verbose_description": "",
|
"upgrades.bricks_attract_coins.verbose_description": "",
|
||||||
|
@ -331,10 +334,9 @@
|
||||||
"upgrades.trickledown.name": "Экономика по принципу \"копеечной монеты",
|
"upgrades.trickledown.name": "Экономика по принципу \"копеечной монеты",
|
||||||
"upgrades.trickledown.tooltip": "Монеты появляются в верхней части экрана.",
|
"upgrades.trickledown.tooltip": "Монеты появляются в верхней части экрана.",
|
||||||
"upgrades.trickledown.verbose_description": "Это может помочь вам отложить несколько монет.",
|
"upgrades.trickledown.verbose_description": "Это может помочь вам отложить несколько монет.",
|
||||||
"upgrades.unbounded.help_no_ceiling": "+{{lvl}} комбо на кирпич, не больше сторон или потолка",
|
"upgrades.unbounded.name": "Набивка",
|
||||||
"upgrades.unbounded.name": "Без ограничений",
|
"upgrades.unbounded.tooltip": "Добавляет пространство слева и справа от уровня, но ваше весло не может пройти так далеко.",
|
||||||
"upgrades.unbounded.tooltip": "+{{lvl}} комбо за кирпич, больше нет сторон, чтобы держать мяч в игре, опасность",
|
"upgrades.unbounded.verbose_description": "Еще одна модернизация может помочь вам увеличить радиус действия весла.",
|
||||||
"upgrades.unbounded.verbose_description": "Надеюсь, вы нашли способ держать мяч на экране. Штрафы за удары по бокам больше не применяются. На уровне 2+ потолок также исчезнет. Это продвинутый перк.",
|
|
||||||
"upgrades.viscosity.name": "Вязкость",
|
"upgrades.viscosity.name": "Вязкость",
|
||||||
"upgrades.viscosity.tooltip": "Медленное падение монет",
|
"upgrades.viscosity.tooltip": "Медленное падение монет",
|
||||||
"upgrades.viscosity.verbose_description": "Монеты обычно разгоняются с помощью гравитации и взрывов до довольно высоких скоростей.\n\nЭтот перк постоянно заставляет их замедляться, как будто они находятся в какой-то вязкой жидкости.\n\nЭто облегчает их поимку и отлично сочетается с перками, влияющими на движение монет.",
|
"upgrades.viscosity.verbose_description": "Монеты обычно разгоняются с помощью гравитации и взрывов до довольно высоких скоростей.\n\nЭтот перк постоянно заставляет их замедляться, как будто они находятся в какой-то вязкой жидкости.\n\nЭто облегчает их поимку и отлично сочетается с перками, влияющими на движение монет.",
|
||||||
|
|
|
@ -138,7 +138,7 @@ export function newGameState(params: RunParams): GameState {
|
||||||
rerolls: 0,
|
rerolls: 0,
|
||||||
creative:
|
creative:
|
||||||
sumOfValues(params.perks) > 1 ||
|
sumOfValues(params.perks) > 1 ||
|
||||||
(params.level && params.level !== "icon:" + randomGift),
|
(params.level && !params.level.startsWith("icon:")),
|
||||||
};
|
};
|
||||||
resetBalls(gameState);
|
resetBalls(gameState);
|
||||||
|
|
||||||
|
|
|
@ -329,11 +329,9 @@ export function render(gameState: GameState) {
|
||||||
ctx.fillStyle = gameState.puckColor;
|
ctx.fillStyle = gameState.puckColor;
|
||||||
for (let i = 0; i < gameState.perks.extra_life; i++) {
|
for (let i = 0; i < gameState.perks.extra_life; i++) {
|
||||||
ctx.fillRect(
|
ctx.fillRect(
|
||||||
gameState.perks.unbounded ? 0 : gameState.offsetXRoundedDown,
|
gameState.offsetXRoundedDown,
|
||||||
gameState.gameZoneHeight - gameState.puckHeight / 2 + 2 * i,
|
gameState.gameZoneHeight - gameState.puckHeight / 2 + 2 * i,
|
||||||
gameState.perks.unbounded
|
gameState.gameZoneWidthRoundedUp,
|
||||||
? gameState.canvasWidth
|
|
||||||
: gameState.gameZoneWidthRoundedUp,
|
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -446,43 +444,40 @@ export function render(gameState: GameState) {
|
||||||
// Borders
|
// Borders
|
||||||
|
|
||||||
ctx.globalCompositeOperation = "source-over";
|
ctx.globalCompositeOperation = "source-over";
|
||||||
ctx.globalAlpha = gameState.perks.unbounded ? 0.1 : 1;
|
ctx.globalAlpha = 1;
|
||||||
|
|
||||||
let redLeftSide =
|
let redLeftSide =
|
||||||
hasCombo &&
|
hasCombo &&
|
||||||
!gameState.perks.unbounded &&
|
|
||||||
(gameState.perks.left_is_lava || gameState.perks.trampoline);
|
(gameState.perks.left_is_lava || gameState.perks.trampoline);
|
||||||
let redRightSide =
|
let redRightSide =
|
||||||
hasCombo &&
|
hasCombo &&
|
||||||
!gameState.perks.unbounded &&
|
|
||||||
(gameState.perks.right_is_lava || gameState.perks.trampoline);
|
(gameState.perks.right_is_lava || gameState.perks.trampoline);
|
||||||
let redTop =
|
let redTop =
|
||||||
hasCombo &&
|
hasCombo &&
|
||||||
gameState.perks.unbounded <= 2 &&
|
|
||||||
(gameState.perks.top_is_lava || gameState.perks.trampoline);
|
(gameState.perks.top_is_lava || gameState.perks.trampoline);
|
||||||
|
|
||||||
|
|
||||||
if (gameState.offsetXRoundedDown) {
|
if (gameState.offsetXRoundedDown) {
|
||||||
// draw outside of gaming area to avoid capturing borders in recordings
|
// draw outside of gaming area to avoid capturing borders in recordings
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
(redLeftSide && "#FF0000") || "#FFFFFF",
|
(redLeftSide && "#FF0000") || "#FFFFFF",
|
||||||
gameState.offsetX - 1,
|
gameState.offsetXRoundedDown - 1,
|
||||||
0,
|
0,
|
||||||
gameState.offsetX - 1,
|
gameState.offsetXRoundedDown - 1,
|
||||||
height,
|
height, 1,
|
||||||
gameState.perks.unbounded ? 0.1 : 1,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
(redRightSide && "#FF0000") || "#FFFFFF",
|
(redRightSide && "#FF0000") || "#FFFFFF",
|
||||||
width - gameState.offsetX + 1,
|
width - gameState.offsetXRoundedDown + 1,
|
||||||
0,
|
0,
|
||||||
width - gameState.offsetX + 1,
|
width - gameState.offsetXRoundedDown + 1,
|
||||||
height,
|
height,
|
||||||
gameState.perks.unbounded ? 0.1 : 1,
|
1,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
|
@ -512,9 +507,9 @@ export function render(gameState: GameState) {
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
"#FF0000",
|
"#FF0000",
|
||||||
gameState.perks.unbounded ? 0 : gameState.offsetXRoundedDown,
|
gameState.offsetXRoundedDown,
|
||||||
1,
|
1,
|
||||||
gameState.perks.unbounded ? width : width - gameState.offsetXRoundedDown,
|
width - gameState.offsetXRoundedDown,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
111
src/upgrades.ts
111
src/upgrades.ts
|
@ -1,22 +1,22 @@
|
||||||
import { t } from "./i18n/i18n";
|
import {t} from "./i18n/i18n";
|
||||||
|
|
||||||
import { comboKeepingRate } from "./pure_functions";
|
import {comboKeepingRate} from "./pure_functions";
|
||||||
import {PerkId} from "./types";
|
import {PerkId} from "./types";
|
||||||
|
|
||||||
|
|
||||||
// Those perks are excluded from creative mode
|
// Those perks are excluded from creative mode
|
||||||
export const noCreative: PerkId[] = [
|
export const noCreative: PerkId[] = [
|
||||||
"extra_levels",
|
"extra_levels",
|
||||||
"shunt",
|
"shunt",
|
||||||
"one_more_choice",
|
"one_more_choice",
|
||||||
"instant_upgrade",
|
"instant_upgrade",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// Those perks are excluded from the starting perks list
|
// Those perks are excluded from the starting perks list
|
||||||
export const notStartingPerk: PerkId[] = [
|
export const notStartingPerk: PerkId[] = [
|
||||||
"instant_upgrade",
|
"instant_upgrade",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
export const rawUpgrades = [
|
export const rawUpgrades = [
|
||||||
|
@ -31,7 +31,7 @@ export const rawUpgrades = [
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
lvl === 1
|
lvl === 1
|
||||||
? t("upgrades.extra_life.tooltip")
|
? t("upgrades.extra_life.tooltip")
|
||||||
: t("upgrades.extra_life.help_plural", { lvl }),
|
: t("upgrades.extra_life.help_plural", {lvl}),
|
||||||
fullHelp: t("upgrades.extra_life.verbose_description"),
|
fullHelp: t("upgrades.extra_life.verbose_description"),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ export const rawUpgrades = [
|
||||||
max: 7,
|
max: 7,
|
||||||
name: t("upgrades.base_combo.name"),
|
name: t("upgrades.base_combo.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.base_combo.tooltip", { coins: 1 + lvl * 3 }),
|
t("upgrades.base_combo.tooltip", {coins: 1 + lvl * 3}),
|
||||||
fullHelp: t("upgrades.base_combo.verbose_description"),
|
fullHelp: t("upgrades.base_combo.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ export const rawUpgrades = [
|
||||||
id: "slow_down",
|
id: "slow_down",
|
||||||
max: 2,
|
max: 2,
|
||||||
name: t("upgrades.slow_down.name"),
|
name: t("upgrades.slow_down.name"),
|
||||||
help: (lvl: number) => t("upgrades.slow_down.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.slow_down.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.slow_down.verbose_description"),
|
fullHelp: t("upgrades.slow_down.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -92,7 +92,7 @@ export const rawUpgrades = [
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
lvl == 1
|
lvl == 1
|
||||||
? t("upgrades.skip_last.tooltip")
|
? t("upgrades.skip_last.tooltip")
|
||||||
: t("upgrades.skip_last.help_plural", { lvl }),
|
: t("upgrades.skip_last.help_plural", {lvl}),
|
||||||
fullHelp: t("upgrades.skip_last.verbose_description"),
|
fullHelp: t("upgrades.skip_last.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.streak_shots.name"),
|
name: t("upgrades.streak_shots.name"),
|
||||||
help: (lvl: number) => t("upgrades.streak_shots.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.streak_shots.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.streak_shots.verbose_description"),
|
fullHelp: t("upgrades.streak_shots.verbose_description"),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ export const rawUpgrades = [
|
||||||
max: 1,
|
max: 1,
|
||||||
|
|
||||||
name: t("upgrades.left_is_lava.name"),
|
name: t("upgrades.left_is_lava.name"),
|
||||||
help: (lvl: number) => t("upgrades.left_is_lava.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.left_is_lava.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.left_is_lava.verbose_description"),
|
fullHelp: t("upgrades.left_is_lava.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -129,7 +129,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.right_is_lava.name"),
|
name: t("upgrades.right_is_lava.name"),
|
||||||
help: (lvl: number) => t("upgrades.right_is_lava.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.right_is_lava.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.right_is_lava.verbose_description"),
|
fullHelp: t("upgrades.right_is_lava.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -141,7 +141,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.top_is_lava.name"),
|
name: t("upgrades.top_is_lava.name"),
|
||||||
help: (lvl: number) => t("upgrades.top_is_lava.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.top_is_lava.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.top_is_lava.verbose_description"),
|
fullHelp: t("upgrades.top_is_lava.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -182,7 +182,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 6,
|
max: 6,
|
||||||
name: t("upgrades.multiball.name"),
|
name: t("upgrades.multiball.name"),
|
||||||
help: (lvl: number) => t("upgrades.multiball.tooltip", { count: lvl + 1 }),
|
help: (lvl: number) => t("upgrades.multiball.tooltip", {count: lvl + 1}),
|
||||||
fullHelp: t("upgrades.multiball.verbose_description"),
|
fullHelp: t("upgrades.multiball.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -208,7 +208,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.pierce.name"),
|
name: t("upgrades.pierce.name"),
|
||||||
help: (lvl: number) => t("upgrades.pierce.tooltip", { count: 3 * lvl }),
|
help: (lvl: number) => t("upgrades.pierce.tooltip", {count: 3 * lvl}),
|
||||||
fullHelp: t("upgrades.pierce.verbose_description"),
|
fullHelp: t("upgrades.pierce.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -220,7 +220,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.picky_eater.name"),
|
name: t("upgrades.picky_eater.name"),
|
||||||
help: (lvl: number) => t("upgrades.picky_eater.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.picky_eater.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.picky_eater.verbose_description"),
|
fullHelp: t("upgrades.picky_eater.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -232,7 +232,7 @@ export const rawUpgrades = [
|
||||||
id: "metamorphosis",
|
id: "metamorphosis",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.metamorphosis.name"),
|
name: t("upgrades.metamorphosis.name"),
|
||||||
help: (lvl: number) => t("upgrades.metamorphosis.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.metamorphosis.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.metamorphosis.verbose_description"),
|
fullHelp: t("upgrades.metamorphosis.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -244,7 +244,7 @@ export const rawUpgrades = [
|
||||||
|
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.compound_interest.name"),
|
name: t("upgrades.compound_interest.name"),
|
||||||
help: (lvl: number) => t("upgrades.compound_interest.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.compound_interest.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.compound_interest.verbose_description"),
|
fullHelp: t("upgrades.compound_interest.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -274,7 +274,7 @@ export const rawUpgrades = [
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
lvl == 1
|
lvl == 1
|
||||||
? t("upgrades.sapper.tooltip")
|
? t("upgrades.sapper.tooltip")
|
||||||
: t("upgrades.sapper.help_plural", { lvl }),
|
: t("upgrades.sapper.help_plural", {lvl}),
|
||||||
fullHelp: t("upgrades.sapper.verbose_description"),
|
fullHelp: t("upgrades.sapper.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -300,7 +300,7 @@ export const rawUpgrades = [
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.extra_levels.name"),
|
name: t("upgrades.extra_levels.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.extra_levels.tooltip", { count: lvl + 7 }),
|
t("upgrades.extra_levels.tooltip", {count: lvl + 7}),
|
||||||
fullHelp: t("upgrades.extra_levels.verbose_description"),
|
fullHelp: t("upgrades.extra_levels.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -312,7 +312,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.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.pierce_color.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.pierce_color.verbose_description"),
|
fullHelp: t("upgrades.pierce_color.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -396,7 +396,7 @@ export const rawUpgrades = [
|
||||||
name: t("upgrades.sturdy_bricks.name"),
|
name: t("upgrades.sturdy_bricks.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
// lvl == 1
|
// lvl == 1
|
||||||
t("upgrades.sturdy_bricks.tooltip", { lvl, percent: lvl * 50 }),
|
t("upgrades.sturdy_bricks.tooltip", {lvl, percent: lvl * 50}),
|
||||||
// ?
|
// ?
|
||||||
// : t("upgrades.sturdy_bricks.help_plural"),
|
// : t("upgrades.sturdy_bricks.help_plural"),
|
||||||
fullHelp: t("upgrades.sturdy_bricks.verbose_description"),
|
fullHelp: t("upgrades.sturdy_bricks.verbose_description"),
|
||||||
|
@ -425,7 +425,7 @@ export const rawUpgrades = [
|
||||||
id: "one_more_choice",
|
id: "one_more_choice",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.one_more_choice.name"),
|
name: t("upgrades.one_more_choice.name"),
|
||||||
help: (lvl: number) => t("upgrades.one_more_choice.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.one_more_choice.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.one_more_choice.verbose_description"),
|
fullHelp: t("upgrades.one_more_choice.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -438,7 +438,7 @@ export const rawUpgrades = [
|
||||||
max: 2,
|
max: 2,
|
||||||
adventure: false,
|
adventure: false,
|
||||||
name: t("upgrades.instant_upgrade.name"),
|
name: t("upgrades.instant_upgrade.name"),
|
||||||
help: (lvl: number) => t("upgrades.instant_upgrade.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.instant_upgrade.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.instant_upgrade.verbose_description"),
|
fullHelp: t("upgrades.instant_upgrade.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -473,7 +473,7 @@ export const rawUpgrades = [
|
||||||
id: "asceticism",
|
id: "asceticism",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.asceticism.name"),
|
name: t("upgrades.asceticism.name"),
|
||||||
help: (lvl: number) => t("upgrades.asceticism.tooltip", { combo: lvl * 3 }),
|
help: (lvl: number) => t("upgrades.asceticism.tooltip", {combo: lvl * 3}),
|
||||||
fullHelp: t("upgrades.asceticism.verbose_description"),
|
fullHelp: t("upgrades.asceticism.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -483,12 +483,9 @@ export const rawUpgrades = [
|
||||||
gift: false,
|
gift: false,
|
||||||
|
|
||||||
id: "unbounded",
|
id: "unbounded",
|
||||||
max: 1,
|
max: 3,
|
||||||
name: t("upgrades.unbounded.name"),
|
name: t("upgrades.unbounded.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) => t("upgrades.unbounded.tooltip", {lvl}),
|
||||||
lvl > 1
|
|
||||||
? t("upgrades.unbounded.help_no_ceiling", { lvl })
|
|
||||||
: t("upgrades.unbounded.tooltip", { lvl }),
|
|
||||||
fullHelp: t("upgrades.unbounded.verbose_description"),
|
fullHelp: t("upgrades.unbounded.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -527,7 +524,7 @@ export const rawUpgrades = [
|
||||||
id: "nbricks",
|
id: "nbricks",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.nbricks.name"),
|
name: t("upgrades.nbricks.name"),
|
||||||
help: (lvl: number) => t("upgrades.nbricks.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.nbricks.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.nbricks.verbose_description"),
|
fullHelp: t("upgrades.nbricks.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -561,7 +558,7 @@ export const rawUpgrades = [
|
||||||
id: "zen",
|
id: "zen",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.zen.name"),
|
name: t("upgrades.zen.name"),
|
||||||
help: (lvl: number) => t("upgrades.zen.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.zen.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.zen.verbose_description"),
|
fullHelp: t("upgrades.zen.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -575,7 +572,7 @@ export const rawUpgrades = [
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
lvl == 1
|
lvl == 1
|
||||||
? t("upgrades.sacrifice.help_l1")
|
? t("upgrades.sacrifice.help_l1")
|
||||||
: t("upgrades.sacrifice.help_over", { lvl }),
|
: t("upgrades.sacrifice.help_over", {lvl}),
|
||||||
fullHelp: t("upgrades.sacrifice.verbose_description"),
|
fullHelp: t("upgrades.sacrifice.verbose_description"),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -587,7 +584,7 @@ export const rawUpgrades = [
|
||||||
id: "trampoline",
|
id: "trampoline",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.trampoline.name"),
|
name: t("upgrades.trampoline.name"),
|
||||||
help: (lvl: number) => t("upgrades.trampoline.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.trampoline.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.trampoline.verbose_description"),
|
fullHelp: t("upgrades.trampoline.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -599,7 +596,7 @@ export const rawUpgrades = [
|
||||||
id: "ghost_coins",
|
id: "ghost_coins",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.ghost_coins.name"),
|
name: t("upgrades.ghost_coins.name"),
|
||||||
help: (lvl: number) => t("upgrades.ghost_coins.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.ghost_coins.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.ghost_coins.verbose_description"),
|
fullHelp: t("upgrades.ghost_coins.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -634,7 +631,7 @@ export const rawUpgrades = [
|
||||||
id: "reach",
|
id: "reach",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.reach.name"),
|
name: t("upgrades.reach.name"),
|
||||||
help: (lvl: number) => t("upgrades.reach.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.reach.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.reach.verbose_description"),
|
fullHelp: t("upgrades.reach.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -647,7 +644,7 @@ export const rawUpgrades = [
|
||||||
max: 4,
|
max: 4,
|
||||||
name: t("upgrades.passive_income.name"),
|
name: t("upgrades.passive_income.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.passive_income.tooltip", { time: lvl * 0.25, lvl }),
|
t("upgrades.passive_income.tooltip", {time: lvl * 0.25, lvl}),
|
||||||
fullHelp: t("upgrades.passive_income.verbose_description"),
|
fullHelp: t("upgrades.passive_income.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -671,7 +668,7 @@ export const rawUpgrades = [
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.side_kick.name"),
|
name: t("upgrades.side_kick.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.side_kick.tooltip", { lvl, loss: lvl * 2 }),
|
t("upgrades.side_kick.tooltip", {lvl, loss: lvl * 2}),
|
||||||
fullHelp: t("upgrades.side_kick.verbose_description"),
|
fullHelp: t("upgrades.side_kick.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -684,7 +681,7 @@ export const rawUpgrades = [
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.side_flip.name"),
|
name: t("upgrades.side_flip.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.side_flip.tooltip", { lvl, loss: lvl * 2 }),
|
t("upgrades.side_flip.tooltip", {lvl, loss: lvl * 2}),
|
||||||
fullHelp: t("upgrades.side_flip.verbose_description"),
|
fullHelp: t("upgrades.side_flip.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -718,7 +715,7 @@ export const rawUpgrades = [
|
||||||
max: 7,
|
max: 7,
|
||||||
name: t("upgrades.addiction.name"),
|
name: t("upgrades.addiction.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.addiction.tooltip", { lvl, delay: (5 / lvl).toFixed(2) }),
|
t("upgrades.addiction.tooltip", {lvl, delay: (5 / lvl).toFixed(2)}),
|
||||||
fullHelp: t("upgrades.addiction.verbose_description"),
|
fullHelp: t("upgrades.addiction.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -730,7 +727,7 @@ export const rawUpgrades = [
|
||||||
max: 7,
|
max: 7,
|
||||||
name: t("upgrades.fountain_toss.name"),
|
name: t("upgrades.fountain_toss.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) =>
|
||||||
t("upgrades.fountain_toss.tooltip", { lvl, max: lvl * 30 }),
|
t("upgrades.fountain_toss.tooltip", {lvl, max: lvl * 30}),
|
||||||
fullHelp: t("upgrades.fountain_toss.verbose_description"),
|
fullHelp: t("upgrades.fountain_toss.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -741,7 +738,7 @@ export const rawUpgrades = [
|
||||||
id: "limitless",
|
id: "limitless",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.limitless.name"),
|
name: t("upgrades.limitless.name"),
|
||||||
help: (lvl: number) => t("upgrades.limitless.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.limitless.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.limitless.verbose_description"),
|
fullHelp: t("upgrades.limitless.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -752,7 +749,7 @@ export const rawUpgrades = [
|
||||||
id: "minefield",
|
id: "minefield",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.minefield.name"),
|
name: t("upgrades.minefield.name"),
|
||||||
help: (lvl: number) => t("upgrades.minefield.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.minefield.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.minefield.verbose_description"),
|
fullHelp: t("upgrades.minefield.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -763,7 +760,7 @@ export const rawUpgrades = [
|
||||||
id: "trickledown",
|
id: "trickledown",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.trickledown.name"),
|
name: t("upgrades.trickledown.name"),
|
||||||
help: (lvl: number) => t("upgrades.trickledown.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.trickledown.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.trickledown.verbose_description"),
|
fullHelp: t("upgrades.trickledown.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -774,7 +771,7 @@ export const rawUpgrades = [
|
||||||
id: "transparency",
|
id: "transparency",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.transparency.name"),
|
name: t("upgrades.transparency.name"),
|
||||||
help: (lvl: number) => t("upgrades.transparency.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.transparency.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.transparency.verbose_description"),
|
fullHelp: t("upgrades.transparency.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -785,7 +782,7 @@ export const rawUpgrades = [
|
||||||
id: "superhot",
|
id: "superhot",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.superhot.name"),
|
name: t("upgrades.superhot.name"),
|
||||||
help: (lvl: number) => t("upgrades.superhot.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.superhot.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.superhot.verbose_description"),
|
fullHelp: t("upgrades.superhot.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -796,7 +793,7 @@ export const rawUpgrades = [
|
||||||
id: "bricks_attract_coins",
|
id: "bricks_attract_coins",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.bricks_attract_coins.name"),
|
name: t("upgrades.bricks_attract_coins.name"),
|
||||||
help: (lvl: number) => t("upgrades.bricks_attract_coins.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.bricks_attract_coins.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.bricks_attract_coins.verbose_description"),
|
fullHelp: t("upgrades.bricks_attract_coins.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -807,7 +804,7 @@ export const rawUpgrades = [
|
||||||
id: "rainbow",
|
id: "rainbow",
|
||||||
max: 7,
|
max: 7,
|
||||||
name: t("upgrades.rainbow.name"),
|
name: t("upgrades.rainbow.name"),
|
||||||
help: (lvl: number) => t("upgrades.rainbow.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.rainbow.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.rainbow.verbose_description"),
|
fullHelp: t("upgrades.rainbow.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -818,7 +815,17 @@ export const rawUpgrades = [
|
||||||
id: "hypnosis",
|
id: "hypnosis",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.hypnosis.name"),
|
name: t("upgrades.hypnosis.name"),
|
||||||
help: (lvl: number) => t("upgrades.hypnosis.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.hypnosis.tooltip", {lvl}),
|
||||||
fullHelp: t("upgrades.hypnosis.verbose_description"),
|
fullHelp: t("upgrades.hypnosis.verbose_description"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
requires: "",
|
||||||
|
threshold: 215000,
|
||||||
|
gift: false,
|
||||||
|
id: "bricks_attract_ball",
|
||||||
|
max: 3,
|
||||||
|
name: t("upgrades.bricks_attract_ball.name"),
|
||||||
|
help: (lvl: number) => t("upgrades.bricks_attract_ball.tooltip", {count:lvl*3}),
|
||||||
|
fullHelp: t("upgrades.bricks_attract_ball.verbose_description"),
|
||||||
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue