// ============ economy.js — money, finance cycles, marketing ============ import { fmtMoney } from '../core/util.js'; export function pay(state, amount, category, note) { state.cash -= amount; pushFin(state, category, -amount); return true; } export function earn(state, amount, category, note) { state.cash += amount; pushFin(state, category, amount); return true; } function pushFin(state, category, amount) { const m = state.finance.current; m[category] = (m[category] || 0) + amount; } export const FIN_CATEGORIES = [ ['rideTickets', 'Ride tickets'], ['shopSales', 'Shop sales'], ['entrance', 'Entrance fees'], ['construction', 'Construction'], ['wages', 'Staff wages'], ['research', 'Research'], ['marketing', 'Marketing'], ['heroes', 'Heroes & gear'], ['loot', 'Monster loot'], ['runCosts', 'Ride running costs'], ['misc', 'Misc'], ['loans', 'Loans'], ]; /** Monthly finance close: wages, interest, archive */ export function monthClose(state) { // wages let wages = 0; for (const s of state.staff) wages += s.wage; for (const r of state.rides) wages += Math.round(r.def.runCost); pay(state, wages, 'wages'); // loan interest 1%/month if (state.loan > 0) { const interest = Math.ceil(state.loan * 0.01); pay(state, interest, 'loans'); } // archive current month const cur = { ...state.finance.current }; state.finance.history.push(cur); if (state.finance.history.length > 36) state.finance.history.shift(); state.finance.current = {}; state.lastMonthProfit = Object.entries(cur).reduce((a, [, v]) => a + v, 0); return wages; } // ---------------- Marketing campaigns ---------------- export const CAMPAIGNS = [ { id: 'flyers', name: 'Fairy Flyer Drop', cost: 400, weeks: 6, pull: 1.6 }, { id: 'heralds', name: 'Town Crier Heralds', cost: 900, weeks: 8, pull: 2.4 }, { id: 'crystal', name: 'Crystal Ball Vision', cost: 1800, weeks: 10, pull: 3.6 }, ]; export function startCampaign(state, id) { const c = CAMPAIGNS.find(c => c.id === id); if (!c || state.cash < c.cost) return false; pay(state, c.cost, 'marketing'); state.campaigns.push({ id: c.id, name: c.name, weeksLeft: c.weeks, pull: c.pull }); return true; } export function campaignPull(state) { let p = 0; for (const c of state.campaigns) p += c.pull; return p; } export function tickCampaigns(state) { for (let i = state.campaigns.length - 1; i >= 0; i--) { state.campaigns[i].weeksLeft--; if (state.campaigns[i].weeksLeft <= 0) state.campaigns.splice(i, 1); } } // ---------------- Loan ---------------- export function takeLoan(state, amount) { amount = Math.min(amount, state.loanLimit - state.loan); if (amount <= 0) return false; state.loan += amount; earn(state, amount, 'loans'); return true; } export function repayLoan(state, amount) { amount = Math.min(amount, state.loan, state.cash); if (amount <= 0) return false; state.loan -= amount; pay(state, amount, 'loans'); return true; }