stations

Station type registry. Register, patch and read the StationTypeStatsItem records that set a station's walk catchment, transfer radius, walk speed and extra dwell.

api.stations. 4 members.

MemberReturnsSummary
registerStationType(stationType)voidRegister a station type.
modifyStationType(id, overrides)voidPatch a registered station type.
getStationTypes()Record<string, StationTypeStatsItem>The live station type registry, keyed by id.
getStationType(id)StationTypeStatsItem or undefinedOne station type record by id.

registerStationType#

api.stations.registerStationType(stationType: StationTypeStatsItem): void

Register a station type.

Writes a normalized copy of stationType to the registry under its id, replacing any existing entry. Missing fields take defaults: name the id, catchmentMultiplier 1.0, transferRadiusMultiplier 1.0, walkSpeedMultiplier 1.0, extraDwellTime 0. The overrides, description, icon and color stay undefined when omitted. The registry is pushed to the sim host worker when it runs. Commute pathfinding workers receive it with every batch. Logs [Modding API] Registering station type: <name> (<id>), or Updating for an existing id. reloadMods keeps registered types.

Parameter stationType (StationTypeStatsItem): StationTypeStatsItem; id required.

Errors:

  • falsy object or missing id: logs [Modding API] Invalid station type - must have id, does nothing.
  • exception: logs [Modding API] Error registering station type:.

Side effects: STATION_TYPES[id]; sim host worker constants push.

Changed: the registry reaches the sim host worker and the commute pathfinding workers; walkSpeedOverride divides by WALKING_SPEED_STRAIGHT_LINE for origin and destination walks, the same as transfers; the drive catchment follows catchmentOverride instead of catchmentMultiplier (PR #1090).

js
api.stations.registerStationType({ id: 'bus-hub', name: 'Bus Connection Hub', catchmentMultiplier: 2, transferRadiusMultiplier: 3, walkSpeedMultiplier: 1.5, extraDwellTime: 30 });
// walk catchment 5400 s, transfer radius 1800 s, walk times divided by 1.5, scheduled dwell 30 s longer at stations of this type

modifyStationType#

api.stations.modifyStationType(id: string, overrides: Partial<StationTypeStatsItem>): void

Patch a registered station type.

Shallow-merges overrides into the existing record. After the merge id is kept, and name, the three multipliers and extraDwellTime are refilled with the registerStationType defaults when missing. The registry is pushed to the sim host worker when it runs. Logs [Modding API] Modifying station type: <id> (development builds only).

ParamTypeDefaultDescription
idstringrequiredid of a registered station type, including standard.
overridesPartial<StationTypeStatsItem>requiredpartial StationTypeStatsItem; id is ignored.

Errors:

  • unknown id: logs [Modding API] Station type "<id>" not found, does nothing.
  • exception: logs [Modding API] Error modifying station type:.

Side effects: STATION_TYPES[id]; sim host worker constants push.

Changed: defaults are refilled after the merge and id is fixed; the registry is pushed to the sim host worker (PR #1090).

js
// every standard station draws riders from twice as far
api.stations.modifyStationType('standard', { catchmentMultiplier: 2 });

getStationTypes#

api.stations.getStationTypes(): Record<string, StationTypeStatsItem>

The live station type registry, keyed by id.

Returns: Record<string, StationTypeStatsItem>. the registry object itself; standard is registered at startup; a direct mutation is not pushed to the sim host worker.

js
for (const [id, t] of Object.entries(api.stations.getStationTypes())) {
    console.log(`${id}: ${t.name}, catchment x${t.catchmentMultiplier}`);
}

getStationType#

api.stations.getStationType(id: string): StationTypeStatsItem | undefined

One station type record by id.

Parameter id (string): station type id.

Returns: StationTypeStatsItem | undefined. the live record; undefined for an unknown id. The game's own lookups fall back to standard.

js
const standard = api.stations.getStationType('standard');
if (standard) console.log(`Extra dwell: ${standard.extraDwellTime} s`);

StationTypeStatsItem#

One station type record, selected per station through station.stationType.

Built-in standard: multipliers 1.0, extraDwellTime 0, no overrides. Catchment and walk speed apply to origin and destination walks in commute pathfinding. Transfer radius and walk speed apply to transfer links, measured against the station being walked to. extraDwellTime applies in the train sim. A station whose type id is not registered uses standard for every value. The station panel shows a type dropdown when more than one type is registered.

FieldTypeDefaultDescription
idstringrequiredRegistry key; stored on each station as station.stationType.
namestringidLabel in the station panel type dropdown.
descriptionstringnoneText under the type dropdown in the station panel; nothing when omitted.
catchmentMultipliernumber1.0Walk catchment = pathfinding rule MAX_WALK_TO_FROM_STATION (2700 s) times this; ratio. The drive catchment scales by the same ratio.
transferRadiusMultipliernumber1.0Transfer radius = pathfinding rule MAX_TRANSFER_WALKING_TIME (600 s) times this; ratio.
walkSpeedMultipliernumber1.0Origin and destination walk times at this station, and transfer walk times to it, are divided by this; ratio.
extraDwellTimenumber0Added to the train type's stopTimeSeconds at every stop here; s.
catchmentOverridenumbernoneReplaces the walk catchment; s; catchmentMultiplier is ignored when set. The drive catchment becomes MAX_DRIVE_TO_FROM_STATION (420 s) times this over MAX_WALK_TO_FROM_STATION.
transferRadiusOverridenumbernoneReplaces the transfer radius; s; transferRadiusMultiplier is ignored when set.
walkSpeedOverridenumbernonem/s; when set, walk times are divided by this over the rule WALKING_SPEED_STRAIGHT_LINE (1.5 m/s) in place of walkSpeedMultiplier.
iconstringnoneStored on the record; no reader in the game.
colorstringnoneStored on the record; no reader in the game.

How Catchment Works#

Each station type scales three base values. The bases are pathfinding rules and game constants, so modifyPathfindingRules and modifyConstants change them for every type; the multipliers apply to the current value.

ValueBaseStation type fieldOverride field
Walk catchment (origin and destination walks)PATHFINDING_RULES.MAX_WALK_TO_FROM_STATION, 2700 scatchmentMultipliercatchmentOverride (s)
Transfer radius (walks to this station from another)PATHFINDING_RULES.MAX_TRANSFER_WALKING_TIME, 600 stransferRadiusMultipliertransferRadiusOverride (s)
Walk speedRULES.WALKING_SPEED_STRAIGHT_LINE, 1.5 m/s (RULES.WALKING_SPEED_ACCURATE_PATH along a walk network)walkSpeedMultiplier; walk times are divided by itwalkSpeedOverride (m/s), divided by WALKING_SPEED_STRAIGHT_LINE
Dwellthe train type's stopTimeSecondsextraDwellTime (s, added)none

An override replaces its multiplier. The drive catchment (PATHFINDING_RULES.MAX_DRIVE_TO_FROM_STATION, 420 s, read only while the Drive-to-Station Access feature flag is on) scales by the same ratio as the walk catchment.

With catchmentMultiplier: 2, commuters walk up to 5400 s to reach the station. With transferRadiusMultiplier: 3, transfers to it may take up to 1800 s on foot.

Commute pathfinding workers receive the registry with every batch, and the sim host worker receives it when it runs, so registered and modified types apply in the simulation.

Assigning Station Types#

A station's type is station.stationType; a station whose type id is not registered uses standard for every value. When more than one type is registered, the station details panel shows a type dropdown. Picking a type rebuilds the stations, which recomputes each station's nearbyStations transfer links with the new radius and walk speed. The API has no setter for a station's type.

Example Station Types#

icon and color are stored on the record but nothing in the game reads them, so these examples leave them out.

Park and Ride#

Wide catchment for stations with parking.

js
api.stations.registerStationType({
    id: 'park-and-ride',
    name: 'Park & Ride',
    description: 'Parking lot; serves a wider suburban area.',
    catchmentMultiplier: 5, // walk catchment 13500 s
    walkSpeedMultiplier: 1,
    extraDwellTime: 25,
});

Express Station#

Small catchment, short extra dwell.

js
api.stations.registerStationType({
    id: 'express',
    name: 'Express Station',
    description: 'Limited-stop station with faster boarding.',
    catchmentMultiplier: 0.8,
    walkSpeedMultiplier: 1,
    extraDwellTime: 10,
});

Airport Terminal#

Large catchment, slow walking, long dwell. A fixed transfer radius replaces the multiplier.

js
api.stations.registerStationType({
    id: 'airport',
    name: 'Airport Terminal',
    description: 'Long walks with luggage.',
    catchmentMultiplier: 3,
    transferRadiusOverride: 1200, // s
    walkSpeedMultiplier: 0.5, // walk times doubled
    extraDwellTime: 45,
});

Transit Center#

Major transfer hub.

js
api.stations.registerStationType({
    id: 'transit-center',
    name: 'Transit Center',
    description: 'Hub with many connections.',
    catchmentMultiplier: 2.5,
    transferRadiusMultiplier: 4, // transfers up to 2400 s on foot
    walkSpeedMultiplier: 1.2,
    extraDwellTime: 35,
});