Files

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 };
}