User Tools

Site Tools


manual:subwaysim:map_construction:create_timetable

This is an old revision of the document!


Create Timetables

Timetables define the AI service pattern on a map:

  • which trains spawn (compositions)
  • which route they drive (stops)
  • on which platforms they stop
  • when and how often services repeat
  • how depot and dispatching logic supports the timetable traffic

Timetables are usually created in your map's Map.lua inside:

  • `function <MapClass>:loadTimetables()`

This page explains the full timetable workflow using the TestMap example.

Related:


Prerequisites

Before creating timetables, ensure:

  • stations are fully defined in `loadStations()`
  • platform numbers / lengths / directions are final
  • the map loads correctly without timetables first (recommended)

Timetables reference station objects, so stations must exist before you build schedules.


Timetables in Map.lua (Where they “live”)

A typical `loadTimetables()` builds:

  • `self.timetables` — list of actual service entries (the ones that spawn trains)
  • templates per line/direction (used for cloning)
  • optional lookup tables (`self.templatesByLine`, `self.templatesByDirection`)
  • depot spaces (`self.depots`)
  • dispatching strategies (`self.dispatchingStrategies`)

At the end, the map registers them via:

controlCenter:setTimetableList(self.timetables, self.dispatchingStrategies, self.depots);

Step 1 — Create Templates (Per Line & Direction)

Templates describe the route and the allowed compositions, but do not spawn trains by themselves.

Example:

-- Direction 1 (TS -> TSA)
self.TestLine_Dir1 = Timetable:new("U1", 0)
	:addTrainComposition("Berlin_HK_1x", 0.5)
	:addTrainComposition("Berlin_HK_2x")
	:addTrainComposition("Berlin_A3L92_1x", 0)
	:addTrainComposition("Berlin_A3L92_2x", 0)
	:addTrainComposition("Berlin_A3L92_3x", 0.5)
	:addTrainComposition("Berlin_A3L92_4x")
Parameter Description
`“U1”` Line name used for UI and routing logic.
`0` Variant / index value (map-specific usage).

Step 2 — Add Stops (Route Definition)

Stops define the route as a sequence of station/platform/time entries.

:addStop({
	station = self.stations.TS,
	platform = 2,
	departure = 0,
	speedLimit = 70,
	routeSettingMaxETA = 0.5,
})
Field Type Description
station Station Reference to a station defined in `loadStations()`.
platform number Platform number the train uses at this station. Must exist in BP_StationDefinition.
departure number Minutes after service start/spawn when the train departs this stop.
speedLimit number Speed limit applied after departing this stop (signal logic dependent).
routeSettingMaxETA number (optional) How many minutes before departure the route (Fahrstraße) should be requested/set.
altPlatform table<string> (optional) Alternative platforms that may be used if the primary platform is unavailable.

Step 3 — Alternative Platforms (altPlatform)

Example:

altPlatform = { "2", }

Use strings (`“1”`, `“2”`) because platform identifiers are commonly handled as strings in dispatch/routing.


Step 4 — Composition Weights

Weights control probability of selecting a composition for AI spawning.

Weight Meaning
1.0 Standard usage
0.5 Reduced probability
0.0 Excluded from AI spawning in this timetable

A composition with weight `0.0` can still exist in the content system and be selectable for the player.


Step 5 — Create Real Services (clone + DayMask)

Templates must be cloned into real timetable entries.

local DM = DayMask;
DayMask Meaning
DM.Weekdays Monday to Friday
DM.Weekends Saturday and Sunday
DM.Sat Saturday only
DM.Sun Sunday only
DM.Always Every day

5.1 Repeating Interval Services

TableUtil.insertList(self.timetables, self.TestLine_Dir1:clone(daytime(04, 30)):repeatUntil(daytime(23, 30), 10));
TableUtil.insertList(self.timetables, self.TestLine_Dir2:clone(daytime(04, 35)):repeatUntil(daytime(23, 35), 10));
Call Description
clone(daytime(HH, MM), DayMask) Creates the first entry at a given time (filtered by day mask if provided).
repeatUntil(daytime(HH, MM), interval) Repeats every X minutes until the end time.
TableUtil.insertList(list, result) Inserts all generated entries into `self.timetables`.

5.2 Single Manual Trips

table.insert(self.timetables, self.TestLine_Dir1:clone(daytime(12, 07), DM.Weekdays));
table.insert(self.timetables, self.TestLine_Dir2:clone(daytime(12, 12), DM.Weekdays));

Use this when you need exact control (first/last train, gaps, specials).


Step 6 — Useful Variations

6.1 Short Runs (Start/Terminate Early)

Terminate at `TSD`:

local TS_to_TSD = self.TestLine_Dir1:clone(0, nil, true):terminateAtStation("TSD", true);
table.insert(self.timetables, TS_to_TSD:clone(daytime(05, 10), DM.Weekdays));

Start at `TSD`:

local TSD_to_TSA = self.TestLine_Dir1:clone(0, nil, true):startAtStation("TSD", true);
table.insert(self.timetables, TSD_to_TSA:clone(daytime(05, 20), DM.Weekdays));

6.2 Platform Overrides

local TS_Platform1 = self.TestLine_Dir1:clone(0, nil, true);
TS_Platform1:getFirstStop().platform = 1;
 
table.insert(self.timetables, TS_Platform1:clone(daytime(06, 00), DM.Weekdays));

6.3 Service Runs (Non-Passenger Moves)

local DP_to_TS_SR = self.TestLine_Dir2:clone(0, nil, true)
	:startAtStation("DP", true)
	:terminateAtStation("TS", true)
	:setIsServiceRun(true);
 
table.insert(self.timetables, DP_to_TS_SR:clone(daytime(04, 10), DM.Weekdays));

6.4 Force Unique Stop Lists

local Variant = self.TestLine_Dir1:clone(0, nil, true);
Variant:forceUniqueStopList();

Step 7 — Depots and Dispatching

Depots and dispatching strategies support the timetable traffic and keep trains moving.

7.1 Depots (Depot Spaces)

`self.depots` groups depot tracks into named blocks.

Field Meaning
station Station reference (must exist in `self.stations`)
platform Track / platform ID as defined in the BP_StationDefinition
direction Which direction trains should park/spawn facing (1 or 2)
noParkingTimetable If true: no dedicated parking timetable is generated

Example:

---@type table<string, Depot_DepotSpace[]>
self.depots = {
 
	["DP_51_54"] = {
		{ station = self.stations.DP, platform = "51", direction = 2, noParkingTimetable = false },
		{ station = self.stations.DP, platform = "52", direction = 2, noParkingTimetable = false },
		{ station = self.stations.DP, platform = "53", direction = 2, noParkingTimetable = false },
		{ station = self.stations.DP, platform = "54", direction = 2, noParkingTimetable = false },
	},
 
	["DP_60"] = {
		{ station = self.stations.DP, platform = "60", direction = 2, noParkingTimetable = true },
	},
};

7.2 Dispatching Strategies (Turnarounds / Depot Moves)

Dispatching strategies define how trains are handled outside normal passenger services:

  • turnarounds at terminals
  • spawning trains from depots
  • sending trains back to depots
  • resolving conflicts / keeping traffic stable

Basic structure:

---@type table<Station, ControlCenter_DispatchingStrategy[]>
self.dispatchingStrategies = {
    [self.stations.TS] = {
        -- strategies for TS
    },
}

Strategies are evaluated top to bottom (order matters).


7.2.1 Pattern A — Simple Turnaround

{
	sourceStation = self.stations.TS,
	targetStation = self.stations.TS,
	sourcePlatforms = { "1", "2" },
	targetPlatforms = { "1", "2" },
	replaceFirstPlatform = true,
	keepLine = false,
	minLayover = 4,
}

7.2.2 Pattern B — Turnaround with Internal Movement

Hidden timetables are used for internal shunting and must be service runs:

{
	sourceStation = self.stations.Go,
	targetStation = self.stations.Go,
	sourcePlatforms = { "1" },
	targetPlatforms = { "2" },
	minLayover = 3,
	timetable = Timetable:new("", 0)
		:setIsServiceRun(true)
		:addStop({
			station = self.stations.Go,
			platform = "6",
			departure = 2,
			turnAround = true,
		})
		:addStop({
			station = self.stations.Go,
			platform = "2",
			departure = 3,
		}),
}

7.2.3 Pattern C — Spawning Trains from a Depot

{
	sourceStation = nil,
	targetStation = self.stations.WA,
	targetPlatforms = { "1", "2" },
	depotName = "WA_06_09",
	overrideFirstPlatform = "3",
	timetable = Timetable:new("", 0)
		:setIsServiceRun(true)
		:addStop({
			station = self.stations.WA,
			platform = "7",
			departure = -5,
		})
		:addStop({
			station = self.stations.WA,
			platform = "3",
			departure = -3,
		}),
}

`sourceStation = nil` means the train comes from a depot.


7.2.4 Pattern D — Sending Trains to a Depot

{
	sourceStation = self.stations.WA,
	sourcePlatforms = { "1", "2" },
	targetStation = nil,
	depotName = "WA_11_18",
	timetable = Timetable:new("", 0)
		:setIsServiceRun(true)
		:addStop({
			station = self.stations.WA,
			platform = "3",
			departure = 2,
		})
		:addStop({
			station = self.stations.WA,
			platform = "11",
			departure = 6,
		}),
}

`targetStation = nil` means the train leaves traffic into a depot.


7.2.5 Hidden Timetables

Hidden timetables:

  • are not shown to the player
  • should always use `setIsServiceRun(true)`
  • are used only for internal movements

Common Pitfalls

  • station short names not matching BP_StationDefinition
  • platform ids mismatching the BP_StationDefinition platform array
  • compositions not registered or misspelled
  • wrong dispatching strategy order
  • forgetting to insert cloned services into `self.timetables`

Next Steps

After your timetables are configured:

  • build and test your mod

Build Mod (.pak)


© 2025 Simuverse Interactive · SubwaySim 2 Modding Wiki

All trademarks and registered trademarks are the property of their respective owners. This Wiki is provided for documentation and modding purposes only.

2025/12/12 12:06 · dcs
manual/subwaysim/map_construction/create_timetable.1769509209.txt.gz · Last modified: by dcs

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki