// Endless upgrades: families of upgrades that continue forever, level after level. import { endlessQuote, lineAvailable, lineLevel } from '../engine/endless.js'; import { t } from '../services/i18n.js'; import { h, icon } from './dom.js'; import { effectText, moneyFormatter, setText } from './text.js'; const AMOUNTS = [1, 10, 100, 'max']; export function createEndlessView(root, actions) { let ctx; let fmt; let money; let amount = 1; const rows = new Map(); const lineName = (line) => line.effect.target ? t('endless.name.generator', { target: t(`theme.gen.${line.effect.target}.name`) }) : t(`endless.name.${line.id}`); function rowFor(line) { const level = h('span', { class: 'badge' }); const total = h('p', { class: 'card__meta' }); const label = h('span', { class: 'btn__label' }); const cost = h('small'); const buy = h( 'button', { class: 'btn btn--buy', type: 'button', onclick: () => actions.buy(line.id, amount) }, label, cost, ); const li = h( 'li', { class: 'card', hidden: true }, icon(`endless.${line.id}`), h( 'div', { class: 'card__body' }, h('h3', { class: 'card__title' }, h('span', { text: lineName(line) }), level), h('p', { class: 'card__desc', text: t('endless.perLevel', { effect: effectText(line.effect, fmt) }) }), total, ), buy, ); return { li, level, total, label, cost, buy, line }; } function rebuild(newCtx, formatter) { ctx = newCtx; fmt = formatter; money = moneyFormatter(fmt); rows.clear(); const list = h('ul', { class: 'cards cards--grid' }); for (const line of ctx.endless) { const row = rowFor(line); rows.set(line.id, row); list.append(row.li); } const amountGroup = h( 'fieldset', { class: 'segmented' }, h('legend', { class: 'sr-only', text: t('endless.amount') }), ...AMOUNTS.map((a) => h( 'label', {}, h('input', { type: 'radio', name: 'endless-amount', value: String(a), checked: a === amount, onchange: () => { amount = a; }, }), h('span', { text: a === 'max' ? t('ui.max') : `×${a}` }), ), ), ); root.replaceChildren( h( 'div', { class: 'panel__head' }, h('h2', { class: 'panel__title', text: t('endless.title') }), amountGroup, ), h('p', { class: 'hint', text: t('endless.intro') }), list, ); } function update(state) { let any = false; for (const { li, level, total, label, cost, buy, line } of rows.values()) { const open = lineAvailable(state, line); li.hidden = !open; if (!open) continue; any = true; const lv = lineLevel(state, line.id); const maxed = lv >= line.maxLevel; let quote = endlessQuote(state, ctx, line.id, amount); if (quote.count <= 0) quote = endlessQuote(state, ctx, line.id, 1); setText(level, t('endless.level', { level: fmt.number(lv) })); setText( total, lv > 0 ? t('endless.total', { effect: effectText({ ...line.effect, value: line.effect.value ** lv }, fmt) }) : t('endless.none'), ); setText(label, maxed ? t('endless.maxed') : t('endless.buy', { count: fmt.number(quote.count) })); setText(cost, maxed ? '' : money(quote.cost)); buy.disabled = maxed || quote.count <= 0 || !(state.funds >= quote.cost); } root.hidden = !any; } return { rebuild, update }; }