Files
Battle-for-Tismo/shared/data/combat.js
T
adrien bd9b206708 Gave the new buildings real effects
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.
2026-09-21 11:38:01 +02:00

86 lines
3.5 KiB
JavaScript

// Combat, garrison and pillage rules. Shared so the server (which applies them)
// and the browser (which forecasts them) compute the same numbers.
// Units garrisoned in a friendly city regain this many hit points each hour.
export const CITY_GARRISON_HEAL_PER_HOUR = 1;
// Combat is fought on a single tile: the attacking stack charges onto the
// defending stack's tile and the two share it until one side is wiped out.
// Every day a battle lasts the tile loses this fraction of its population and
// of its GDP per capita. Once the fighting stops, GDP per capita recovers by
// `recoveryPerDay` each day, starting `recoveryDelayDays` after the last battle.
export const BATTLE = {
populationLossPerDay: 0.3,
gdpPerCapitaLossPerDay: 0.3,
recoveryDelayDays: 30,
recoveryPerDay: 100,
// Structures on a battlefield take this much damage each day of fighting.
structureDamagePerDay: 120,
};
// Pillaging: each unit removes this fraction of the tile's remaining
// population, cuts its GDP per capita by this multiplier, and heals one hit
// point per this many people driven off.
export const PILLAGE = {
populationLoss: 0.1,
gdpPenalty: 0.7,
healPerPeople: 1000,
};
// Trenches: infantry dug into a tile are much harder to dislodge, at the cost
// of the local economy. The defense figures are multipliers on a unit's base
// defense; melee attackers get no bonus, artillery is heavily blunted.
export const TRENCH = {
gdpMultiplier: 0.8,
meleeDefenseMultiplier: 2.0,
artilleryDefenseMultiplier: 3.0,
};
// Sustained bombardment: a ground or naval battery ordered onto a target fires
// one volley every in-game hour. Each volley deals this fraction of the damage
// a single strike would (attack minus the defender's effective defense), so a
// unit under fire is worn down over many hours instead of erased in one salvo.
export const BOMBARD = {
hourlyDamageFraction: 0.1,
};
// Bombarding a city that has no garrison left: each point of damage kills this
// many people and leaves the usual battle scar on its tile. A blow can also
// knock a building down a level; each building rolls its own chance per point
// of damage, scaled by its `destructionResistance` (wartime shelters resist
// almost all of it and never shield the rest of the city).
export const CITY_BOMBARD = {
populationPerDamage: 10,
buildingDestructionChancePerDamage: 0.0004,
};
// Aircraft sorties: a plane flies to its target, bombs once, returns to a
// friendly airport and then cannot strike again for `cooldownHours` (two days).
// Each attacking aircraft costs `cost` from its nation's budget, charged up
// front so bombing cannot be spammed for free.
export const AIR_STRIKE = {
cost: 10_000_000,
cooldownHours: 48,
};
// A city's air defense fires one volley at a hostile aircraft the moment it
// enters the city's tile. Damage scales with the building's level.
export const AIR_DEFENSE = {
damagePerLevel: 150,
};
// The result of pillaging a tile with `count` units in sequence, starting from
// its current population. Each step removes a tenth of what is left and heals
// for the people it removed; the GDP-per-capita multiplier compounds. Shared so
// the server and the forecast tooltip compute the same numbers.
export function pillageSteps(population, count) {
const steps = [];
let remaining = population;
for (let i = 0; i < count; i++) {
const removed = remaining * PILLAGE.populationLoss;
remaining -= removed;
steps.push({ removed, remaining, heal: removed / PILLAGE.healPerPeople });
}
return { steps, gdpMultiplier: Math.pow(PILLAGE.gdpPenalty, count) };
}