import type { Upgrade } from "../schemas"; /** * Ship upgrades (CR-009 §2). Percentages are of the model's base stat and add * up across levels. Overrides keep models distinct (decision 0.5.67) and give * only a maxed Courier the reach to Mars from Earth (decision 0.5.68, CR-015). * Extended Fuel Tanks raise tank capacity; reach grows as capacity^(1 ÷ 0.65) * on the economic-distance curve, so its percentages are smaller than the old * range ones for the same maxed reach. */ export const upgrades: Upgrade[] = [ { id: "engines", name: "Engine Tuning", stat: "cruiseSpeedKmPerGameHour", percentPerLevel: 10, maxLevel: 3, }, { id: "cargo-bay", name: "Cargo Bay Expansion", stat: "cargoCapacityTonnes", percentPerLevel: 15, maxLevel: 3, }, { id: "fuel-tanks", name: "Extended Fuel Tanks", stat: "tankCapacityFu", // Maxed: × 1.33 capacity, ≈ × 1.55 reach (as +20 % range a level did). percentPerLevel: 11, maxLevel: 3, modelOverrides: { // Reach 4.9 → 54 → 133 → 234 M km: Earth → Mars (≈ 201) only at level 3; level 2 can't reach Mars from the Moon either (133 × 1.3 < 200). courier: { percentPerLevel: 380 }, // Reach 460 → ≈ 664 M km at level 3: short of a base Bulk Hauler's 1,250 and of Jupiter from Earth (≈ 792). freighter: { percentPerLevel: 9 }, }, }, { id: "landing-thrusters", name: "Landing Thrusters", stat: "overheadGameHours", percentPerLevel: -15, maxLevel: 3, }, { // Deferred in CR-009, added by CR-026 (decision 0.5.149): +1 hull rating a level. id: "hull-plating", name: "Hull Plating", stat: "hullRating", percentPerLevel: 0, flatPerLevel: 1, maxLevel: 3, }, { id: "handling-gear", name: "Cargo Handling Gear", stat: "handlingGameHoursPerTonne", percentPerLevel: -15, maxLevel: 3, }, ]; /** An upgrade's percent per level for a ship model, after overrides. */ export function upgradePercentPerLevel(upgrade: Upgrade, modelId: string): number { return upgrade.modelOverrides?.[modelId]?.percentPerLevel ?? upgrade.percentPerLevel; } /** An upgrade's highest level for a ship model, after overrides. */ export function upgradeMaxLevel(upgrade: Upgrade, modelId: string): number { return upgrade.modelOverrides?.[modelId]?.maxLevel ?? upgrade.maxLevel; }