mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 12:15:06 -04:00
Build 29068563
This commit is contained in:
parent
6ef13f2d19
commit
df8bfbb350
25 changed files with 384 additions and 336 deletions
|
@ -39,11 +39,13 @@ New players get confused as to which upgrades they have and why a side became re
|
||||||
|
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
- As soon as level condition is reached, lock it in and tell the user
|
|
||||||
- change fortunate ball to work more like coin magnet, carrying the balls around to catch them at next puck bounce
|
- change fortunate ball to work more like coin magnet, carrying the balls around to catch them at next puck bounce
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- review the "next unlocks" in score and game over
|
||||||
|
- As soon as upgrade condition is reached, toast
|
||||||
|
- As soon as level condition is reached, lock it in and tell the user
|
||||||
- extra life only saves your last ball, max 7 instead of 3
|
- extra life only saves your last ball, max 7 instead of 3
|
||||||
- Don't use "RAZ" in French explanations.
|
- Don't use "RAZ" in French explanations.
|
||||||
- explain ghost coin's slow down effect
|
- explain ghost coin's slow down effect
|
||||||
|
|
|
@ -29,8 +29,8 @@ android {
|
||||||
applicationId = "me.lecaro.breakout"
|
applicationId = "me.lecaro.breakout"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 29068232
|
versionCode = 29068563
|
||||||
versionName = "29068232"
|
versionName = "29068563"
|
||||||
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
217
dist/index.html
vendored
217
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
||||||
// The version of the cache.
|
// The version of the cache.
|
||||||
const VERSION = "29068232";
|
const VERSION = "29068563";
|
||||||
|
|
||||||
// The name of the cache
|
// The name of the cache
|
||||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||||
|
|
25
src/addToTotalScore.ts
Normal file
25
src/addToTotalScore.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { GameState } from "./types";
|
||||||
|
import { icons, upgrades } from "./loadGameData";
|
||||||
|
import { schedulGameSound } from "./gameStateMutators";
|
||||||
|
import { toast } from "./toast";
|
||||||
|
import { t } from "./i18n/i18n";
|
||||||
|
import { getTotalScore, setSettingValue } from "./settings";
|
||||||
|
|
||||||
|
export function addToTotalScore(gameState: GameState, points: number) {
|
||||||
|
if (gameState.creative) return;
|
||||||
|
const pastScore = getTotalScore();
|
||||||
|
const newScore = pastScore + points;
|
||||||
|
setSettingValue("breakout_71_total_score", newScore);
|
||||||
|
// Check unlocked upgrades
|
||||||
|
upgrades.forEach((u) => {
|
||||||
|
if (u.threshold > pastScore && u.threshold <= newScore) {
|
||||||
|
schedulGameSound(gameState, "colorChange", 0, 1);
|
||||||
|
toast(
|
||||||
|
icons["icon:" + u.id] +
|
||||||
|
"<strong>" +
|
||||||
|
t("gameOver.unlocked_perk") +
|
||||||
|
"</strong>",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -442,8 +442,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "icon:base_combo",
|
"name": "icon:base_combo",
|
||||||
"size": 5,
|
"size": 7,
|
||||||
"bricks": "ttttttytytttttttytytttttt",
|
"bricks": "________bbbbb__bybyb__bbbbb__bybyb__bbbbb________",
|
||||||
"svg": null
|
"svg": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29068232"
|
"29068563"
|
||||||
|
|
|
@ -513,7 +513,6 @@ h2.histogram-title strong {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.toast {
|
.toast {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -527,20 +526,18 @@ h2.histogram-title strong {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
animation: toast 800ms forwards;
|
animation: toast forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes toast {
|
@keyframes toast {
|
||||||
0%{
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform:translate(-20px, 0);
|
transform: translate(-20px, -20px) scale(0.5);
|
||||||
}
|
}
|
||||||
10%,90%{
|
10%,
|
||||||
|
90% {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
100%{
|
|
||||||
opacity: 0;
|
|
||||||
transform:translate(20px, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -298,8 +298,8 @@ export async function openUpgradesPicker(gameState: GameState) {
|
||||||
`,
|
`,
|
||||||
...actions,
|
...actions,
|
||||||
|
|
||||||
getNearestUnlockHTML(gameState),
|
|
||||||
pickedUpgradesHTMl(gameState),
|
pickedUpgradesHTMl(gameState),
|
||||||
|
getNearestUnlockHTML(gameState),
|
||||||
|
|
||||||
`<div id="level-recording-container"></div>`,
|
`<div id="level-recording-container"></div>`,
|
||||||
],
|
],
|
||||||
|
@ -424,7 +424,7 @@ setInterval(() => {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
monitorLevelsUnlocks(gameState)
|
monitorLevelsUnlocks(gameState);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
window.addEventListener("visibilitychange", () => {
|
window.addEventListener("visibilitychange", () => {
|
||||||
|
|
|
@ -31,11 +31,7 @@ import {
|
||||||
import { t } from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
import { icons } from "./loadGameData";
|
import { icons } from "./loadGameData";
|
||||||
|
|
||||||
import {
|
import { getCurrentMaxCoins, getCurrentMaxParticles } from "./settings";
|
||||||
addToTotalScore,
|
|
||||||
getCurrentMaxCoins,
|
|
||||||
getCurrentMaxParticles,
|
|
||||||
} from "./settings";
|
|
||||||
import { background } from "./render";
|
import { background } from "./render";
|
||||||
import { gameOver } from "./gameOver";
|
import { gameOver } from "./gameOver";
|
||||||
import {
|
import {
|
||||||
|
@ -50,6 +46,7 @@ import {
|
||||||
import { stopRecording } from "./recording";
|
import { stopRecording } from "./recording";
|
||||||
import { isOptionOn } from "./options";
|
import { isOptionOn } from "./options";
|
||||||
import { clamp, comboKeepingRate } from "./pure_functions";
|
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;
|
||||||
|
@ -1508,7 +1505,8 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
ball.y > ylimit &&
|
ball.y > ylimit &&
|
||||||
ball.vy > 0 &&
|
ball.vy > 0 &&
|
||||||
(ballIsUnderPuck ||
|
(ballIsUnderPuck ||
|
||||||
(gameState.balls.length<2 && gameState.perks.extra_life &&
|
(gameState.balls.length < 2 &&
|
||||||
|
gameState.perks.extra_life &&
|
||||||
ball.y > ylimit + gameState.puckHeight / 2))
|
ball.y > ylimit + gameState.puckHeight / 2))
|
||||||
) {
|
) {
|
||||||
if (ballIsUnderPuck) {
|
if (ballIsUnderPuck) {
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
import {Ball, GameState, Level, PerkId, PerksMap, RunHistoryItem, UpgradeLike,} from "./types";
|
import {
|
||||||
|
Ball,
|
||||||
|
GameState,
|
||||||
|
Level,
|
||||||
|
PerkId,
|
||||||
|
PerksMap,
|
||||||
|
RunHistoryItem,
|
||||||
|
UpgradeLike,
|
||||||
|
} from "./types";
|
||||||
import { icons, upgrades } from "./loadGameData";
|
import { icons, upgrades } from "./loadGameData";
|
||||||
import { t } from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
import { clamp } from "./pure_functions";
|
import { clamp } from "./pure_functions";
|
||||||
import { rawUpgrades } from "./upgrades";
|
import { rawUpgrades } from "./upgrades";
|
||||||
import { hashCode } from "./getLevelBackground";
|
import { hashCode } from "./getLevelBackground";
|
||||||
|
import { getTotalScore } from "./settings";
|
||||||
|
|
||||||
export function describeLevel(level: Level) {
|
export function describeLevel(level: Level) {
|
||||||
let bricks = 0,
|
let bricks = 0,
|
||||||
|
@ -74,7 +83,7 @@ export function getRowColIndex(gameState: GameState, row: number, col: number) {
|
||||||
|
|
||||||
export function getPossibleUpgrades(gameState: GameState) {
|
export function getPossibleUpgrades(gameState: GameState) {
|
||||||
return upgrades
|
return upgrades
|
||||||
.filter((u) => gameState.totalScoreAtRunStart >= u.threshold)
|
.filter((u) => getTotalScore() >= u.threshold)
|
||||||
.filter((u) => !u?.requires || gameState.perks[u?.requires]);
|
.filter((u) => !u?.requires || gameState.perks[u?.requires]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +296,7 @@ function isExcluded(id:PerkId){
|
||||||
if (u.requires) excluded.add(u.requires);
|
if (u.requires) excluded.add(u.requires);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return excluded.has(id)
|
return excluded.has(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLevelUnlockCondition(levelIndex: number) {
|
export function getLevelUnlockCondition(levelIndex: number) {
|
||||||
|
@ -297,7 +306,6 @@ export function getLevelUnlockCondition(levelIndex: number) {
|
||||||
minScore = Math.max(-1000 + 100 * levelIndex, 0);
|
minScore = Math.max(-1000 + 100 * levelIndex, 0);
|
||||||
|
|
||||||
if (levelIndex > 20) {
|
if (levelIndex > 20) {
|
||||||
|
|
||||||
const possibletargets = rawUpgrades
|
const possibletargets = rawUpgrades
|
||||||
.slice(0, Math.floor(levelIndex / 2))
|
.slice(0, Math.floor(levelIndex / 2))
|
||||||
.map((u) => u)
|
.map((u) => u)
|
||||||
|
|
|
@ -2262,21 +2262,6 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
<concept_node>
|
|
||||||
<name>continue_to_unlock</name>
|
|
||||||
<description/>
|
|
||||||
<comment/>
|
|
||||||
<translations>
|
|
||||||
<translation>
|
|
||||||
<language>en-US</language>
|
|
||||||
<approved>false</approved>
|
|
||||||
</translation>
|
|
||||||
<translation>
|
|
||||||
<language>fr-FR</language>
|
|
||||||
<approved>false</approved>
|
|
||||||
</translation>
|
|
||||||
</translations>
|
|
||||||
</concept_node>
|
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>get_upgrades_to_unlock</name>
|
<name>get_upgrades_to_unlock</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
@ -2337,21 +2322,6 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
<concept_node>
|
|
||||||
<name>title_looped</name>
|
|
||||||
<description/>
|
|
||||||
<comment/>
|
|
||||||
<translations>
|
|
||||||
<translation>
|
|
||||||
<language>en-US</language>
|
|
||||||
<approved>true</approved>
|
|
||||||
</translation>
|
|
||||||
<translation>
|
|
||||||
<language>fr-FR</language>
|
|
||||||
<approved>true</approved>
|
|
||||||
</translation>
|
|
||||||
</translations>
|
|
||||||
</concept_node>
|
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>upcoming_levels</name>
|
<name>upcoming_levels</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"gameOver.stats.level_reached": "Level reached",
|
"gameOver.stats.level_reached": "Level reached",
|
||||||
"gameOver.stats.total_score": "Total score",
|
"gameOver.stats.total_score": "Total score",
|
||||||
"gameOver.stats.upgrades_applied": "Upgrades applied",
|
"gameOver.stats.upgrades_applied": "Upgrades applied",
|
||||||
"gameOver.unlocked_perk": "You just unlocked a perk",
|
"gameOver.unlocked_perk": "Upgrade unlocked",
|
||||||
"gameOver.unlocked_perk_plural": "You just unlocked {{count}} perks",
|
"gameOver.unlocked_perk_plural": "You just unlocked {{count}} perks",
|
||||||
"gameOver.win.summary": "This game is over. You stashed {{score}} coins. ",
|
"gameOver.win.summary": "This game is over. You stashed {{score}} coins. ",
|
||||||
"gameOver.win.title": "You completed this game",
|
"gameOver.win.title": "You completed this game",
|
||||||
|
@ -143,13 +143,11 @@
|
||||||
"play.stats.levelMisses": "Missed shots, where you hit nothing",
|
"play.stats.levelMisses": "Missed shots, where you hit nothing",
|
||||||
"play.stats.levelTime": "Level time",
|
"play.stats.levelTime": "Level time",
|
||||||
"play.stats.levelWallBounces": "Wall bounces",
|
"play.stats.levelWallBounces": "Wall bounces",
|
||||||
"score_panel.close_to_unlock": "You could unlock a level at the end of this run:",
|
"score_panel.close_to_unlock": "Next level unlock :",
|
||||||
"score_panel.continue_to_unlock": "You are about to unlock level \"{{level}}\"",
|
|
||||||
"score_panel.get_upgrades_to_unlock": "Get {{missingUpgrades}} and score {{points}} more points to unlock level \"{{level}}\"",
|
"score_panel.get_upgrades_to_unlock": "Get {{missingUpgrades}} and score {{points}} more points to unlock level \"{{level}}\"",
|
||||||
"score_panel.rerolls_count": "You have accumulated {{rerolls}} rerolls",
|
"score_panel.rerolls_count": "You have accumulated {{rerolls}} rerolls",
|
||||||
"score_panel.score_to_unlock": "Score {{points}} more points to unlock level \"{{level}}\"",
|
"score_panel.score_to_unlock": "Score {{points}} more points to unlock level \"{{level}}\"",
|
||||||
"score_panel.title": "{{score}} points at level {{level}}/{{max}} ",
|
"score_panel.title": "{{score}} points at level {{level}}/{{max}} ",
|
||||||
"score_panel.title_looped": "{{score}} points at level {{level}}/{{max}} of loop {{loop}}",
|
|
||||||
"score_panel.upcoming_levels": "Upcoming levels :",
|
"score_panel.upcoming_levels": "Upcoming levels :",
|
||||||
"score_panel.upgrades_picked": "Upgrades picked so far : ",
|
"score_panel.upgrades_picked": "Upgrades picked so far : ",
|
||||||
"unlocks.greyed_out_help": "The grayed out upgrades can be unlocked by increasing your total score. The total score increases every time you score in game, outside of test runs.",
|
"unlocks.greyed_out_help": "The grayed out upgrades can be unlocked by increasing your total score. The total score increases every time you score in game, outside of test runs.",
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"gameOver.stats.level_reached": "Niveau atteint",
|
"gameOver.stats.level_reached": "Niveau atteint",
|
||||||
"gameOver.stats.total_score": "Score total",
|
"gameOver.stats.total_score": "Score total",
|
||||||
"gameOver.stats.upgrades_applied": "Mises à jour appliquées",
|
"gameOver.stats.upgrades_applied": "Mises à jour appliquées",
|
||||||
"gameOver.unlocked_perk": "Vous avez débloqué une amélioration",
|
"gameOver.unlocked_perk": "Amélioration débloquée",
|
||||||
"gameOver.unlocked_perk_plural": "Vous avez débloqué {{count}} améliorations",
|
"gameOver.unlocked_perk_plural": "Vous avez débloqué {{count}} améliorations",
|
||||||
"gameOver.win.summary": "Cette partie est terminée. Vous avez accumulé {{score}} pièces. ",
|
"gameOver.win.summary": "Cette partie est terminée. Vous avez accumulé {{score}} pièces. ",
|
||||||
"gameOver.win.title": "Vous avez terminé cette partie",
|
"gameOver.win.title": "Vous avez terminé cette partie",
|
||||||
|
@ -143,13 +143,11 @@
|
||||||
"play.stats.levelMisses": "Tirs ratés, ou vous n'avez touché aucune brique",
|
"play.stats.levelMisses": "Tirs ratés, ou vous n'avez touché aucune brique",
|
||||||
"play.stats.levelTime": "Durée du niveau",
|
"play.stats.levelTime": "Durée du niveau",
|
||||||
"play.stats.levelWallBounces": "Rebonds sur les murs",
|
"play.stats.levelWallBounces": "Rebonds sur les murs",
|
||||||
"score_panel.close_to_unlock": "Vous pourriez débloquer un niveau à la fin de cette partie :",
|
"score_panel.close_to_unlock": "Prochain niveau débloqué : ",
|
||||||
"score_panel.continue_to_unlock": "Vous êtes sur le point de débloquer le niveau « {{level}} »",
|
"score_panel.get_upgrades_to_unlock": "Obtenez {{missingUpgrades}} et attrapez {{points}} pièces supplémentaires pour débloquer le niveau « {{level}} »",
|
||||||
"score_panel.get_upgrades_to_unlock": "Obtenez {{missingUpgrades}} et marquez {{points}} points supplémentaires pour débloquer le niveau « {{level}} »",
|
|
||||||
"score_panel.rerolls_count": "Vous avez accumulé {{rerolls}} rerolls",
|
"score_panel.rerolls_count": "Vous avez accumulé {{rerolls}} rerolls",
|
||||||
"score_panel.score_to_unlock": "Marquez {{points}} points supplémentaires pour débloquer le niveau « {{level}} »",
|
"score_panel.score_to_unlock": "Attrapez {{points}} pièces supplémentaires pour débloquer le niveau « {{level}} »",
|
||||||
"score_panel.title": "{{score}} points au niveau {{level}}/{{max}} ",
|
"score_panel.title": "{{score}} points au niveau {{level}}/{{max}} ",
|
||||||
"score_panel.title_looped": "{{score}} points au niveau {{level}}/{{max}} ",
|
|
||||||
"score_panel.upcoming_levels": "Niveaux de la parties : ",
|
"score_panel.upcoming_levels": "Niveaux de la parties : ",
|
||||||
"score_panel.upgrades_picked": "Améliorations choisies jusqu'à présent :",
|
"score_panel.upgrades_picked": "Améliorations choisies jusqu'à présent :",
|
||||||
"unlocks.greyed_out_help": "Les éléments grisées peuvent être débloquées en augmentant votre score total. Le score total augmente à chaque fois que vous marquez des points dans le jeu, en dehors des parties de test.",
|
"unlocks.greyed_out_help": "Les éléments grisées peuvent être débloquées en augmentant votre score total. Le score total augmente à chaque fois que vous marquez des points dans le jeu, en dehors des parties de test.",
|
||||||
|
|
|
@ -113,15 +113,17 @@ migrate("set_breakout_71_unlocked_levels"+_appVersion, () => {
|
||||||
localStorage.getItem("breakout_71_unlocked_levels") || "[]",
|
localStorage.getItem("breakout_71_unlocked_levels") || "[]",
|
||||||
) as string[];
|
) as string[];
|
||||||
|
|
||||||
allLevels.filter((l,li)=>!reasonLevelIsLocked(li,runsHistory,false)).forEach(l=>{
|
allLevels
|
||||||
|
.filter((l, li) => !reasonLevelIsLocked(li, runsHistory, false))
|
||||||
|
.forEach((l) => {
|
||||||
if (!breakout_71_unlocked_levels.includes(l.name)) {
|
if (!breakout_71_unlocked_levels.includes(l.name)) {
|
||||||
breakout_71_unlocked_levels.push(l.name)
|
breakout_71_unlocked_levels.push(l.name);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
localStorage.setItem("breakout_71_unlocked_levels", JSON.stringify(breakout_71_unlocked_levels));
|
localStorage.setItem(
|
||||||
|
"breakout_71_unlocked_levels",
|
||||||
|
JSON.stringify(breakout_71_unlocked_levels),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterMigration();
|
||||||
|
|
||||||
|
|
||||||
afterMigration()
|
|
||||||
|
|
|
@ -7,35 +7,44 @@ import {t} from "./i18n/i18n";
|
||||||
import { toast } from "./toast";
|
import { toast } from "./toast";
|
||||||
import { schedulGameSound } from "./gameStateMutators";
|
import { schedulGameSound } from "./gameStateMutators";
|
||||||
|
|
||||||
let list: {minScore: number, forbidden: UpgradeLike[], required: UpgradeLike[]}[] ;
|
let list: {
|
||||||
let unlocked=new Set(getSettingValue('breakout_71_unlocked_levels',[]) as string[])
|
minScore: number;
|
||||||
|
forbidden: UpgradeLike[];
|
||||||
|
required: UpgradeLike[];
|
||||||
|
}[];
|
||||||
|
let unlocked = new Set(
|
||||||
|
getSettingValue("breakout_71_unlocked_levels", []) as string[],
|
||||||
|
);
|
||||||
|
|
||||||
export function monitorLevelsUnlocks(gameState: GameState) {
|
export function monitorLevelsUnlocks(gameState: GameState) {
|
||||||
if (gameState.creative) return;
|
if (gameState.creative) return;
|
||||||
|
|
||||||
if (!list) {
|
if (!list) {
|
||||||
list = allLevels.map((l, li) => ({
|
list = allLevels.map((l, li) => ({
|
||||||
name:l.name,li,l,
|
name: l.name,
|
||||||
...getLevelUnlockCondition(li)
|
li,
|
||||||
}))
|
l,
|
||||||
|
...getLevelUnlockCondition(li),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
list.forEach(({ name, minScore, forbidden, required, l }) => {
|
list.forEach(({ name, minScore, forbidden, required, l }) => {
|
||||||
// Already unlocked
|
// Already unlocked
|
||||||
if(unlocked.has(name)) return
|
if (unlocked.has(name)) return;
|
||||||
// Score not reached yet
|
// Score not reached yet
|
||||||
if(gameState.score<minScore) return
|
if (gameState.score < minScore) return;
|
||||||
// We are missing a required perk
|
// We are missing a required perk
|
||||||
if(required.find(id=>!gameState.perks[id])) return;
|
if (required.find((id) => !gameState.perks[id])) return;
|
||||||
// We have a forbidden perk
|
// We have a forbidden perk
|
||||||
if(forbidden.find(id=>gameState.perks[id])) return;
|
if (forbidden.find((id) => gameState.perks[id])) return;
|
||||||
// Level just got unlocked
|
// Level just got unlocked
|
||||||
unlocked.add(name)
|
unlocked.add(name);
|
||||||
setSettingValue('breakout_71_unlocked_levels', getSettingValue('breakout_71_unlocked_levels',[]).concat([name]))
|
setSettingValue(
|
||||||
|
"breakout_71_unlocked_levels",
|
||||||
|
getSettingValue("breakout_71_unlocked_levels", []).concat([name]),
|
||||||
|
);
|
||||||
|
|
||||||
toast(icons[name]+'<strong>'+t('unlocks.just_unlocked')+'</strong>')
|
toast(icons[name] + "<strong>" + t("unlocks.just_unlocked") + "</strong>");
|
||||||
schedulGameSound(gameState, 'colorChange', 0, 1)
|
schedulGameSound(gameState, "colorChange", 0, 1);
|
||||||
|
});
|
||||||
})
|
|
||||||
}
|
}
|
|
@ -42,14 +42,13 @@ export function getRunLevels(
|
||||||
|
|
||||||
export function newGameState(params: RunParams): GameState {
|
export function newGameState(params: RunParams): GameState {
|
||||||
const highScore = getHighScore();
|
const highScore = getHighScore();
|
||||||
const totalScoreAtRunStart=getTotalScore()
|
|
||||||
|
|
||||||
const perks = { ...makeEmptyPerksMap(upgrades), ...(params?.perks || {}) };
|
const perks = { ...makeEmptyPerksMap(upgrades), ...(params?.perks || {}) };
|
||||||
|
|
||||||
let randomGift: PerkId | undefined = undefined;
|
let randomGift: PerkId | undefined = undefined;
|
||||||
if (!sumOfValues(perks)) {
|
if (!sumOfValues(perks)) {
|
||||||
const giftable = upgrades.filter(
|
const giftable = upgrades.filter(
|
||||||
(u) => totalScoreAtRunStart >= u.threshold && isStartingPerk(u),
|
(u) => getTotalScore() >= u.threshold && isStartingPerk(u),
|
||||||
);
|
);
|
||||||
|
|
||||||
randomGift =
|
randomGift =
|
||||||
|
@ -108,7 +107,6 @@ export function newGameState(params: RunParams): GameState {
|
||||||
coinSize: 14,
|
coinSize: 14,
|
||||||
puckHeight: 20,
|
puckHeight: 20,
|
||||||
|
|
||||||
totalScoreAtRunStart,
|
|
||||||
pauseUsesDuringRun: 0,
|
pauseUsesDuringRun: 0,
|
||||||
keyboardPuckSpeed: 0,
|
keyboardPuckSpeed: 0,
|
||||||
lastTick: performance.now(),
|
lastTick: performance.now(),
|
||||||
|
|
|
@ -11,6 +11,8 @@ import {
|
||||||
import { getCreativeModeWarning, getHistory } from "./gameOver";
|
import { getCreativeModeWarning, getHistory } from "./gameOver";
|
||||||
import { pause } from "./game";
|
import { pause } from "./game";
|
||||||
import { allLevels, icons } from "./loadGameData";
|
import { allLevels, icons } from "./loadGameData";
|
||||||
|
import { firstWhere } from "./pure_functions";
|
||||||
|
import { getSettingValue, getTotalScore } from "./settings";
|
||||||
|
|
||||||
export async function openScorePanel(gameState: GameState) {
|
export async function openScorePanel(gameState: GameState) {
|
||||||
pause(true);
|
pause(true);
|
||||||
|
@ -37,31 +39,34 @@ export async function openScorePanel(gameState: GameState) {
|
||||||
|
|
||||||
export function getNearestUnlockHTML(gameState: GameState) {
|
export function getNearestUnlockHTML(gameState: GameState) {
|
||||||
if (gameState.creative) return "";
|
if (gameState.creative) return "";
|
||||||
const unlockable = allLevels
|
const unlocked = new Set(getSettingValue("breakout_71_unlocked_levels", []));
|
||||||
.map((l, li) => {
|
const firstUnlockable = firstWhere(allLevels, (l, li) => {
|
||||||
|
if (unlocked.has(l.name)) return;
|
||||||
|
const reason = reasonLevelIsLocked(li, getHistory(), false);
|
||||||
|
if (!reason) return;
|
||||||
|
|
||||||
const { minScore, forbidden, required } = getLevelUnlockCondition(li);
|
const { minScore, forbidden, required } = getLevelUnlockCondition(li);
|
||||||
|
const missing = required.filter((u) => !gameState?.perks?.[u.id]);
|
||||||
|
// we can't have a forbidden perk
|
||||||
|
if (forbidden.find((u) => gameState?.perks?.[u.id])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All required upgrades need to be unlocked
|
||||||
|
if (missing.find((u) => u.threshold > getTotalScore())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
l,
|
l,
|
||||||
li,
|
li,
|
||||||
minScore,
|
minScore,
|
||||||
forbidden,
|
forbidden,
|
||||||
required,
|
required,
|
||||||
missing: required.filter((u) => !gameState?.perks?.[u.id]),
|
missing,
|
||||||
reason: reasonLevelIsLocked(li, getHistory(), false),
|
reason,
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
.filter(
|
|
||||||
({ reason, forbidden, missing }) =>
|
|
||||||
// Level needs to be locked
|
|
||||||
reason &&
|
|
||||||
// we can't have a forbidden perk
|
|
||||||
!forbidden.find((u) => gameState?.perks?.[u.id]) &&
|
|
||||||
// All required upgrades need to be unlocked
|
|
||||||
!missing.find((u) => u.threshold > gameState.totalScoreAtRunStart),
|
|
||||||
);
|
|
||||||
|
|
||||||
const firstUnlockable =
|
|
||||||
unlockable.find(({ missing }) => !missing.length) || unlockable[0];
|
|
||||||
|
|
||||||
if (!firstUnlockable) return "";
|
if (!firstUnlockable) return "";
|
||||||
let missingPoints = firstUnlockable.minScore - gameState.score;
|
let missingPoints = firstUnlockable.minScore - gameState.score;
|
||||||
|
@ -74,13 +79,9 @@ export function getNearestUnlockHTML(gameState: GameState) {
|
||||||
points: missingPoints,
|
points: missingPoints,
|
||||||
level: firstUnlockable.l.name,
|
level: firstUnlockable.l.name,
|
||||||
})) ||
|
})) ||
|
||||||
(missingPoints > 0 &&
|
|
||||||
t("score_panel.score_to_unlock", {
|
t("score_panel.score_to_unlock", {
|
||||||
points: missingPoints,
|
points: missingPoints,
|
||||||
level: firstUnlockable.l.name,
|
level: firstUnlockable.l.name,
|
||||||
})) ||
|
|
||||||
t("score_panel.continue_to_unlock", {
|
|
||||||
level: firstUnlockable.l.name,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return `
|
return `
|
||||||
|
|
|
@ -65,3 +65,13 @@ export function miniMarkDown(md: string) {
|
||||||
)
|
)
|
||||||
.join("\n");
|
.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function firstWhere<Input, Output>(
|
||||||
|
arr: Input[],
|
||||||
|
mapper: (item: Input, index: number) => Output | undefined,
|
||||||
|
): Output | undefined {
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
const result = mapper(arr[i], i);
|
||||||
|
if (typeof result !== "undefined") return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
// Settings
|
// Settings
|
||||||
|
|
||||||
import { GameState } from "./types";
|
|
||||||
|
|
||||||
let cachedSettings: { [key: string]: unknown } = {};
|
let cachedSettings: { [key: string]: unknown } = {};
|
||||||
|
|
||||||
export function getSettingValue<T>(key: string, defaultValue: T) {
|
export function getSettingValue<T>(key: string, defaultValue: T) {
|
||||||
|
@ -29,11 +27,6 @@ export function getTotalScore() {
|
||||||
return getSettingValue("breakout_71_total_score", 0);
|
return getSettingValue("breakout_71_total_score", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addToTotalScore(gameState: GameState, points: number) {
|
|
||||||
if (!gameState.creative)
|
|
||||||
setSettingValue("breakout_71_total_score", getTotalScore() + points);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCurrentMaxCoins() {
|
export function getCurrentMaxCoins() {
|
||||||
return Math.pow(2, getSettingValue("max_coins", 1)) * 200;
|
return Math.pow(2, getSettingValue("max_coins", 1)) * 200;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ export function startingPerkMenuButton() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export function isStartingPerk(u: Upgrade): boolean {
|
export function isStartingPerk(u: Upgrade): boolean {
|
||||||
|
|
||||||
return getSettingValue("start_with_" + u.id, u.giftable);
|
return getSettingValue("start_with_" + u.id, u.giftable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
src/toast.ts
21
src/toast.ts
|
@ -1,8 +1,17 @@
|
||||||
|
let onScreen = 0;
|
||||||
|
|
||||||
export function toast(html) {
|
export function toast(html) {
|
||||||
const div =document.createElement('div')
|
const div = document.createElement("div");
|
||||||
div.classList='toast'
|
div.classList = "toast";
|
||||||
div.innerHTML=html
|
div.innerHTML = html;
|
||||||
document.body.appendChild(div)
|
const lasts = 1500 + onScreen * 200;
|
||||||
// TOast
|
div.style.animationDuration = lasts + "ms";
|
||||||
// setTimeout(()=>div.remove() , 500 )
|
div.style.top = 40 + onScreen * 50 + "px";
|
||||||
|
|
||||||
|
document.body.appendChild(div);
|
||||||
|
onScreen++;
|
||||||
|
setTimeout(() => {
|
||||||
|
div.remove();
|
||||||
|
onScreen--;
|
||||||
|
}, lasts);
|
||||||
}
|
}
|
8
src/types.d.ts
vendored
8
src/types.d.ts
vendored
|
@ -258,7 +258,6 @@ export type GameState = {
|
||||||
ballSize: number;
|
ballSize: number;
|
||||||
coinSize: number;
|
coinSize: number;
|
||||||
puckHeight: number;
|
puckHeight: number;
|
||||||
totalScoreAtRunStart: number;
|
|
||||||
pauseUsesDuringRun: number;
|
pauseUsesDuringRun: number;
|
||||||
keyboardPuckSpeed: number;
|
keyboardPuckSpeed: number;
|
||||||
lastTick: number;
|
lastTick: number;
|
||||||
|
@ -296,4 +295,9 @@ export type OptionDef = {
|
||||||
help: string;
|
help: string;
|
||||||
};
|
};
|
||||||
export type OptionId = keyof typeof options;
|
export type OptionId = keyof typeof options;
|
||||||
export type UpgradeLike = { id: PerkId; name: string; requires: string };
|
export type UpgradeLike = {
|
||||||
|
id: PerkId;
|
||||||
|
name: string;
|
||||||
|
requires: string;
|
||||||
|
threshold: number;
|
||||||
|
};
|
||||||
|
|
|
@ -17,20 +17,9 @@ export const rawUpgrades = [
|
||||||
: t("upgrades.extra_life.help_plural", { lvl }),
|
: t("upgrades.extra_life.help_plural", { lvl }),
|
||||||
fullHelp: t("upgrades.extra_life.fullHelp"),
|
fullHelp: t("upgrades.extra_life.fullHelp"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
requires: "",
|
|
||||||
threshold: 0,
|
|
||||||
id: "streak_shots",
|
|
||||||
giftable: true,
|
|
||||||
max: 1,
|
|
||||||
name: t("upgrades.streak_shots.name"),
|
|
||||||
help: (lvl: number) => t("upgrades.streak_shots.help", { lvl }),
|
|
||||||
fullHelp: t("upgrades.streak_shots.fullHelp"),
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
id: "base_combo",
|
id: "base_combo",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
|
@ -42,7 +31,6 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
giftable: false,
|
giftable: false,
|
||||||
id: "slow_down",
|
id: "slow_down",
|
||||||
|
@ -53,7 +41,6 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
giftable: false,
|
giftable: false,
|
||||||
id: "bigger_puck",
|
id: "bigger_puck",
|
||||||
|
@ -64,7 +51,6 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
giftable: false,
|
giftable: false,
|
||||||
id: "viscosity",
|
id: "viscosity",
|
||||||
|
@ -76,8 +62,32 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
threshold: 50,
|
||||||
|
giftable: false,
|
||||||
|
id: "skip_last",
|
||||||
|
max: 7,
|
||||||
|
name: t("upgrades.skip_last.name"),
|
||||||
|
help: (lvl: number) =>
|
||||||
|
lvl == 1
|
||||||
|
? t("upgrades.skip_last.help")
|
||||||
|
: t("upgrades.skip_last.help_plural", { lvl }),
|
||||||
|
fullHelp: t("upgrades.skip_last.fullHelp"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requires: "",
|
||||||
|
threshold: 100,
|
||||||
|
id: "streak_shots",
|
||||||
|
giftable: true,
|
||||||
|
max: 1,
|
||||||
|
name: t("upgrades.streak_shots.name"),
|
||||||
|
help: (lvl: number) => t("upgrades.streak_shots.help", { lvl }),
|
||||||
|
fullHelp: t("upgrades.streak_shots.fullHelp"),
|
||||||
|
},
|
||||||
|
|
||||||
threshold: 0,
|
{
|
||||||
|
requires: "",
|
||||||
|
|
||||||
|
threshold: 200,
|
||||||
id: "left_is_lava",
|
id: "left_is_lava",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 1,
|
max: 1,
|
||||||
|
@ -89,7 +99,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
threshold: 300,
|
||||||
id: "right_is_lava",
|
id: "right_is_lava",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 1,
|
max: 1,
|
||||||
|
@ -100,7 +110,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
threshold: 400,
|
||||||
id: "top_is_lava",
|
id: "top_is_lava",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 1,
|
max: 1,
|
||||||
|
@ -111,20 +121,6 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 0,
|
|
||||||
giftable: false,
|
|
||||||
id: "skip_last",
|
|
||||||
max: 7,
|
|
||||||
name: t("upgrades.skip_last.name"),
|
|
||||||
help: (lvl: number) =>
|
|
||||||
lvl == 1
|
|
||||||
? t("upgrades.skip_last.help")
|
|
||||||
: t("upgrades.skip_last.help_plural", { lvl }),
|
|
||||||
fullHelp: t("upgrades.skip_last.fullHelp"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
requires: "",
|
|
||||||
|
|
||||||
threshold: 500,
|
threshold: 500,
|
||||||
id: "telekinesis",
|
id: "telekinesis",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
|
@ -138,8 +134,7 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
threshold: 700,
|
||||||
threshold: 1000,
|
|
||||||
giftable: false,
|
giftable: false,
|
||||||
id: "coin_magnet",
|
id: "coin_magnet",
|
||||||
max: 3,
|
max: 3,
|
||||||
|
@ -153,7 +148,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 1500,
|
threshold: 800,
|
||||||
id: "multiball",
|
id: "multiball",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 6,
|
max: 6,
|
||||||
|
@ -164,7 +159,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 2000,
|
threshold: 1000,
|
||||||
giftable: false,
|
giftable: false,
|
||||||
id: "smaller_puck",
|
id: "smaller_puck",
|
||||||
max: 2,
|
max: 2,
|
||||||
|
@ -177,8 +172,7 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
threshold: 1500,
|
||||||
threshold: 3000,
|
|
||||||
id: "pierce",
|
id: "pierce",
|
||||||
giftable: false,
|
giftable: false,
|
||||||
max: 3,
|
max: 3,
|
||||||
|
@ -189,7 +183,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 4000,
|
threshold: 2000,
|
||||||
id: "picky_eater",
|
id: "picky_eater",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 1,
|
max: 1,
|
||||||
|
@ -200,7 +194,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 5000,
|
threshold: 2500,
|
||||||
giftable: false,
|
giftable: false,
|
||||||
id: "metamorphosis",
|
id: "metamorphosis",
|
||||||
max: 1,
|
max: 1,
|
||||||
|
@ -211,7 +205,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 6000,
|
threshold: 3000,
|
||||||
id: "compound_interest",
|
id: "compound_interest",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 1,
|
max: 1,
|
||||||
|
@ -221,7 +215,7 @@ export const rawUpgrades = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
threshold: 7000,
|
threshold: 4000,
|
||||||
id: "hot_start",
|
id: "hot_start",
|
||||||
giftable: true,
|
giftable: true,
|
||||||
max: 3,
|
max: 3,
|
||||||
|
@ -236,7 +230,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 9000,
|
threshold: 6000,
|
||||||
id: "sapper",
|
id: "sapper",
|
||||||
giftable: false,
|
giftable: false,
|
||||||
max: 7,
|
max: 7,
|
||||||
|
@ -250,7 +244,7 @@ export const rawUpgrades = [
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
|
|
||||||
threshold: 11000,
|
threshold: 9000,
|
||||||
id: "bigger_explosions",
|
id: "bigger_explosions",
|
||||||
giftable: false,
|
giftable: false,
|
||||||
max: 1,
|
max: 1,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue