feat: New features (research, invest, gambling, new game+, trophies)
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
// Research tab: labs produce points over time; points buy nodes of the tree.
|
||||
|
||||
import { labCost, researchStatus } from '../engine/research.js';
|
||||
import { t } from '../services/i18n.js';
|
||||
import { h, icon } from './dom.js';
|
||||
import { effectText, moneyFormatter, setText } from './text.js';
|
||||
|
||||
const BRANCHES = ['prod', 'mkt', 'log', 'fin', 'ins'];
|
||||
|
||||
export function createResearchView(root, actions) {
|
||||
let ctx;
|
||||
let fmt;
|
||||
let money;
|
||||
let els;
|
||||
const nodeRows = new Map();
|
||||
|
||||
function nodeRow(node) {
|
||||
const status = h('p', { class: 'card__meta' });
|
||||
const buy = h('button', {
|
||||
class: 'btn btn--buy',
|
||||
type: 'button',
|
||||
onclick: () => actions.buyNode(node.id),
|
||||
});
|
||||
const li = h(
|
||||
'li',
|
||||
{ class: 'card' },
|
||||
icon(`research.${node.id}`),
|
||||
h(
|
||||
'div',
|
||||
{ class: 'card__body' },
|
||||
h('h3', { class: 'card__title', text: t(`research.node.${node.id}`) }),
|
||||
h('p', { class: 'card__desc', text: effectText(node.effect, fmt) }),
|
||||
status,
|
||||
),
|
||||
buy,
|
||||
);
|
||||
return { li, status, buy, node };
|
||||
}
|
||||
|
||||
function rebuild(newCtx, formatter) {
|
||||
ctx = newCtx;
|
||||
fmt = formatter;
|
||||
money = moneyFormatter(fmt);
|
||||
nodeRows.clear();
|
||||
|
||||
els = {
|
||||
rp: h('strong'),
|
||||
rate: h('span', { class: 'hint' }),
|
||||
labs: h('span', { class: 'hint' }),
|
||||
buyLab: h('button', { class: 'btn btn--wide', type: 'button', onclick: () => actions.buyLab() }),
|
||||
};
|
||||
|
||||
const branchPanels = BRANCHES.map((branch) => {
|
||||
const list = h('ul', { class: 'cards' });
|
||||
for (const node of ctx.research.filter((n) => n.branch === branch)) {
|
||||
const row = nodeRow(node);
|
||||
nodeRows.set(node.id, row);
|
||||
list.append(row.li);
|
||||
}
|
||||
return h(
|
||||
'section',
|
||||
{ class: 'panel' },
|
||||
h('h2', { class: 'panel__title', text: t(`research.branch.${branch}`) }),
|
||||
list,
|
||||
);
|
||||
});
|
||||
|
||||
root.replaceChildren(
|
||||
h(
|
||||
'section',
|
||||
{ class: 'panel panel--wide' },
|
||||
h('h2', { class: 'panel__title', text: t('tab.research') }),
|
||||
h('p', { class: 'hint', text: t('research.intro') }),
|
||||
h(
|
||||
'div',
|
||||
{ class: 'tile' },
|
||||
icon('res.research'),
|
||||
h('div', {}, h('span', { class: 'tile__label', text: t('theme.res.research') }), els.rp, els.rate),
|
||||
),
|
||||
els.labs,
|
||||
els.buyLab,
|
||||
),
|
||||
...branchPanels,
|
||||
);
|
||||
}
|
||||
|
||||
function update(state, d) {
|
||||
const r = ctx.rules.research;
|
||||
setText(els.rp, fmt.number(Math.floor(state.rp)));
|
||||
setText(els.rate, t('research.rate', { rate: fmt.number(Math.round(d.rpRate * 1000) / 1000) }));
|
||||
setText(els.labs, t('research.labs', { count: state.labs, perLab: fmt.number(r.rpPerLabPerSecond * d.mods.rp) }));
|
||||
|
||||
const maxed = state.labs >= r.labMax;
|
||||
const cost = labCost(state, ctx);
|
||||
setText(els.buyLab, maxed ? t('research.labMax') : t('research.buyLab', { cost: money(cost) }));
|
||||
els.buyLab.disabled = maxed || state.funds < cost;
|
||||
|
||||
for (const { li, status, buy, node } of nodeRows.values()) {
|
||||
const s = researchStatus(state, node);
|
||||
li.classList.toggle('card--done', s === 'owned');
|
||||
li.classList.toggle('card--locked', s === 'locked');
|
||||
buy.hidden = s !== 'available';
|
||||
buy.disabled = state.rp < node.cost;
|
||||
setText(buy, t('research.cost', { cost: fmt.number(node.cost) }));
|
||||
if (s === 'owned') setText(status, t('research.owned'));
|
||||
else if (s === 'locked') {
|
||||
const names = node.requires.map((id) => t(`research.node.${id}`)).join(', ');
|
||||
setText(status, t('research.requires', { names }));
|
||||
} else setText(status, '');
|
||||
}
|
||||
}
|
||||
|
||||
return { rebuild, update };
|
||||
}
|
||||
Reference in New Issue
Block a user