// Legacy tab: restart the run for permanent points, spend them on perks. import { legacyGain, perkCost, perkLevel } from '../engine/legacy.js'; import { t } from '../services/i18n.js'; import { h, icon } from './dom.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('span', { class: 'btn__label' }); const buy = h('button', { class: 'btn btn--buy', type: 'button', onclick: () => actions.buyPerk(perk.id) }, cost); 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) }), ), buy, ); perks.append(li); perkRows.set(perk.id, { perk, level, cost, buy }); } root.replaceChildren( h( 'section', { class: 'panel' }, h('h2', { class: 'panel__title', text: t('tab.legacy') }), h('p', { class: 'hint', text: t('legacy.intro', { passive: fmt.number(ctx.rules.legacy.passivePerPoint * 100) }) }), 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') }), perks), ); } function update(state, d) { const { threshold, passivePerPoint } = ctx.rules.legacy; 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((1 + passivePerPoint) ** state.legacy.earned) })); const gain = legacyGain(state, ctx, d.mods); setText(els.gain, t('legacy.gain', { gain: fmt.number(gain) })); els.progress.max = threshold; els.progress.value = Math.min(state.totalProduced, threshold); setText( els.need, gain >= 1 ? t('legacy.ready') : t('legacy.need', { have: fmt.number(Math.floor(state.totalProduced)), need: fmt.number(threshold) }), ); setText(els.restart, t('legacy.restart')); els.restart.disabled = gain < 1; for (const { perk, level, cost, buy } 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) })); buy.disabled = maxed || state.legacy.points < price; } } return { rebuild, update }; }