The catalogue had grown a barracks, wartime shelters, an air-defense battery, a warm-water port and a shipyard, but only as data: infantry still trained without a barracks, shelters did nothing, and an airport was just an airbase. Each building now names the rule it grants with a `mechanic` id, so the simulation and the city panel describe the same thing without magic strings. - Barracks and shipyards open one more production line each. A line sticks to one entry at full rate, so two units build at once rather than the head absorbing every line; the base behaviour (one queue, overflow carrying into the next entry) is unchanged. - Wartime shelters keep 10% of civilians per level safe from bombardment and are very hard to knock down, and ranged fire can now destroy a building level outright, with no refund. Each building rolls its own chance per point of damage, from a generator seeded off the world so a bombardment replays identically. - Air defense fires one volley at a hostile aircraft the moment it enters the city tile, scaled by its level; a plane shot down never drops its bombs. - A port adds 1000 GDP per capita per level, per adjacent sea tile, to every tile in its region. - An airport draws a daily trickle of people from every other airport city in the world, scaled by the destination's level. - Wired the new effects into the city panel and taught the repeatable Industrial Automation to satisfy other technologies' prerequisites. Added tests for each mechanic and for the parallel lines.
166 lines
5.5 KiB
JavaScript
166 lines
5.5 KiB
JavaScript
// Buildings that can be raised in a city. Build costs are fixed and grow only
|
|
// with the level, with no level cap; upkeep is 1% of that cost, so it follows
|
|
// the level too.
|
|
|
|
import { EFFECT_GDP, EFFECT_BUDGET_INCOME, EFFECT_RESEARCH, EFFECT_CULTURE, effect } from "./effects.js";
|
|
|
|
// Buildings whose benefit is a rule rather than a stat effect. Kept as ids so
|
|
// the simulation and the UI can name them without magic strings.
|
|
export const BUILDING_MECHANIC = {
|
|
// Units: one more parallel training line per level.
|
|
PARALLEL_TRAINING: "parallel_training",
|
|
// Buildings: one more parallel construction line per level.
|
|
PARALLEL_BUILDING: "parallel_building",
|
|
// Cuts civilian deaths from bombing, and is very hard to knock down.
|
|
CIVILIAN_SHELTER: "civilian_shelter",
|
|
// Fires one volley at hostile aircraft passing over the city.
|
|
AIR_DEFENSE: "air_defense",
|
|
// Flat GDP per capita for the city's region, per adjacent sea tile.
|
|
PORT_GDP: "port_gdp",
|
|
// Lets people fly in from any other city with an airport.
|
|
AIR_IMMIGRATION: "air_immigration",
|
|
};
|
|
|
|
export const BUILDINGS = [
|
|
{
|
|
id: "market",
|
|
name: "Market",
|
|
description: "A hub of local trade. Raises the GDP per capita of the city's region, with diminishing returns.",
|
|
baseCost: 500_000,
|
|
costAlpha: 1.2,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_GDP, 0.04, 0.75)],
|
|
icon: "icon_market.svg",
|
|
},
|
|
{
|
|
id: "bank",
|
|
name: "Bank",
|
|
description: "Channels private wealth into the state coffers. Raises the tax collected from the city's region.",
|
|
baseCost: 1_000_000,
|
|
costAlpha: 1.3,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_BUDGET_INCOME, 0.05, 0.7)],
|
|
icon: "icon_bank.svg",
|
|
},
|
|
{
|
|
id: "barracks",
|
|
name: "Barracks",
|
|
description: "Enables training infantry units. Each level allows one more parallel training.",
|
|
baseCost: 10_000_000,
|
|
costAlpha: 1.1,
|
|
refundFraction: 0.5,
|
|
effects: [],
|
|
mechanic: "parallel_training",
|
|
icon: "icon_barracks.svg",
|
|
},
|
|
{
|
|
id: "shelters",
|
|
name: "Wartime shelters",
|
|
description: "Each level reduces civilian life loss from bombing by 10%. Extremely hard to destroy. Does not protect other buildings.",
|
|
baseCost: 100_000_000,
|
|
costAlpha: 2,
|
|
refundFraction: 0.5,
|
|
effects: [],
|
|
mechanic: "civilian_shelter",
|
|
civilianProtectionPerLevel: 0.1,
|
|
// Multiplies the odds of the city losing a level of this building to a
|
|
// bombardment: at a tenth of the normal chance it is very hard to destroy.
|
|
destructionResistance: 0.1,
|
|
icon: "icon_shelters.svg",
|
|
},
|
|
{
|
|
id: "aa_building",
|
|
name: "Air defense",
|
|
description: "Damages hostile aircraft that fly above this city.",
|
|
baseCost: 1_000_000_000,
|
|
costAlpha: 2,
|
|
refundFraction: 0.5,
|
|
effects: [],
|
|
mechanic: "air_defense",
|
|
icon: "icon_aa_building.svg",
|
|
},
|
|
{
|
|
id: "research_lab",
|
|
name: "Research lab",
|
|
description: "Applies science to industry and government. Produces research points for the whole nation.",
|
|
baseCost: 100_000_000,
|
|
costAlpha: 1.65,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_RESEARCH, 1.0, 0.9)],
|
|
icon: "icon_research_lab.svg",
|
|
},
|
|
{
|
|
id: "university",
|
|
name: "University",
|
|
description: "Higher education produces research and a little culture for the whole nation.",
|
|
baseCost: 100_000_000,
|
|
costAlpha: 1.7,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_RESEARCH, 2.0, 0.8), effect(EFFECT_CULTURE, 0.5, 0.7)],
|
|
icon: "icon_university.svg",
|
|
},
|
|
{
|
|
id: "museum",
|
|
name: "Museum",
|
|
description: "Preserves the nation's heritage, raising its culture output across the country.",
|
|
baseCost: 50_000_000,
|
|
costAlpha: 1.6,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_CULTURE, 1.5, 0.85)],
|
|
icon: "icon_museum.svg",
|
|
},
|
|
{
|
|
id: "cinema_studio",
|
|
name: "Cinema studio",
|
|
description: "Mass media spreads the nation's culture, raising its culture output across the country.",
|
|
baseCost: 50_000_000,
|
|
costAlpha: 1.75,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_CULTURE, 3.0, 0.7)],
|
|
icon: "icon_cinema_studio.svg",
|
|
},
|
|
{
|
|
id: "port",
|
|
name: "Port",
|
|
description: "Warm water port. Gains 1000 GDP/capita per tile per level.",
|
|
baseCost: 20_000_000,
|
|
costAlpha: 1.7,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_BUDGET_INCOME, 0.08, 0.7)],
|
|
// Every tile the city's region covers gains this much GDP per capita for
|
|
// each sea tile next to the city, per port level.
|
|
mechanic: "port_gdp",
|
|
gdpPerCapitaPerSeaTilePerLevel: 1000,
|
|
icon: "icon_port.svg",
|
|
coastal: true,
|
|
},
|
|
{
|
|
id: "airport",
|
|
name: "Airport",
|
|
description: "An airfield with a control tower. Lets the city train aircraft and serves as a home airbase for them to land and refuel. Immigration can reach this city from any other city in the world with an airport. The effect scales with airport level.",
|
|
baseCost: 250_000_000,
|
|
costAlpha: 1.7,
|
|
refundFraction: 0.5,
|
|
effects: [effect(EFFECT_GDP, 0.05, 0.8)],
|
|
mechanic: "air_immigration",
|
|
icon: "icon_airport.svg",
|
|
},
|
|
{
|
|
id: "shipyard",
|
|
name: "Shipyard",
|
|
description: "Naval yards that build warships. Only a coastal city can raise one, and it must already have a port. Each level adds one parallel building queue.",
|
|
baseCost: 150_000_000,
|
|
costAlpha: 1.65,
|
|
refundFraction: 0.5,
|
|
effects: [],
|
|
mechanic: "parallel_building",
|
|
icon: "icon_shipyard.svg",
|
|
coastal: true,
|
|
requiresBuilding: "port",
|
|
},
|
|
];
|
|
|
|
export function buildingById(id) {
|
|
return BUILDINGS.find((b) => b.id === id) || null;
|
|
}
|