// Master of Vega — human-readable descriptions for `tech.effects` values. // Headless, no Phaser: kept separate from VegaTurnReport.js so any other // screen (a future tech-tree view, say) can reuse the same wording without // pulling in turn-report-specific code. // // Every formatter is hand-matched to how the effect is actually consumed // elsewhere in the engine (VegaCombat.js/VegaLogic.js/VegaShips.js) — not a // generic key/value dump. A few effects (cloaked, scanRange, singularity) // are currently inert stats with no downstream mechanic wired up yet; their // wording stays modest/flavor rather than promising a numeric benefit that // doesn't exist in the sim. const pct = (mult) => `${Math.round(Math.abs(mult - 1) * 100)}%`; function describeWeapon(w) { const perRound = w.shots > 1 ? `, ${w.shots} shots per round` : ''; const pierce = w.shieldPierce ? `, pierces ${w.shieldPierce} point${w.shieldPierce === 1 ? '' : 's'} of enemy shields` : ''; const cracker = w.planetCracker ? ' — powerful enough to crack a planet apart' : ''; return `New ${w.kind} weapon available: ${w.name}, ${w.min}-${w.max} damage per shot${perRound}${pierce}${cracker}.`; } function hostilityWorlds(rules, tier) { const names = rules.planetTypes .filter((t) => t.colonizable && t.hostility === tier) .map((t) => t.name); return names.length ? `${names.join('/')}-class` : `hostility ${tier}`; } const FORMATTERS = { armor: (rules, v) => `Hull armor upgraded to ${v.name} plating — hull hit points ×${v.hpMult} (+${pct(v.hpMult)}).`, cloaked: () => 'Ships are fitted with a stealth field, cloaking them from enemy sensors.', colonizeHostility: (rules, v) => `Colonists can now settle ${hostilityWorlds(rules, v)} worlds.`, counterEspionage: (rules, v) => `+${v} counter-espionage — makes it harder for enemy agents to steal your technology.`, engine: (rules, v) => `Engines upgraded to ${v.name} Drive (speed ${v.speed}).`, espionage: (rules, v) => `+${v} espionage — improves your odds of stealing enemy technology.`, factoryCostMult: (rules, v) => `Factories cost ${pct(v)} less to build.`, fuelRange: (rules, v) => `Fuel range extended to ${v} parsecs — fleets can be ordered further from friendly colonies and starbases.`, groundAttack: (rules, v) => `+${v} ground attack — improves the odds of a successful invasion.`, groundDefense: (rules, v) => `+${v} ground defense — colonies field more defenders when invaded.`, initiative: (rules, v) => `+${v} initiative — fleets choose their engagement range before slower opponents each combat round.`, maxPopBonus: (rules, v) => `+${v} maximum population per colony.`, planetaryShield: (rules, v) => ( `+${v} planetary shield — cuts population lost to bombardment by about ${Math.round((1 - 1 / (1 + v * 0.15)) * 100)}%.` ), redirectInFlight: () => 'Fleets already in transit can be redirected to a new destination.', refitCostMult: (rules, v) => `Auto-refit costs reduced by ${pct(v)}.`, repairPerRound: (rules, v) => `Ships self-repair ${Math.round(v * 100)}% of max hull every combat round.`, researchMult: (rules, v) => `Research output increased by ${pct(v)} empire-wide.`, scanRange: (rules, v) => `+${v} scanner range for detecting distant fleets and systems.`, shield: (rules, v) => `Deflector shields absorb ${v} point${v === 1 ? '' : 's'} of damage from every incoming hit, on ships and planetary defenses alike.`, singularity: () => "A breakthrough in exotic physics — the foundation for the galaxy's ultimate weapon.", targeting: (rules, v) => `Combat accuracy increased by ${Math.round(v * 6)}% (better targeting computers).`, wasteMult: (rules, v) => `Industrial waste reduced by ${pct(v)}.`, weapon: (rules, v) => describeWeapon(v), }; /** Turns a tech's `effects` object into an array of full sentences, one per effect. */ export function describeTechEffects(rules, effects) { return Object.entries(effects ?? {}) .map(([key, value]) => FORMATTERS[key]?.(rules, value)) .filter(Boolean); }