manual:subwaysim:map_construction:create_timetable
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| manual:subwaysim:map_construction:create_timetable [2026/01/27 11:20] – dcs | manual:subwaysim:map_construction:create_timetable [2026/01/27 11:26] (current) – dcs | ||
|---|---|---|---|
| Line 14: | Line 14: | ||
| This page explains the full **timetable workflow** using the TestMap example. | This page explains the full **timetable workflow** using the TestMap example. | ||
| - | Related: | + | Related: [[manual: |
| - | * [[manual: | + | |
| ---- | ---- | ||
| Line 49: | Line 48: | ||
| ---- | ---- | ||
| - | ===== Step 1 — Create Templates (Per Line & Direction) ===== | + | ===== 6) Timetables |
| - | Templates describe the route and the allowed compositions, | + | Timetables define: |
| + | * which trains | ||
| + | * what route they drive (stops) | ||
| + | * on which platforms they stop | ||
| + | * how often services repeat | ||
| - | Example: | + | ==== 6.1 Timetable: |
| + | |||
| + | A timetable template is created with: | ||
| <code lua> | <code lua> | ||
| - | -- Direction 1 (TS -> TSA) | + | Timetable: |
| - | self.TestLine_Dir1 = Timetable: | + | |
| - | : | + | |
| - | : | + | |
| - | : | + | |
| - | : | + | |
| - | : | + | |
| - | : | + | |
| </ | </ | ||
| Line 70: | Line 68: | ||
| | `0` | Variant / index value (map-specific usage). | | | `0` | Variant / index value (map-specific usage). | | ||
| - | ---- | + | Templates are usually created per direction: |
| + | * Direction 1: TS → TSA | ||
| + | * Direction 2: TSA → TS | ||
| - | ===== Step 2 — Add Stops (Route Definition) ===== | + | ==== 6.2 Train Compositions |
| - | Stops define | + | Train compositions |
| + | |||
| + | Each composition is referenced by its `contentName`, | ||
| + | ContentManager (e.g. in `Vehicle.lua` or `Composition.lua`). | ||
| + | |||
| + | Example: | ||
| + | contentName = " | ||
| + | |||
| + | The name must match **exactly**. | ||
| + | If a composition is not registered or the name is incorrect, no train will spawn for it. | ||
| + | |||
| + | ==== Adding Compositions to a Timetable ==== | ||
| + | |||
| + | Compositions are added directly to the timetable template: | ||
| + | |||
| + | <code lua> | ||
| + | : | ||
| + | </code> | ||
| + | |||
| + | A weight can optionally be provided: | ||
| + | |||
| + | <code lua> | ||
| + | : | ||
| + | </code> | ||
| + | |||
| + | If no weight is specified, a default weight of `1.0` is assumed. | ||
| + | |||
| + | ==== Composition Weights ==== | ||
| + | |||
| + | Weights control how likely a composition is selected **relative to other compositions** | ||
| + | within the same timetable. | ||
| + | |||
| + | They only affect **AI spawning behavior** for this timetable. | ||
| + | |||
| + | ^ Weight ^ Meaning ^ | ||
| + | | **1.0** | Standard usage. The composition is commonly selected. | | ||
| + | | **0.5** | Reduced probability. The composition is used less frequently. | | ||
| + | | **0.0** | The composition is excluded from AI spawning for this timetable. | | ||
| + | |||
| + | ==== Important Behavior of Weight = 0.0 ==== | ||
| + | |||
| + | A weight of `0.0` prevents the composition from being selected when AI trains are spawned | ||
| + | by this timetable. | ||
| + | |||
| + | The composition itself remains a valid registered vehicle and may still: | ||
| + | * exist in the content system | ||
| + | * appear in the vehicle selection menu | ||
| + | |||
| + | This behavior is intentional and allows a composition to be: | ||
| + | * available to the player | ||
| + | * but excluded from AI traffic on a specific line or timetable | ||
| + | |||
| + | ==== 6.3 addStop() (Route Definition) ==== | ||
| + | |||
| + | Stops define the actual route of a timetable. | ||
| + | Each stop is a table passed into `addStop({ ... })`. | ||
| + | |||
| + | Example: | ||
| <code lua> | <code lua> | ||
| Line 94: | Line 151: | ||
| | altPlatform | table< | | altPlatform | table< | ||
| - | ---- | ||
| - | ===== Step 3 — Alternative Platforms | + | ==== 6.4 altPlatform (Alternative Platforms) ==== |
| Example: | Example: | ||
| Line 104: | Line 160: | ||
| </ | </ | ||
| - | Use strings | + | ⚠️ |
| - | ---- | + | This allows AI to select another platform if: |
| + | * the preferred platform is blocked | ||
| + | * dispatching assigns an alternative | ||
| - | ===== Step 4 — Composition Weights ===== | + | ==== 6.5 routeSettingMaxETA (Route Pre-Setting) |
| - | Weights control probability of selecting a composition for AI spawning. | + | Example: |
| - | ^ Weight ^ Meaning ^ | + | <code lua> |
| - | | 1.0 | Standard usage | | + | routeSettingMaxETA = 0.5 |
| - | | 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. | + | Meaning: |
| + | * the route will be requested/ | ||
| - | ---- | + | This can help avoid early route locking and improves traffic handling at busy stations. |
| - | ===== Step 5 — Create Real Services (clone + DayMask) | + | ==== 6.6 clone() + DayMask |
| - | Templates | + | A timetable template does not spawn trains by itself. |
| + | It must be cloned into **real timetable entries** and inserted into `self.timetables`. | ||
| + | |||
| + | For day-based schedules, use `DayMask`: | ||
| <code lua> | <code lua> | ||
| Line 136: | Line 197: | ||
| | DM.Always | Every day | | | DM.Always | Every day | | ||
| - | ==== 5.1 Repeating | + | The typical workflow is: |
| + | * Create a timetable template (e.g. `self.TestLine_Dir1`) | ||
| + | * Clone it for a start time (optionally with a day mask) | ||
| + | * Either insert a single trip, or generate a repeating service | ||
| + | |||
| + | ==== 6.6.1 Repeating Services | ||
| + | |||
| + | This creates a repeating service between two times: | ||
| <code lua> | <code lua> | ||
| - | TableUtil.insertList(self.timetables, | + | TableUtil.insertList( |
| - | TableUtil.insertList(self.timetables, | + | self.timetables, |
| + | self.TestLine_Dir1: | ||
| + | ); | ||
| + | |||
| + | TableUtil.insertList( | ||
| + | self.timetables, | ||
| + | self.TestLine_Dir2: | ||
| + | ); | ||
| </ | </ | ||
| ^ Call ^ Description ^ | ^ Call ^ Description ^ | ||
| - | | clone(daytime(HH, | + | | clone(daytime(HH, |
| | repeatUntil(daytime(HH, | | repeatUntil(daytime(HH, | ||
| | TableUtil.insertList(list, | | TableUtil.insertList(list, | ||
| - | ==== 5.2 Single Manual Trips ==== | + | Result: |
| + | * a full service pattern is generated automatically | ||
| + | |||
| + | ==== 6.6.2 Single | ||
| + | |||
| + | If you want to schedule **individual trips** (first/last train, gaps, special runs), | ||
| + | insert a single cloned entry: | ||
| <code lua> | <code lua> | ||
| Line 155: | Line 236: | ||
| </ | </ | ||
| - | Use this when you need exact control (first/last train, gaps, specials). | + | This creates exactly one departure at the given time. |
| - | ---- | + | Use this approach when you need full control over: |
| + | * exact departure times | ||
| + | * exceptions or gaps | ||
| + | * different patterns on different days | ||
| - | ===== Step 6 — Useful Variations ===== | ||
| - | ==== 6.1 Short Runs (Start/ | + | ==== 6.7 Useful Variations |
| - | Terminate at `TSD`: | + | The following patterns are commonly used when building more advanced schedules. |
| + | They are shown here using the **TestMap stations** (`TS`, `TSD`, `TSA`, `DP`). | ||
| + | |||
| + | |||
| + | ==== 6.7.1 Short Runs (Start or Terminate | ||
| + | |||
| + | Sometimes a service should start later or terminate earlier than the full route. | ||
| + | This is useful for: | ||
| + | * depot in/out runs | ||
| + | * special services | ||
| + | * partial line operations | ||
| + | |||
| + | Example: terminate | ||
| <code lua> | <code lua> | ||
| local TS_to_TSD = self.TestLine_Dir1: | local TS_to_TSD = self.TestLine_Dir1: | ||
| + | |||
| table.insert(self.timetables, | table.insert(self.timetables, | ||
| </ | </ | ||
| - | Start at `TSD`: | + | Example: start at `TSD` (depot insertion into service): |
| <code lua> | <code lua> | ||
| local TSD_to_TSA = self.TestLine_Dir1: | local TSD_to_TSA = self.TestLine_Dir1: | ||
| + | |||
| table.insert(self.timetables, | table.insert(self.timetables, | ||
| </ | </ | ||
| - | ==== 6.2 Platform Overrides ==== | + | |
| + | ==== 6.7.2 Platform Overrides | ||
| + | |||
| + | If you want to use the same template but spawn on a different platform, | ||
| + | you can override platform numbers after cloning. | ||
| + | |||
| + | Example: force first stop to use platform 1 instead of 2 at TS: | ||
| <code lua> | <code lua> | ||
| Line 186: | Line 289: | ||
| </ | </ | ||
| - | ==== 6.3 Service Runs (Non-Passenger Moves) ==== | + | This is useful if: |
| + | * multiple platforms exist | ||
| + | * you want different patterns at different times of day | ||
| + | * you temporarily reroute services during testing | ||
| + | |||
| + | ==== 6.7.3 Service Runs (Non-Passenger Moves) ==== | ||
| + | |||
| + | A service run is a trip that should not be treated as a normal passenger service. | ||
| + | |||
| + | Example: a depot-related move to TS marked as service run: | ||
| <code lua> | <code lua> | ||
| Line 197: | Line 309: | ||
| </ | </ | ||
| - | ==== 6.4 Force Unique Stop Lists ==== | + | ==== 6.7.4 Force Unique Stop Lists (Safe Editing) |
| + | |||
| + | If you modify stop properties (platforms, PIS text, flags), | ||
| + | it can be helpful to ensure the stop list is unique: | ||
| <code lua> | <code lua> | ||
| Line 203: | Line 318: | ||
| Variant: | Variant: | ||
| </ | </ | ||
| + | |||
| + | This prevents accidental shared stop references when creating multiple variants. | ||
| ---- | ---- | ||
| - | ===== Step 7 — Depots and Dispatching ===== | + | ===== 7) Depots and Dispatching ===== |
| + | |||
| + | This section defines: | ||
| + | * depot storage spaces (optional) | ||
| + | * turnaround / dispatch behavior at stations | ||
| + | |||
| + | ==== 7.1 Depots (Parking Tracks / Depot Spaces) ==== | ||
| + | |||
| + | Depots define **where AI trains are allowed to park** when they are not in service. | ||
| + | They are also used by the ControlCenter for dispatching and (later) career mode. | ||
| + | |||
| + | In the TestMap, the depot station is: | ||
| + | |||
| + | * `DP` (Depot) | ||
| + | |||
| + | And it provides these depot tracks: | ||
| - | Depots and dispatching strategies support the timetable traffic and keep trains moving. | + | * 51, 52, 53, 54 (long depot tracks) |
| + | * 60 (short depot / test track) | ||
| - | ==== 7.1 Depots (Depot Spaces) | + | ==== 7.1.1 Depot Table Structure |
| - | `self.depots` groups depot tracks into named blocks. | + | `self.depots` |
| + | Each group contains a list of `Depot_DepotSpace` entries. | ||
| ^ Field ^ Meaning ^ | ^ Field ^ Meaning ^ | ||
| Line 218: | Line 352: | ||
| | platform | Track / platform ID as defined in the BP_StationDefinition | | | platform | Track / platform ID as defined in the BP_StationDefinition | | ||
| | direction | Which direction trains should park/spawn facing (1 or 2) | | | direction | Which direction trains should park/spawn facing (1 or 2) | | ||
| - | | noParkingTimetable | If true: no dedicated parking timetable | + | | noParkingTimetable | If true: no dedicated parking timetable |
| - | Example: | + | ==== 7.1.2 TestMap |
| <code lua> | <code lua> | ||
| Line 226: | Line 360: | ||
| self.depots = { | self.depots = { | ||
| + | -- Main depot area (long tracks) | ||
| [" | [" | ||
| { station = self.stations.DP, | { station = self.stations.DP, | ||
| Line 233: | Line 368: | ||
| }, | }, | ||
| + | -- Short depot / test track (useful to keep free or for special moves) | ||
| [" | [" | ||
| { station = self.stations.DP, | { station = self.stations.DP, | ||
| Line 239: | Line 375: | ||
| </ | </ | ||
| - | ---- | + | Notes: |
| + | * The group keys (`" | ||
| + | * `platform` must match the platform numbers inside your **BP_StationDefinition** for DP. | ||
| + | * Use `noParkingTimetable = true` if you want to keep a track free (e.g. for turnarounds or testing). | ||
| - | ==== 7.2 Dispatching Strategies (Turnarounds / Depot Moves) ==== | ||
| - | Dispatching | + | ==== 7.2 Dispatching |
| - | * turnarounds at terminals | + | |
| - | * spawning trains from depots | + | |
| - | * sending trains back to depots | + | |
| - | * resolving conflicts / keeping traffic stable | + | |
| - | Basic structure: | + | Dispatching Strategies define how trains are handled **outside of normal passenger service**. |
| + | They are used to: | ||
| + | |||
| + | * turn trains around at terminal stations, | ||
| + | * spawn trains from depots, | ||
| + | * send trains back to depots, | ||
| + | * resolve platform conflicts, | ||
| + | * and keep traffic flowing when timetables alone are not sufficient. | ||
| + | |||
| + | Dispatching is handled by the **ControlCenter** and works in addition to normal timetables. | ||
| + | |||
| + | ==== 7.2.1 Basic Structure ==== | ||
| + | |||
| + | Dispatching strategies are defined as a table, grouped by station: | ||
| <code lua> | <code lua> | ||
| ---@type table< | ---@type table< | ||
| self.dispatchingStrategies = { | self.dispatchingStrategies = { | ||
| - | [self.stations.TS] = { | + | [self.stations.WA] = { |
| - | -- strategies for TS | + | -- strategies for this station |
| }, | }, | ||
| } | } | ||
| </ | </ | ||
| - | Strategies | + | Each station can have **multiple strategies**. |
| + | They are evaluated **top to bottom**, so order matters. | ||
| - | ---- | ||
| - | ==== 7.2.1 Pattern A — Simple Turnaround ==== | + | ==== 7.2.2 When Dispatching Is Used ==== |
| + | |||
| + | Dispatching strategies are evaluated when: | ||
| + | |||
| + | * a timetable ends at a station, | ||
| + | * a train needs to turn around, | ||
| + | * no suitable train is available for a departure, | ||
| + | * or a train must be moved to or from a depot. | ||
| + | |||
| + | If no strategy matches, the train will remain idle. | ||
| + | |||
| + | |||
| + | ==== 7.2.3 Strategy Fields ==== | ||
| + | |||
| + | Each dispatching strategy can define the following fields: | ||
| + | |||
| + | ^ Field ^ Description ^ | ||
| + | | sourceStation | Station where the train currently is. Use `nil` for depot spawns. | | ||
| + | | targetStation | Station the train should serve next. Use `nil` for depot despawn. | | ||
| + | | sourcePlatforms | Allowed platforms the train may come from. | | ||
| + | | targetPlatforms | Allowed platforms the train may go to. | | ||
| + | | depotName | Name of the depot (as defined in the depots table). | | ||
| + | | minLayover | Minimum minutes the train must wait before reuse. | | ||
| + | | keepLine | Try to keep the train on the same line. | | ||
| + | | replaceFirstPlatform | Replace the first stop platform if needed. | | ||
| + | | replaceLastPlatform | Replace the last stop platform if needed. | | ||
| + | | overrideFirstPlatform | Force a specific first platform. | | ||
| + | | overrideLastPlatform | Force a specific last platform. | | ||
| + | | timetable | Optional hidden timetable used for movements. | | ||
| + | |||
| + | Not all fields are required for every strategy. | ||
| + | |||
| + | |||
| + | ==== 7.2.4 Pattern A — Simple Turnaround ==== | ||
| + | |||
| + | This is the most common case: | ||
| + | A train arrives at a station and turns around to serve the opposite direction. | ||
| + | |||
| + | Example (Test Map): | ||
| <code lua> | <code lua> | ||
| { | { | ||
| - | sourceStation = self.stations.TS, | + | |
| - | targetStation = self.stations.TS, | + | targetStation = self.stations.Kbo, |
| - | sourcePlatforms = { "1", "2" }, | + | sourcePlatforms = { " |
| - | targetPlatforms = { " | + | targetPlatforms = { " |
| - | replaceFirstPlatform = true, | + | minLayover = 3, |
| - | keepLine = false, | + | |
| - | minLayover = 4, | + | |
| } | } | ||
| </ | </ | ||
| - | ---- | + | What happens: |
| - | ==== 7.2.2 Pattern B — Turnaround with Internal Movement ==== | + | * a train arriving on platform 1 |
| + | * waits at least 3 minutes | ||
| + | * and departs again from platform | ||
| - | Hidden timetables are used for internal | + | No depot is involved. |
| + | |||
| + | |||
| + | ==== 7.2.5 Pattern B — Turnaround with Internal Movement ==== | ||
| + | |||
| + | Some stations require a **shunting | ||
| + | |||
| + | In this case, a hidden timetable is attached: | ||
| <code lua> | <code lua> | ||
| { | { | ||
| - | sourceStation = self.stations.Go, | + | |
| - | targetStation = self.stations.Go, | + | targetStation = self.stations.Go, |
| - | sourcePlatforms = { " | + | sourcePlatforms = { " |
| - | targetPlatforms = { " | + | targetPlatforms = { " |
| - | minLayover = 3, | + | minLayover = 3, |
| - | timetable = Timetable: | + | timetable = Timetable: |
| - | : | + | : |
| - | : | + | : |
| - | station = self.stations.Go, | + | station = self.stations.Go, |
| - | platform = " | + | platform = " |
| - | departure = 2, | + | departure = 2, |
| - | turnAround = true, | + | turnAround = true, |
| - | }) | + | }) |
| - | : | + | : |
| - | station = self.stations.Go, | + | station = self.stations.Go, |
| - | platform = " | + | platform = " |
| - | departure = 3, | + | departure = 3, |
| - | }), | + | }), |
| } | } | ||
| </ | </ | ||
| - | ---- | + | This allows: |
| + | * temporary use of siding or crossover tracks | ||
| + | * clean turnarounds without blocking passenger platforms | ||
| - | ==== 7.2.3 Pattern C — Spawning Trains from a Depot ==== | + | |
| + | ==== 7.2.6 Pattern C — Spawning Trains from a Depot ==== | ||
| + | |||
| + | When no train is available, dispatching can **fetch a train from a depot**. | ||
| + | |||
| + | Example: | ||
| <code lua> | <code lua> | ||
| { | { | ||
| - | sourceStation = nil, | + | |
| - | targetStation = self.stations.WA, | + | targetStation = self.stations.WA, |
| - | targetPlatforms = { " | + | targetPlatforms = { " |
| - | depotName = " | + | depotName = " |
| - | overrideFirstPlatform = " | + | overrideFirstPlatform = " |
| - | timetable = Timetable: | + | timetable = Timetable: |
| - | : | + | : |
| - | : | + | : |
| - | station = self.stations.WA, | + | station = self.stations.WA, |
| - | platform = " | + | platform = " |
| - | departure = -5, | + | departure = -5, |
| - | }) | + | }) |
| - | : | + | : |
| - | station = self.stations.WA, | + | station = self.stations.WA, |
| - | platform = " | + | platform = " |
| - | departure = -3, | + | departure = -3, |
| - | }), | + | }), |
| } | } | ||
| </ | </ | ||
| - | `sourceStation = nil` means the train comes from a depot. | + | Key points: |
| - | ---- | + | * `sourceStation = nil` means the train comes from a depot |
| + | * the depot name must match the depots table | ||
| + | * negative departure times happen **before** the actual service | ||
| - | ==== 7.2.4 Pattern D — Sending Trains to a Depot ==== | + | |
| + | ==== 7.2.7 Pattern D — Sending Trains to a Depot ==== | ||
| + | |||
| + | After service ends, trains can be removed from traffic. | ||
| + | |||
| + | Example: | ||
| <code lua> | <code lua> | ||
| { | { | ||
| - | sourceStation = self.stations.WA, | + | |
| - | sourcePlatforms = { " | + | sourcePlatforms = { " |
| - | targetStation = nil, | + | targetStation = nil, |
| - | depotName = " | + | depotName = " |
| - | timetable = Timetable: | + | timetable = Timetable: |
| - | : | + | : |
| - | : | + | : |
| - | station = self.stations.WA, | + | station = self.stations.WA, |
| - | platform = " | + | platform = " |
| - | departure = 2, | + | departure = 2, |
| - | }) | + | }) |
| - | : | + | : |
| - | station = self.stations.WA, | + | station = self.stations.WA, |
| - | platform = " | + | platform = " |
| - | departure = 6, | + | departure = 6, |
| - | }), | + | }), |
| } | } | ||
| </ | </ | ||
| - | `targetStation = nil` means the train leaves traffic into a depot. | + | Here: |
| - | ---- | + | * the train leaves passenger service |
| + | * moves into the depot | ||
| + | * and is no longer available for dispatching | ||
| - | ==== 7.2.5 Hidden Timetables ==== | ||
| - | Hidden | + | ==== 7.2.8 Hidden |
| + | |||
| + | Timetables inside dispatching strategies: | ||
| * are not shown to the player | * are not shown to the player | ||
| - | * should | + | * are always |
| * are used only for internal movements | * are used only for internal movements | ||
| + | |||
| + | They allow precise control over: | ||
| + | * routing | ||
| + | * speed limits | ||
| + | * platform usage | ||
| + | * turnarounds | ||
| + | |||
| + | |||
| + | ==== 7.2.9 Strategy Order ==== | ||
| + | |||
| + | Dispatching strategies are evaluated **in order**. | ||
| + | |||
| + | Recommended structure per station: | ||
| + | |||
| + | 1. normal turnarounds | ||
| + | 2. depot spawn strategies | ||
| + | 3. depot despawn strategies | ||
| + | 4. fallback strategies | ||
| + | |||
| + | This avoids unnecessary depot movements and keeps traffic stable. | ||
| + | |||
| + | |||
| + | ==== 7.2.10 Common Pitfalls ==== | ||
| + | |||
| + | * depot names not matching the depots table | ||
| + | * missing `setIsServiceRun(true)` on hidden timetables | ||
| + | * conflicting platform definitions | ||
| + | * wrong strategy order | ||
| + | |||
| + | If dispatching behaves unexpectedly, | ||
| + | |||
| ---- | ---- | ||
| - | ===== Common Pitfalls | + | ===== 8) Career Mode (Optional) |
| + | |||
| + | Career Mode is optional. | ||
| + | If you don’t want career mode features on your map, you can leave `loadCareerMode()` empty. | ||
| + | |||
| + | If you *do* want career mode, this function defines: | ||
| + | |||
| + | * where the player is allowed to take over a train | ||
| + | * optional route closures (for scenario logic) | ||
| + | * which train compositions the player is likely to get | ||
| + | * which timetable templates are used for pathfinding | ||
| + | |||
| + | ==== 8.1 Takeover Stations (Where the Player Can Start) ==== | ||
| + | |||
| + | `self.cmTakeoverStations` is a list of stations where career mode allows a takeover. | ||
| + | |||
| + | For the TestMap, we keep it simple: | ||
| + | |||
| + | <code lua> | ||
| + | -- Initializes data for career mode (optional) | ||
| + | function TestMap: | ||
| + | |||
| + | -- Stations where the player can take over in career mode | ||
| + | self.cmTakeoverStations = { | ||
| + | self.stations.TS, | ||
| + | self.stations.TSA, | ||
| + | self.stations.DP, | ||
| + | }; | ||
| + | |||
| + | end | ||
| + | </ | ||
| + | |||
| + | Notes: | ||
| + | * You reference the stations from `self.stations` (created in `loadStations()`). | ||
| + | * If a station is missing here, the player won’t be offered takeovers there. | ||
| + | |||
| + | ==== 8.2 Route Closures (Optional) ==== | ||
| + | |||
| + | Route closures allow you to define sections that may be blocked in career mode. | ||
| + | This is mainly for scenario systems and future gameplay logic. | ||
| + | |||
| + | Each closure uses: | ||
| + | * `stationSource` → start of the closed section | ||
| + | * `stationTarget` → end of the closed section | ||
| + | * a DayMask (e.g. `DayMask.Always`, | ||
| + | |||
| + | Example for the TestMap (optional): | ||
| + | |||
| + | <code lua> | ||
| + | function TestMap: | ||
| + | |||
| + | self.cmTakeoverStations = { | ||
| + | self.stations.TS, | ||
| + | self.stations.TSA, | ||
| + | self.stations.DP, | ||
| + | }; | ||
| + | |||
| + | -- Optional: example closure between TS and TSA on weekends | ||
| + | self.cmRouteClosures = { | ||
| + | { | ||
| + | stationSource | ||
| + | stationTarget | ||
| + | tempClosure | ||
| + | }, | ||
| + | }; | ||
| + | |||
| + | end | ||
| + | </ | ||
| + | |||
| + | If you don’t need closures, simply omit `self.cmRouteClosures`. | ||
| + | |||
| + | ==== 8.3 cmGroups (Train Pool + Probability) ==== | ||
| + | |||
| + | `self.cmGroups` defines which train compositions can appear in career mode. | ||
| + | |||
| + | Each group represents a **probability set** for vehicle selection. | ||
| + | |||
| + | You can define **multiple groups**. | ||
| + | Each group has: | ||
| + | |||
| + | ^ Field ^ Meaning ^ | ||
| + | | frequency | Probability factor in the range **0.0 – 1.0** | | ||
| + | | compositions | List of composition `contentName` strings | | ||
| + | |||
| + | Important: | ||
| + | * `frequency = 1.0` means **100 % chance** for this group to be considered. | ||
| + | * `frequency = 0.0` disables the group entirely. | ||
| + | * Values between 0.0 and 1.0 reduce the chance accordingly. | ||
| + | * The value is **not relative** to other groups. | ||
| + | |||
| + | ==== Example (TestMap) ==== | ||
| + | |||
| + | <code lua> | ||
| + | function TestMap: | ||
| + | |||
| + | self.cmTakeoverStations = { | ||
| + | self.stations.TS, | ||
| + | self.stations.TSA, | ||
| + | self.stations.DP, | ||
| + | }; | ||
| + | |||
| + | -- Career mode vehicle selection pool | ||
| + | self.cmGroups = { | ||
| + | -- Main vehicle pool (always available) | ||
| + | { | ||
| + | frequency = 1.0, | ||
| + | compositions = { | ||
| + | " | ||
| + | " | ||
| + | }, | ||
| + | }, | ||
| + | |||
| + | -- Optional / rare vehicles | ||
| + | { | ||
| + | frequency = 0.4, | ||
| + | compositions = { | ||
| + | " | ||
| + | " | ||
| + | }, | ||
| + | }, | ||
| + | }; | ||
| + | |||
| + | end | ||
| + | </ | ||
| + | |||
| + | Result: | ||
| + | * HK_2x and A3L92_4x are **always available** in career mode. | ||
| + | * HK_1x and A3L92_3x appear **only occasionally**, | ||
| + | |||
| + | ==== 8.4 Pathfinding Templates ==== | ||
| + | |||
| + | Career mode also needs timetable templates that can be used for route finding. | ||
| + | |||
| + | For the TestMap, we reference our two templates: | ||
| + | |||
| + | <code lua> | ||
| + | function TestMap: | ||
| + | |||
| + | self.cmTakeoverStations = { | ||
| + | self.stations.TS, | ||
| + | self.stations.TSA, | ||
| + | self.stations.DP, | ||
| + | }; | ||
| + | |||
| + | self.cmGroups = { | ||
| + | { | ||
| + | frequency = 1, | ||
| + | compositions = { | ||
| + | " | ||
| + | " | ||
| + | }, | ||
| + | }, | ||
| + | }; | ||
| + | |||
| + | -- Templates that can be used for pathfinding | ||
| + | self.pathfindingTemplates = { | ||
| + | self.TestLine_Dir1, | ||
| + | self.TestLine_Dir2, | ||
| + | }; | ||
| + | |||
| + | end | ||
| + | </ | ||
| + | |||
| + | If you forget this, career mode may not be able to plan valid routes on your map. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 9) Registering Stations and Timetables ===== | ||
| + | |||
| + | The final step is registering runtime data with the ControlCenter: | ||
| + | |||
| + | <code lua> | ||
| + | controlCenter: | ||
| + | controlCenter: | ||
| + | </ | ||
| + | |||
| + | ^ Call ^ Description ^ | ||
| + | | setStationList | Registers all stations for routing, UI and spawning logic. | | ||
| + | | setTimetableList | Registers AI services plus dispatching and depot logic. | | ||
| - | * station short names not matching BP_StationDefinition | + | If this function is missing or incomplete: |
| - | * platform ids mismatching the BP_StationDefinition platform array | + | * AI traffic will not work |
| - | * compositions | + | * stations may not be recognized for routing |
| - | * wrong dispatching strategy order | + | |
| - | * forgetting to insert cloned services into `self.timetables` | + | |
| ---- | ---- | ||
manual/subwaysim/map_construction/create_timetable.1769509209.txt.gz · Last modified: by dcs
