mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-21 12:36:15 -04:00
wip
This commit is contained in:
parent
46228a2128
commit
9624c5b351
16 changed files with 518 additions and 52 deletions
|
@ -17,9 +17,13 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
- avoid showing a +1 and -1 at the same time when a combo increase is reset
|
- avoid showing a +1 and -1 at the same time when a combo increase is reset
|
||||||
|
- display runs history
|
||||||
|
- display closest unlock with current perks in score and gameover screens
|
||||||
|
- progress of unlock
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- in the runs history, only save perks that were chosen by the user
|
||||||
- migration to save past content to localStorage.recovery_data right before starting a new version
|
- migration to save past content to localStorage.recovery_data right before starting a new version
|
||||||
- mention unlock conditions in help
|
- mention unlock conditions in help
|
||||||
- show unlock condition in unlocks menu for perks as tooltip
|
- show unlock condition in unlocks menu for perks as tooltip
|
||||||
|
|
159
dist/index.html
vendored
159
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -43,7 +43,7 @@ export async function asyncAlert<t>({
|
||||||
content: (string | AsyncAlertAction<t>)[];
|
content: (string | AsyncAlertAction<t>)[];
|
||||||
allowClose?: boolean;
|
allowClose?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
}): Promise<t | void> {
|
}): Promise<t | void|string> {
|
||||||
updateAlertsOpen(+1);
|
updateAlertsOpen(+1);
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
popupWrap.className = className;
|
popupWrap.className = className;
|
||||||
|
@ -139,6 +139,11 @@ ${icon}
|
||||||
addto.appendChild(button);
|
addto.appendChild(button);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
popup.addEventListener('click', e=>{
|
||||||
|
if(e.target.getAttribute('data-resolve-to')){
|
||||||
|
closeWithResult(e.target.getAttribute('data-resolve-to'))
|
||||||
|
}
|
||||||
|
},true)
|
||||||
popupWrap.appendChild(popup);
|
popupWrap.appendChild(popup);
|
||||||
(
|
(
|
||||||
popupWrap.querySelector(
|
popupWrap.querySelector(
|
||||||
|
|
|
@ -1280,5 +1280,12 @@
|
||||||
"bricks": "_________________________bbb____ttb_bbbbb__tttbbbb_bbbttt_bbbb__bbbt__bbbb_ttbbb__bbttttttbbbbbb_ttt___bbbb_____________________________________",
|
"bricks": "_________________________bbb____ttb_bbbbb__tttbbbb_bbbttt_bbbb__bbbt__bbbb_ttbbb__bbttttttbbbbbb_ttt___bbbb_____________________________________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon:history",
|
||||||
|
"size": 8,
|
||||||
|
"bricks": "__gggg___ggbggg_gggbgggggggbggggggggbbgggggggggg_gggggg___gggg__",
|
||||||
|
"svg": null,
|
||||||
|
"color": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,6 +1,5 @@
|
||||||
* {
|
* {
|
||||||
font-family:
|
font-family: Courier New,
|
||||||
Courier New,
|
|
||||||
Courier,
|
Courier,
|
||||||
Lucida Sans Typewriter,
|
Lucida Sans Typewriter,
|
||||||
Lucida Typewriter,
|
Lucida Typewriter,
|
||||||
|
@ -465,3 +464,32 @@ h2.histogram-title strong {
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#popup.history > div {
|
||||||
|
max-width: none;
|
||||||
|
|
||||||
|
table {
|
||||||
|
th:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
td, th {
|
||||||
|
padding: 0 5px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
th:first-child, td:first-child {
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
width: 20px;
|
||||||
|
height: auto;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
tr:nth-child(2n) {
|
||||||
|
background: rgba(0, 0, 0, 0.58);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ import {startingPerkMenuButton} from "./startingPerks";
|
||||||
import "./migrations";
|
import "./migrations";
|
||||||
import {getCreativeModeWarning, getHistory} from "./gameOver";
|
import {getCreativeModeWarning, getHistory} from "./gameOver";
|
||||||
import {generateSaveFileContent} from "./generateSaveFileContent";
|
import {generateSaveFileContent} from "./generateSaveFileContent";
|
||||||
|
import {runHistoryViewerMenuEntry} from "./runHistoryViewer";
|
||||||
|
|
||||||
export async function play() {
|
export async function play() {
|
||||||
if (await applyFullScreenChoice()) return;
|
if (await applyFullScreenChoice()) return;
|
||||||
|
@ -460,6 +461,7 @@ export async function openMainMenu() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
creativeMode(gameState),
|
creativeMode(gameState),
|
||||||
|
runHistoryViewerMenuEntry(),
|
||||||
{
|
{
|
||||||
icon: icons["icon:unlocks"],
|
icon: icons["icon:unlocks"],
|
||||||
text: t("main_menu.unlocks"),
|
text: t("main_menu.unlocks"),
|
||||||
|
|
|
@ -33,7 +33,6 @@ export function gameOver(title: string, intro: string) {
|
||||||
pause(true);
|
pause(true);
|
||||||
stopRecording();
|
stopRecording();
|
||||||
addToTotalPlayTime(gameState.runStatistics.runTime);
|
addToTotalPlayTime(gameState.runStatistics.runTime);
|
||||||
gameState.runStatistics.max_level = gameState.currentLevel + 1;
|
|
||||||
|
|
||||||
let animationDelay = -300;
|
let animationDelay = -300;
|
||||||
const getDelay = () => {
|
const getDelay = () => {
|
||||||
|
@ -112,6 +111,7 @@ try {
|
||||||
localStorage.getItem("breakout_71_runs_history") || "[]",
|
localStorage.getItem("breakout_71_runs_history") || "[]",
|
||||||
) as RunHistoryItem[];
|
) as RunHistoryItem[];
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
export function getHistory() {
|
export function getHistory() {
|
||||||
return runsHistory;
|
return runsHistory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -596,23 +596,6 @@ export function addToScore(gameState: GameState, coin: Coin) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function recordBestWorstLevelScore(gameState: GameState) {
|
|
||||||
const levelScore = gameState.score - gameState.levelStartScore;
|
|
||||||
const { runStatistics } = gameState;
|
|
||||||
if (
|
|
||||||
runStatistics.best_level_score === -1 ||
|
|
||||||
runStatistics.best_level_score < levelScore
|
|
||||||
) {
|
|
||||||
runStatistics.best_level_score = levelScore;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
runStatistics.worst_level_score === -1 ||
|
|
||||||
runStatistics.worst_level_score > levelScore
|
|
||||||
) {
|
|
||||||
runStatistics.worst_level_score = levelScore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setLevel(gameState: GameState, l: number) {
|
export async function setLevel(gameState: GameState, l: number) {
|
||||||
// Here to alleviate double upgrades issues
|
// Here to alleviate double upgrades issues
|
||||||
if (gameState.upgradesOfferedFor >= l) {
|
if (gameState.upgradesOfferedFor >= l) {
|
||||||
|
@ -622,7 +605,6 @@ export async function setLevel(gameState: GameState, l: number) {
|
||||||
gameState.upgradesOfferedFor = l;
|
gameState.upgradesOfferedFor = l;
|
||||||
pause(false);
|
pause(false);
|
||||||
stopRecording();
|
stopRecording();
|
||||||
recordBestWorstLevelScore(gameState);
|
|
||||||
|
|
||||||
if (l > 0) {
|
if (l > 0) {
|
||||||
await openUpgradesPicker(gameState);
|
await openUpgradesPicker(gameState);
|
||||||
|
|
|
@ -419,6 +419,196 @@
|
||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>history</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>columns</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>max_combo</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>max_level</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>puck_bounces</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>puck_bounces_tooltip</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>runTime</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>runTime_tooltip</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>score</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>started</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>upgrades_picked</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>help</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>locked</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>title</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>lab</name>
|
<name>lab</name>
|
||||||
<children>
|
<children>
|
||||||
|
|
|
@ -24,6 +24,18 @@
|
||||||
"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",
|
||||||
|
"history.columns.max_combo": "Max combo",
|
||||||
|
"history.columns.max_level": "Levels",
|
||||||
|
"history.columns.puck_bounces": "PB",
|
||||||
|
"history.columns.puck_bounces_tooltip": "Puck bounces : number of time the ball bounced on the puck",
|
||||||
|
"history.columns.runTime": "Dur.",
|
||||||
|
"history.columns.runTime_tooltip": "Duration of the run, in seconds, only counting time where the game is running and the ball is in motion",
|
||||||
|
"history.columns.score": "Score",
|
||||||
|
"history.columns.started": "Date",
|
||||||
|
"history.columns.upgrades_picked": "Upgrades",
|
||||||
|
"history.help": "See the list of your {{count}} game",
|
||||||
|
"history.locked": "Play at least ten games to unlock",
|
||||||
|
"history.title": "Runs history",
|
||||||
"lab.help": "Try any build you want",
|
"lab.help": "Try any build you want",
|
||||||
"lab.instructions": "Select upgrades below, then pick the level to play. Creative mode runs are ignored in unlocks, high score, total score and statistics, and only last one level.",
|
"lab.instructions": "Select upgrades below, then pick the level to play. Creative mode runs are ignored in unlocks, high score, total score and statistics, and only last one level.",
|
||||||
"lab.menu_entry": "Creative mode",
|
"lab.menu_entry": "Creative mode",
|
||||||
|
|
|
@ -24,6 +24,18 @@
|
||||||
"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",
|
||||||
|
"history.columns.max_combo": "",
|
||||||
|
"history.columns.max_level": "",
|
||||||
|
"history.columns.puck_bounces": "",
|
||||||
|
"history.columns.puck_bounces_tooltip": "",
|
||||||
|
"history.columns.runTime": "Dur.",
|
||||||
|
"history.columns.runTime_tooltip": "",
|
||||||
|
"history.columns.score": "",
|
||||||
|
"history.columns.started": "",
|
||||||
|
"history.columns.upgrades_picked": "",
|
||||||
|
"history.help": "",
|
||||||
|
"history.locked": "",
|
||||||
|
"history.title": "",
|
||||||
"lab.help": "Essayez n'importe quel build",
|
"lab.help": "Essayez n'importe quel build",
|
||||||
"lab.instructions": "Sélectionnez les améliorations ci-dessous, puis choisissez le niveau à jouer. Les parties en mode créatif sont ignorées dans les déblocages, le meilleur score, le score total et les statistiques, et ne durent qu'un seul niveau.",
|
"lab.instructions": "Sélectionnez les améliorations ci-dessous, puis choisissez le niveau à jouer. Les parties en mode créatif sont ignorées dans les déblocages, le meilleur score, le score total et les statistiques, et ne durent qu'un seul niveau.",
|
||||||
"lab.menu_entry": "Mode créatif",
|
"lab.menu_entry": "Mode créatif",
|
||||||
|
|
|
@ -78,7 +78,15 @@ migrate("compact_runs_data", () => {
|
||||||
delete r.perks[key]
|
delete r.perks[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if('best_level_score' in r) {
|
||||||
|
delete r.best_level_score
|
||||||
|
}
|
||||||
|
if('worst_level_score' in r) {
|
||||||
|
delete r.worst_level_score
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
localStorage.setItem("breakout_71_runs_history", JSON.stringify(runsHistory));
|
localStorage.setItem("breakout_71_runs_history", JSON.stringify(runsHistory));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -103,8 +103,6 @@ export function newGameState(params: RunParams): GameState {
|
||||||
runTime: 0,
|
runTime: 0,
|
||||||
coins_spawned: 0,
|
coins_spawned: 0,
|
||||||
score: 0,
|
score: 0,
|
||||||
best_level_score: -1,
|
|
||||||
worst_level_score: -1,
|
|
||||||
bricks_broken: 0,
|
bricks_broken: 0,
|
||||||
misses: 0,
|
misses: 0,
|
||||||
balls_lost: 0,
|
balls_lost: 0,
|
||||||
|
@ -112,7 +110,6 @@ export function newGameState(params: RunParams): GameState {
|
||||||
wall_bounces: 0,
|
wall_bounces: 0,
|
||||||
upgrades_picked: 1,
|
upgrades_picked: 1,
|
||||||
max_combo: 1,
|
max_combo: 1,
|
||||||
max_level: 0,
|
|
||||||
},
|
},
|
||||||
lastOffered: {},
|
lastOffered: {},
|
||||||
levelTime: 0,
|
levelTime: 0,
|
||||||
|
|
99
src/runHistoryViewer.ts
Normal file
99
src/runHistoryViewer.ts
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
import {getHistory} from "./gameOver";
|
||||||
|
import {icons} from "./loadGameData";
|
||||||
|
import {t} from "./i18n/i18n";
|
||||||
|
import {asyncAlert} from "./asyncAlert";
|
||||||
|
import {rawUpgrades} from "./upgrades";
|
||||||
|
|
||||||
|
export function runHistoryViewerMenuEntry(){
|
||||||
|
const history = getHistory()
|
||||||
|
|
||||||
|
return {
|
||||||
|
icon:icons['icon:history'],
|
||||||
|
text:t('history.title'),
|
||||||
|
disabled : history.length<10,
|
||||||
|
help: history.length<10 ? t('history.locked'):t('history.help',{count:history.length}),
|
||||||
|
async value(){
|
||||||
|
let sort = 0
|
||||||
|
let sortDir = -1
|
||||||
|
let columns = [
|
||||||
|
{
|
||||||
|
label:t('history.columns.started'),
|
||||||
|
field: r=>r.started,
|
||||||
|
render(v){
|
||||||
|
return new Date(v).toISOString().slice(0,10)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:t('history.columns.score'),
|
||||||
|
field: r=>r.score
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:t('history.columns.runTime'),
|
||||||
|
tooltip:t('history.columns.runTime_tooltip'),
|
||||||
|
|
||||||
|
field: r=>r.runTime,
|
||||||
|
render(v){
|
||||||
|
return Math.floor(v/1000)+'s'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:t('history.columns.puck_bounces'),
|
||||||
|
tooltip:t('history.columns.puck_bounces_tooltip'),
|
||||||
|
field: r=>r.puck_bounces,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:t('history.columns.max_combo'),
|
||||||
|
field: r=>r.max_combo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:t('history.columns.upgrades_picked'),
|
||||||
|
field: r=>r.upgrades_picked,
|
||||||
|
},
|
||||||
|
...rawUpgrades.map(u=>({
|
||||||
|
label: icons['icon:'+u.id],
|
||||||
|
tooltip:u.name,
|
||||||
|
field: r=>r.perks[u.id]||0,
|
||||||
|
render(v){
|
||||||
|
if(!v) return '-'
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
]
|
||||||
|
while(true){
|
||||||
|
const header = columns.map((c, ci) => `<th data-tooltip="${c.tooltip || ''}" data-resolve-to="sort:${ci}">${c.label}</th>`).join('')
|
||||||
|
const toString = v => v.toString()
|
||||||
|
const tbody = history.sort((a, b) => sortDir * (columns[sort].field(a) - columns[sort].field(b))).map(h => '<tr>' + columns.map(c => {
|
||||||
|
const value = c.field(h) ?? 0
|
||||||
|
const render = c.render || toString
|
||||||
|
return '<td>' + render(value) + '</td>'
|
||||||
|
}).join('') + '</tr>').join('')
|
||||||
|
|
||||||
|
|
||||||
|
const result = await asyncAlert({
|
||||||
|
title: t('history.title'),
|
||||||
|
className: 'history',
|
||||||
|
content: [
|
||||||
|
`
|
||||||
|
<table>
|
||||||
|
<thead><tr>${header}</tr></thead>
|
||||||
|
<tbody>${tbody}</tbody>
|
||||||
|
</table>
|
||||||
|
`
|
||||||
|
|
||||||
|
]
|
||||||
|
})
|
||||||
|
if(!result) return
|
||||||
|
if(result.startsWith('sort:')){
|
||||||
|
const newSort = parseInt(result.split(':')[1])
|
||||||
|
if(newSort==sort){
|
||||||
|
sortDir*=-1
|
||||||
|
}else{
|
||||||
|
sortDir=-1
|
||||||
|
sort=newSort
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ export function setupTooltips() {
|
||||||
while (parent && !parent.hasAttribute("data-tooltip")) {
|
while (parent && !parent.hasAttribute("data-tooltip")) {
|
||||||
parent = parent.parentElement;
|
parent = parent.parentElement;
|
||||||
}
|
}
|
||||||
if (parent?.hasAttribute("data-tooltip")) {
|
if (parent?.getAttribute("data-tooltip")?.trim()) {
|
||||||
hovering = parent as HTMLElement;
|
hovering = parent as HTMLElement;
|
||||||
tooltip.innerHTML = hovering.getAttribute("data-tooltip") || "";
|
tooltip.innerHTML = hovering.getAttribute("data-tooltip") || "";
|
||||||
tooltip.style.display = "";
|
tooltip.style.display = "";
|
||||||
|
|
3
src/types.d.ts
vendored
3
src/types.d.ts
vendored
|
@ -147,9 +147,6 @@ export type RunStats = {
|
||||||
wall_bounces: number;
|
wall_bounces: number;
|
||||||
upgrades_picked: number;
|
upgrades_picked: number;
|
||||||
max_combo: number;
|
max_combo: number;
|
||||||
max_level: number;
|
|
||||||
best_level_score: number;
|
|
||||||
worst_level_score: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PerksMap = {
|
export type PerksMap = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue