feat: New features (research, invest, gambling, new game+, trophies)
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
// Contracts tab: opportunities to seize, active effects, the active contract
|
||||
// and the board of offers.
|
||||
|
||||
import { t } from '../services/i18n.js';
|
||||
import { h } from './dom.js';
|
||||
import { formatDuration, moneyFormatter, rewardText, setText } from './text.js';
|
||||
|
||||
const BUFF_LABEL = {
|
||||
demand_mult: 'contracts.buff.demand',
|
||||
global_mult: 'contracts.buff.production',
|
||||
material_price_mult: 'contracts.buff.material',
|
||||
};
|
||||
|
||||
export function createContractsView(root, actions) {
|
||||
let ctx;
|
||||
let fmt;
|
||||
let els;
|
||||
let offersSignature = '';
|
||||
let buffsSignature = '';
|
||||
|
||||
function rebuild(newCtx, formatter) {
|
||||
ctx = newCtx;
|
||||
fmt = formatter;
|
||||
offersSignature = '';
|
||||
buffsSignature = '';
|
||||
|
||||
els = {
|
||||
eventTitle: h('h3', { class: 'card__title' }),
|
||||
eventText: h('p', { class: 'card__desc' }),
|
||||
eventTime: h('p', { class: 'card__meta' }),
|
||||
claim: h('button', { class: 'btn btn--primary', type: 'button', text: t('contracts.claim'), onclick: () => actions.claimEvent() }),
|
||||
eventBox: h('div', { class: 'callout' }),
|
||||
eventNone: h('p', { class: 'hint', text: t('contracts.eventNone') }),
|
||||
buffs: h('ul', { class: 'cards' }),
|
||||
activeBox: h('div', { class: 'callout' }),
|
||||
activeTitle: h('h3', { class: 'card__title' }),
|
||||
activeReward: h('p', { class: 'card__desc' }),
|
||||
activeProgress: h('progress', { class: 'progress', max: 1, value: 0 }),
|
||||
activeText: h('p', { class: 'card__meta' }),
|
||||
abandon: h('button', { class: 'btn', type: 'button', text: t('contracts.abandon'), onclick: () => actions.abandon() }),
|
||||
activeNone: h('p', { class: 'hint', text: t('contracts.activeNone') }),
|
||||
offers: h('ul', { class: 'cards' }),
|
||||
offersNone: h('p', { class: 'hint', text: t('contracts.offersNone') }),
|
||||
};
|
||||
els.eventBox.append(els.eventTitle, els.eventText, els.eventTime, els.claim);
|
||||
els.activeBox.append(els.activeTitle, els.activeReward, els.activeProgress, els.activeText, els.abandon);
|
||||
|
||||
root.replaceChildren(
|
||||
h(
|
||||
'section',
|
||||
{ class: 'panel' },
|
||||
h('h2', { class: 'panel__title', text: t('contracts.events') }),
|
||||
els.eventBox,
|
||||
els.eventNone,
|
||||
h('h3', { class: 'dialog__subtitle', text: t('contracts.effects') }),
|
||||
els.buffs,
|
||||
),
|
||||
h(
|
||||
'section',
|
||||
{ class: 'panel' },
|
||||
h('h2', { class: 'panel__title', text: t('contracts.active') }),
|
||||
els.activeBox,
|
||||
els.activeNone,
|
||||
h('h3', { class: 'dialog__subtitle', text: t('contracts.board') }),
|
||||
h('p', { class: 'hint', text: t('contracts.boardInfo', { seconds: ctx.rules.contracts.offerEverySeconds }) }),
|
||||
els.offers,
|
||||
els.offersNone,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function eventText(type) {
|
||||
const cfg = ctx.rules.events.types.find((e) => e.id === type);
|
||||
return t(`event.${type}.text`, {
|
||||
value: cfg?.buff ? fmt.number(cfg.buff.value) : '',
|
||||
seconds: cfg?.buff ? cfg.buff.seconds : '',
|
||||
});
|
||||
}
|
||||
|
||||
function updateEvent(state) {
|
||||
const current = state.events.current;
|
||||
els.eventBox.hidden = !current;
|
||||
els.eventNone.hidden = Boolean(current);
|
||||
if (!current) return;
|
||||
setText(els.eventTitle, t(`event.${current.type}.title`));
|
||||
setText(els.eventText, eventText(current.type));
|
||||
setText(els.eventTime, t('contracts.timeLeft', { time: formatDuration(current.remaining) }));
|
||||
}
|
||||
|
||||
function updateBuffs(state) {
|
||||
const signature = state.events.buffs.map((b) => `${b.type}:${b.value}`).join();
|
||||
if (signature !== buffsSignature) {
|
||||
buffsSignature = signature;
|
||||
els.buffs.replaceChildren(
|
||||
...state.events.buffs.map((b) =>
|
||||
h(
|
||||
'li',
|
||||
{ class: 'card' },
|
||||
h('div', { class: 'card__body' }, h('h3', { class: 'card__title', text: t(BUFF_LABEL[b.type], { value: fmt.number(b.value) }) }), h('p', { class: 'card__meta' })),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
[...els.buffs.children].forEach((li, i) => {
|
||||
const buff = state.events.buffs[i];
|
||||
if (buff) setText(li.querySelector('.card__meta'), t('contracts.timeLeft', { time: formatDuration(buff.remaining) }));
|
||||
});
|
||||
}
|
||||
|
||||
function updateActive(state) {
|
||||
const active = state.contracts.active;
|
||||
els.activeBox.hidden = !active;
|
||||
els.activeNone.hidden = Boolean(active);
|
||||
if (!active) return;
|
||||
const { offer } = active;
|
||||
setText(els.activeTitle, t(`contracts.template.${offer.template}`));
|
||||
setText(els.activeReward, rewardText(offer.reward, fmt, offer.seconds));
|
||||
els.activeProgress.max = offer.target;
|
||||
els.activeProgress.value = active.progress;
|
||||
setText(
|
||||
els.activeText,
|
||||
t('contracts.progress', {
|
||||
done: fmt.number(Math.floor(active.progress)),
|
||||
target: fmt.number(offer.target),
|
||||
time: formatDuration(active.remaining),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function updateOffers(state) {
|
||||
const offers = state.contracts.offers;
|
||||
const signature = offers.map((o) => `${o.template}:${o.target}:${o.reward.type}:${o.reward.amount}`).join();
|
||||
if (signature !== offersSignature) {
|
||||
offersSignature = signature;
|
||||
els.offers.replaceChildren(
|
||||
...offers.map((offer, index) =>
|
||||
h(
|
||||
'li',
|
||||
{ class: 'card' },
|
||||
h(
|
||||
'div',
|
||||
{ class: 'card__body' },
|
||||
h('h3', { class: 'card__title', text: t(`contracts.template.${offer.template}`) }),
|
||||
h('p', { class: 'card__desc', text: t('contracts.goal', { target: fmt.number(offer.target), duration: formatDuration(offer.seconds) }) }),
|
||||
h('p', { class: 'card__meta', text: rewardText(offer.reward, fmt, offer.seconds) }),
|
||||
),
|
||||
h('button', { class: 'btn btn--buy', type: 'button', text: t('contracts.accept'), 'data-index': index, onclick: () => actions.accept(index) }),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
els.offersNone.hidden = offers.length > 0;
|
||||
for (const button of els.offers.querySelectorAll('button')) button.disabled = Boolean(state.contracts.active);
|
||||
}
|
||||
|
||||
function update(state) {
|
||||
updateEvent(state);
|
||||
updateBuffs(state);
|
||||
updateActive(state);
|
||||
updateOffers(state);
|
||||
}
|
||||
|
||||
return { rebuild, update };
|
||||
}
|
||||
Reference in New Issue
Block a user