fertig-classic-games/src/games/mastervega/VegaTechEffects.js

64 lines
4.0 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.

// 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);
}