120 lines
4.2 KiB
JavaScript
120 lines
4.2 KiB
JavaScript
// Legacy tab: restart the run for permanent points, spend them on perks.
|
|
|
|
import { legacyGain, nextPointAt, perkCost, perkLevel } from '../engine/legacy.js';
|
|
import { passiveBonus } from '../engine/modifiers.js';
|
|
import { t } from '../services/i18n.js';
|
|
import { h, icon, makeBuyable, setBuyable } from './dom.js';
|
|
import { bump, purchased } from './fx.js';
|
|
import { effectText, setText } from './text.js';
|
|
|
|
export function createLegacyView(root, actions) {
|
|
let ctx;
|
|
let fmt;
|
|
let els;
|
|
const perkRows = new Map();
|
|
|
|
function rebuild(newCtx, formatter) {
|
|
ctx = newCtx;
|
|
fmt = formatter;
|
|
perkRows.clear();
|
|
|
|
els = {
|
|
points: h('strong'),
|
|
earned: h('dd'),
|
|
prestiges: h('dd'),
|
|
passive: h('dd'),
|
|
gain: h('p', { class: 'card__desc' }),
|
|
need: h('p', { class: 'hint' }),
|
|
progress: h('progress', { class: 'progress', max: 1, value: 0 }),
|
|
restart: h('button', { class: 'btn btn--danger btn--wide', type: 'button', onclick: () => actions.restart() }),
|
|
};
|
|
|
|
const perks = h('ul', { class: 'cards' });
|
|
for (const perk of ctx.legacy) {
|
|
const level = h('span', { class: 'badge' });
|
|
const cost = h('strong');
|
|
const li = h(
|
|
'li',
|
|
{ class: 'card' },
|
|
icon(`legacy.${perk.id}`),
|
|
h(
|
|
'div',
|
|
{ class: 'card__body' },
|
|
h('h3', { class: 'card__title' }, h('span', { text: t(`legacy.perk.${perk.id}`) }), level),
|
|
h('p', { class: 'card__desc', text: effectText(perk.effect, fmt) }),
|
|
),
|
|
h('div', { class: 'card__price' }, cost),
|
|
);
|
|
makeBuyable(li, () => {
|
|
if (!actions.buyPerk(perk.id)) return;
|
|
purchased(li, '+1', null);
|
|
bump(level);
|
|
});
|
|
perks.append(li);
|
|
perkRows.set(perk.id, { perk, li, level, cost });
|
|
}
|
|
|
|
root.replaceChildren(
|
|
h(
|
|
'section',
|
|
{ class: 'panel' },
|
|
h('h2', { class: 'panel__title', text: t('tab.legacy') }),
|
|
h('p', { class: 'hint', text: t('legacy.intro') }),
|
|
h('div', { class: 'tile tile--primary' }, icon('res.legacy'), h('div', {}, h('span', { class: 'tile__label', text: t('theme.res.legacy') }), els.points)),
|
|
h(
|
|
'dl',
|
|
{ class: 'stats' },
|
|
h('div', {}, h('dt', { text: t('legacy.earned') }), els.earned),
|
|
h('div', {}, h('dt', { text: t('legacy.restarts') }), els.prestiges),
|
|
h('div', {}, h('dt', { text: t('legacy.passive') }), els.passive),
|
|
),
|
|
h('h3', { class: 'dialog__subtitle', text: t('legacy.restartTitle') }),
|
|
els.gain,
|
|
els.progress,
|
|
els.need,
|
|
els.restart,
|
|
),
|
|
h(
|
|
'section',
|
|
{ class: 'panel' },
|
|
h('h2', { class: 'panel__title', text: t('legacy.perks') }),
|
|
h('p', { class: 'hint', text: t('ui.clickToBuy') }),
|
|
perks,
|
|
),
|
|
);
|
|
}
|
|
|
|
function update(state, d) {
|
|
setText(els.points, fmt.number(state.legacy.points));
|
|
setText(els.earned, fmt.number(state.legacy.earned));
|
|
setText(els.prestiges, fmt.number(state.legacy.prestiges));
|
|
setText(els.passive, t('legacy.passiveValue', { bonus: fmt.number(passiveBonus(state, ctx)) }));
|
|
|
|
const gain = legacyGain(state, ctx, d.mods);
|
|
setText(els.gain, t('legacy.gain', { gain: fmt.number(gain) }));
|
|
// Points are earned from everything ever produced, so the bar shows the lifetime total.
|
|
const target = nextPointAt(state, ctx);
|
|
els.progress.max = target;
|
|
els.progress.value = Math.min(state.lifetimeProduced, target);
|
|
setText(
|
|
els.need,
|
|
gain >= 1
|
|
? t('legacy.ready')
|
|
: t('legacy.need', { have: fmt.number(Math.floor(state.lifetimeProduced)), need: fmt.number(target) }),
|
|
);
|
|
setText(els.restart, t('legacy.restart'));
|
|
els.restart.disabled = gain < 1;
|
|
|
|
for (const { perk, li, level, cost } of perkRows.values()) {
|
|
const lv = perkLevel(state, perk);
|
|
const maxed = lv >= perk.maxLevel;
|
|
const price = perkCost(perk, lv);
|
|
setText(level, t('legacy.level', { level: lv, max: perk.maxLevel }));
|
|
setText(cost, maxed ? t('legacy.maxed') : t('legacy.perkCost', { cost: fmt.number(price) }));
|
|
setBuyable(li, !maxed && state.legacy.points >= price);
|
|
}
|
|
}
|
|
|
|
return { rebuild, update };
|
|
}
|