Files
idle_clicker/public/js/ui/endlessView.js
T

127 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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, makeBuyable, setBuyable } from './dom.js';
import { bump, purchased } from './fx.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('strong');
const cost = h('small');
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,
),
h('div', { class: 'card__price' }, label, cost),
);
const row = { li, level, total, label, cost, line, shown: 1 };
makeBuyable(li, () => {
if (!actions.buy(line.id, amount)) return;
purchased(li, `+${fmt.number(row.shown)}`);
bump(level);
});
return row;
}
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')} ${t('ui.clickToBuy')}` }),
list,
);
}
function update(state) {
let any = false;
for (const row of rows.values()) {
const { li, level, total, label, cost, line } = row;
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'),
);
row.shown = quote.count;
setText(label, maxed ? t('endless.maxed') : `×${fmt.number(quote.count)}`);
setText(cost, maxed ? '' : money(quote.cost));
setBuyable(li, !maxed && quote.count > 0 && state.funds >= quote.cost);
}
root.hidden = !any;
}
return { rebuild, update };
}