Tracks and streets are defined by config files in the res/config/track/
or res/config/street/
folders.
A track configuration file specifies a set of parameters to define the properties, dimension, features and visuals of tracks. They are stored in .lua
files in the folder res/config/track/
.
The file has the following format:
function data() return { -- name, description, availability -- shape configuration -- ballast configuration -- sleeper configuration -- rail configuration -- catenary configuration -- track configuration -- speed configuration -- radius and slope configuration -- materials, models, textures configuration -- cost configuration } end
The following properties are used for general purposes:
t.name = _("High-speed tracks") t.desc = _("Specialized tracks for higher speeds") t.categories = { "1435mm", } t.yearFrom = 1925 t.yearTo = 0
name
is the name of the track type that is used in the menu. It can be translated in a strings.lua file.desc
is the description of the track type used in the buy menu. It can be translated too.categories
is a list of category keys. They are used for the category filters in the menu. A track can be part of more than one category. If left empty, it is only available in the non-filtered view.yearFrom
is the year from when the track should be available. Unset or values below 1851 mean from start.yearTo
is the year until when the track should be available. Unset or value 0 means unlimited availability, values below 1850 result in a never available track.
shapeStep = 5 and shapeStep = 1
Shapes represent the base geometry of the tracks and are used for collision tests, terrain alignment generation and generation of the procedural geometry.
t.shapeWidth = 4.0 -- [m] shape width t.shapeStep = 4.0 -- [m] shape step t.shapeSleeperStep = 8.0 / 13.0 -- [m] distance between sleepers
The width should be high enough to contain the actual procedural geometry. The step size allows for smoother curves (small) or less geometric primitives (high), which speed up collision checks. Tracks that allow a small minimal radius and have a small track width should tend to smaller shapeSteps to avoid corners in the tracks.
ballastCutOff = 0.5 and ballastCutOff = 0.1
Ballast is the bed for track usually made from crushed stone. The height and material (see below) can be configured.
t.ballastHeight = .3 -- [m] height of the ballast t.ballastCutOff = .1 -- [m] cut off profile
The ballastCutOff
can be used to influence the steepness of the ballast sides. 0.1 is relatively steep,
0.5 is not as steep but the horizontal top part is reduced so the ends of sleepers get nearer the ballast bed edges.
static models and procedurally generated ones
Sleepers (or ties) are the rail supports usually made from wood, concrete or steel. The dimension and material (see below) can be configured. These settings are only used for procedurally generated sleepers at switches and crossings. Normal sleepers use the static models (see below).
t.sleeperBase = ballastHeight -- [m] bottom height from ground level t.sleeperLength = .24 -- [m] length of the sleeper along track t.sleeperWidth = 2.6 -- [m] width of the sleeper t.sleeperHeight = .08 -- [m] height of the sleeper t.sleeperCutOff = .04 -- [m] cut off profile
The sleeperCutOff
property is used to define the cut off angle for the sleepers. Usually it is higher for steel sleepers.
static models and procedurally generated ones
The rail configuration is used for switches and crossings. Along normal tracks, the static models are used (see below)
t.railTrackWidth = 1.435 -- [m] track gauge (space between rails) t.railBase = sleeperBase + .08 -- [m] base height from ground level t.railHeight = .15 -- [m] height of the rail t.railWidth = .07 -- [m] width of the rail t.railCutOff = .02 -- [m] cutoff profile
The railCutOff
property is used to define the cut off angle for the rail. Usually it is very low. Be aware that changing the railWidth of existing track types may lead to compatibility problems in savegames.
Electrified tracks need catenary for the power transfer. The poles are instances of a model, whereas the cable is procedurally generated.
t.catenaryBase = 5.917 + railBase + railHeight -- [m] base height of the cable over ground level t.catenaryHeight = 1.35 -- [m] height of the support cable at the poles t.catenaryPoleDistance = 25.0 -- [m] target distance between poles t.catenaryMaxPoleDistanceFactor = 2.0 -- factor for maximum pole distance t.catenaryMinPoleDistanceFactor = 0.8 -- factor for minimal pole distance (in curves)
It is possible to drag parallel with this distance from an existing track.
trackDistance = 5.0 -- [m] distance between track centers
Be aware that a trackDistance other than 5 meters might result in problems with the ballast track bed and catenary pole gantry generation.
The maximum speed on straight segments is speedLimit
, and on curved segments calculated according the formula below.
speedLimit = 300.0 / 3.6 -- [m/s] maximum speed on a straight track speedCoeffs = { .9, 15.0, .63 } -- curve speed limit = a * (radius + b) ^ c
In Transport Fever 2 it is possible to set a minimal radius as well as maximum steepnes of slopes to realize narrow gauge railways with thight curves and steep rails in the mountains.
t.minCurveRadiusBuild = 60.0 -- [m] minimal radius when dragging t.minCurveRadius = 44.0 -- [m] minimal radius when snapping (and parallel tracks) t.maxSlopeBuild = 0.075 t.maxSlope = t.maxSlopeBuild * 1.6 t.maxSlopeShape = t.maxSlope * 1.25 t.slopeBuildSteps = 2 -- [1-4] steps for slope arrow buttons
The minimal radius is set by the two first properties in this section. The first one is used when tracks are dragged free on the map. The second is relevant for the snapping along or to other tracks, e.g. at switches and parallel tracks.
The maximum slope is defined by three values. maxSlopeBuild
is the slope of a straight line between start and end point 1. maxSlope
is the limit for the track curve that aligns to the slopes of tracks at the start and end point 2. maxSlopeShape
is the limit for the actual track that may be displaced by intersecting roads or crossing tracks 3.
slopeBuildSteps
is the number of steps that are available with the fixed slope arrow buttons . The more steps, the smaller they are.
The procedurally generated parts of the tracks use the following materials:
t.ballastMaterial = "track/ballast.mtl" (1) t.sleeperMaterial = "track/sleeper_concrete.mtl" (2) t.railMaterial = "track/rail.mtl" (3) t.catenaryMaterial = "track/catenary.mtl" (4) t.tunnelWallMaterial = "track/tunnel_rail_ug.mtl" (5) t.tunnelHullMaterial = "track/tunnel_hull.mtl" t.fillGroundTex = "ballast_fill.lua" (6) t.borderGroundTex = "ballast.lua" (7)
fillGroundText
is used for the area below the track to blend the ballast better to the terrain.
borderGroundTex
is the ground texture that is used for the border along the track ballast. tunnelHullMaterial
is the material for the outside of the tunnel (that normally is not visible at all).
For normal tracks (except switches and crossings), static models are used. There are additional models for the catenary and bumper and switch signals which are optional.
t.catenaryPoleModel = "railroad/power_pole_us_2.mdl" t.catenaryMultiPoleModel = "railroad/power_pole_us_1_pole.mdl" t.catenaryMultiGirderModel = "railroad/power_pole_us_1a_repeat.mdl" t.catenaryMultiInnerPoleModel = "railroad/power_pole_us_1b_pole2.mdl" t.bumperModel = "railroad/bumper.mdl" t.switchSignalModel = "railroad/switch_box.mdl" t.railModel ="railroad/tracks/single_rail.mdl" t.sleeperModel = "railroad/tracks/single_sleeper_base.mdl" t.trackStraightModel = { "railroad/tracks/2m_base.mdl", "railroad/tracks/4m_base.mdl", "railroad/tracks/8m_base.mdl", "railroad/tracks/16m_base.mdl", }
The catenary uses four different models for different situations:
The track sections are used depending on the length of the section and the radius. Straight tracks use the models from trackStraightModel
with appropriate lengths (2, 4, 8 or 16 meters). For very small sections and tight curves, the model is constructed from the single sleeper and two instances of the single rail model. All models have their origin at the terrain height, not the ballast top height and are centered in length and width.
The two values can be set to adjust the costs of tracks.
maintenanceCost = 25.0 -- [$/m/M] per meter and month cost = 80.0 -- [$/m] per meter
The game automatically generates station modules for every non-vanilla track type in the vanilla postRun function. To prevent these modules from appearing, a custom postRun function can be used in the mod to hide them. The below code crawls through the repository of modules and sets the visibility property to false for the modules specified in the list.
postRunFn = function () local filteredModules = { ["trainstation_<tracktypename>.lua"] = 1, ["trainstation_<tracktypename>.luacatenary"] = 1, } local modules = api.res.moduleRep.getAll() for index, moduleFileName in ipairs(modules) do if filteredModules[moduleFileName] == 1 then api.res.moduleRep.setVisible(index - 1,false) end end end,
A street configuration files specifies a set of parameters to define the properties, dimension, features and visuals of streets. They are stored in .lua
files in the folder res/config/street/
.
The file consists of three parts:
function data() return { -- property and dimension definitions -- ... materials = { -- material definitions }, assets = { -- asset definitions }, } end
The common properties of streets are:
function data() return { numLanes = 2, -- number of lanes, see below streetWidth = 10.0, -- [m] width of the street (without sidewalk!) sidewalkWidth = 3.0, -- [m] width of the sidewalk (must not be 0) sidewalkHeight = .3, -- [m] height of the sidewalk aiLock = false, -- street type can't be changed by town development [bool] country = false, -- disallow town buildings [bool] speed = 20.0, -- [km/h] maximum allowed drive speed type = "old small", -- legacy type that can be referenced elsewhere transportModesStreet = { "BUS", } -- restriction of allowed street transport mode types transportModesSidewalk = { "PERSON", } -- restriction of allowed sidewalk transport mode types busAndTramRight -- restriction of the outmost lane to only be used by bus and tram priority = 10 -- priorisation for the visualisation of crossing markings yearFrom = 0, -- available from [year] yearTo = 1925, -- available until [year] name = _("Small street"), -- name for the buy menu desc = _("Two-lane street with %2%."), -- description for the buy menu icon = "ui/streets/standard/old_small.tga" -- optional reference to the ui icon categories = { "urban" }, -- category for the buy menu cost = 20.0, -- building costs per meter maintenanceCost = 0.15, -- monthly maintenance cost per meter borderGroundTex = "street_border.lua", -- ground texture for the borders of the street streetFillGroundTex = "", -- ground texture for the street sidewalkFillGroundTex = "", -- ground texture for the sidewalks maxSlope = 0.4, maxSlopeBuild = 0.2, maxSlopeShape = 0.4, slopeBuildSteps = 4, -- step size for procedurally generated street section embankmentSlopeLow = 0.75, -- less steep slope gradient embankmentSlopeHigh = 2.5, -- steeper slope gradient -- material, catenary and assets definitions... }
Streets that have an equal number of lanes in both direction can use the simple property numLanes
. The number is divided by two to determine the number of lanes for each of the directions. Streets with an unequal number of lanes per direction require the use of the alternative laneConfig
property:
laneConfig = { { forward = true }, -- sidewalk left { forward = false }, -- left lane { forward = true }, -- middle lane { forward = true }, -- right lane { forward = true }, -- sidewalk right },
The first and last list entries are the sidewalks. They are used by pedestriants in both directions with a small sideway offset. Be aware that at least 3 entries are required, less entries lead to a crash.
The basic dimensions of streets are defined with three properties:
1 streetWidth
is the width of all street lanes. It is equally devided over all lanes.
2 sidewalkWidth
is the width of each sidewalk in meters. Must not be 0.
3 sidewalkHeight
is the height of the sidewalks in meters.
Several properties influence the functionality of the street:
aiLock
is a boolean variable. If set to true
, built street segments with this street type will not be changed by the town development and this street type is not considered as potential target type for street upgrades by town development.country
is another boolean variable. If set to true
, no houses will spawn along streets of this type.speed
is the maximum allowed drive speed in km/h. In sharp curves, vehicles will slow anyway.type
is a key (usually the file name without _ ) that was used for referencing elsewhere. It is legacy in Transport Fever 2.transportModesStreet
is a list of keys for transport modes that are allowed on this street. It is possible to use “BUS”
, “TRUCK”
and “CAR”
.transportModesSidewalk
is a list of keys for transport modes that are allowed on the sidewalk of this street. It is possible to use “CARGO”
and “PERSON”
.busAndTramRight
restricts the outmost lane to only be used by bus and tram if set to true
. This is similar to the addition of a buslane ingame.priority
is an integer value used for the priorization of street types when it comes to the visualisation of markings at crossings. The higher the value is, the more likely this streets markings are used for the optic at intersections. This is used for the junction* materials described below.If an intersection consists of different street types, the one that is used most for the street segments meeting at the intersection node is used for the paving and other materials. If several types are used equally often, there is no guranteed order, but usually the type with smaller index in the street type repo is used.
To hide a street type from the menu, use the setVisibility(bool) function in the postRunFn method or set the third parameter for adding street types to false when adding to the street type repository by script.
As an alternative you can set a custom fileFilter to filter the street types.
The following properties are used for general purposes:
yearFrom
is the year from when the street should be available. Unset or values below 1851 mean from start.yearTo
is the year until when the street should be available. Unset or value 0 means unlimited availability, values below 1850 result in a never available street.name
is the name of the street type that is used in the menu. It can be translated in a strings.lua file.desc
is the description of the street type used in the buy menu. It can be translated too.icon
is an optional reference to the icon that should be used in the menu. It is relative to the res/textures/
folder.categories
is a list of category keys. They are used for the category filters in the menu. A street can be part of more than one category.cost
is the building cost per meter. Additional features like tram tracks and bus lanes will raise that value.
There are three properties that can be used for ground textures in the area of streets:
1 borderGroundTex
is the ground texture that is used for the border along the street.
2 sidewalkFillGroundTex
is used for the area below the sidewalks. If the street does not have a sidewalk material, this ground texture can be seen. This is often used with country roads.
3 streetFillGroundTex
is used for the area below the street itself. It is usually not visible at all except the street does not have a paving material.
Other properties are:
maxSlope
, maxSlopeBuild
and maxSlopeShape
are the parameters for the slope gradient limits. They work the same as the ones of the track configuration described above.slopeBuildSteps
is a factor for the step size of procedurally generated street sections. Smaller values result in smoother bends but need more performance.embankmentSlopeLow
is the slope gradient that usually is tried to be used.embankmentSlopeHigh
is used, if the low gradient would require very wide embankments or there are other objects with terrain alignments that prevent the use of the low gradient.
The list of materials defines the materials used for various parts of the street. Every definition contains a link to a .mtl
file and its size:
materials = { streetPaving = { name = "street/country_new_medium_paving.mtl", -- reference to material file size = { 8.0, 8.0 } -- the size of the texture tile }, -- more material definitions... },
The material references are relative to the res/models/material/
path. The textures are used as tiled textures wich are layed next to each other to fill the required area. With size
, it is possible to specify the size of such a tile in meters for x and y dimension.
Available material definitions:
1 streetPaving
is the base texture of streets. It is not orientated along the lane direction.
2 streetBorder
is the overlay texture stripe that is used along the outer edges of the outermost lanes.
3 streetLane
is an overlay texture of street lanes. It is oriented along the lane.
4 streetArrow
is an overlay decal used for arrows in front of crossings.
5 streetStripe
is the overlay texture stripe that is used between lanes of the same direction.
6 streetStripeMedian
is the overlay texture stripe that is used between lanes of different directions.
7 streetTram
is the overlay texture with the tram track basement.
8 streetTramTrack
is the overlay texture with the actual tram tracks.
9 streetBus
is the overlay texture of bus lanes. It is oriented along the lane.
10 sidewalkPaving
is the base texture of sidewalks. It is not orientated along the lane direction.
11 sidewalkLane
is the oberlay texture of sidewalk lanes. It is oriented along the lane.
12 sidewalkBorderInner
is the overlay texture stripe that is used along the sidewalk edge towards the street lanes.
13 sidewalkBorderOuter
is the overlay texture stripe that is used along the outer edge of the sidewalk.
14 sidewalkCurb
is the texture that is used for the face at the side of the higher sidewalks towards the street and front faces where sidewalks have different heights. This often happens at railroad crossings and the contact points between town and country roads.
15 crossingLane
is an overlay texture of street lanes in intersections. It is oriented along the lane.
16 crossingTram
is the overlay texture with the tram track basement in intersections.
17 crossingTramTrack
is the overlay texture with the actual tram tracks in intersections.
18 crossingCrosswalk
ist the overlay decal for crosswalk markings.
Further material definitions are not shown in the picture above:
sidewalkWall
is the texture that is shown at the vertical faces at the outside of the sidewalks.crossingBus
is the overlay texture used by buslanes at crossings. This works similar to the other crossing overlays.crossingStripeMedian
is the overlay texture stripe that is used between lanes of different directions at crossings.crossingStopline
is an overlay decal used for stop lines in front of crossings.junctionBorder
is the overlay texture stripe that is used along the outer edges of the outermost lanes at the dead ends of streets and in crossings. junctionLane
is an overlay texture of street lanes at the dead ends of streets and in crossings. It is oriented along the lane.junctionEntryLane
is an overlay texture of street lanes at the dead ends of streets and in junctionStripe
is the overlay texture stripe that is used between lanes of the same direction at the dead ends of streets and crossings with a prioritized street. junctionStripeMedian
is the overlay texture stripe that is used between lanes of different directions at crossings when there is a street with higher priority.junctionLine
is the overay texture stripe that is only used if there is no prioritized street.catenary
is the material used for the tram catenary wires.tunnelWall
is the material for the tunnel wall.tunnelHull
is the material for the outside of the tunnel (that normally is not visible at all).If a material is not set for a street type, this part is invisible ingame.
Base materials - like street and sidewalk pavings - require the following parameters:
function data() return = { order = 0 params = { -- more params polygon_offset = { factor = -2, units = -2, }, }, type = "PHYS_TRANSPARENT_NRML_MAP" -- or non-transparent }
Overlay materials - like markings, borders, bus lanes or tram tracks - require the following parameters:
function data() return = { order = 1 -- for multiple overlays set order appropriately params = { -- more params alpha_test = { alphaThreshold = 0.5, preferAlphaToCoverage = false, }, polygon_offset = { factor = -3, units = -3, }, }, type = "PHYS_TRANSPARENT_NRML_MAP" }
Detailed information about material definitions can be found at the material definitions.
The catenary models that should be used are referenced in the catenary
block.
catenary = { pole = { name = "asset/tram_pole.mdl" }, poleCrossbar = { name = "asset/tram_pole_crossbar.mdl" }, poleDoubleCrossbar = { name = "asset/tram_pole_double_crossbar.mdl" }, isolatorStraight = "asset/cable_isolator.mdl"; isolatorCurve = "asset/cable_isolator.mdl"; junction = "asset/cable_junction.mdl"; },
Streets can be decorated by placing different assets along the street. The assets
block contains a list of them:
assets = { { name = "street/street_light_eu_c.mdl", -- reference to the asset model offset = 10.0, -- [m] offset along the street distance = 20.0, -- [m] distance between assets prob = 1.0, -- [0.0 - 1.0] placement probability offsetOrth = 3.4, -- [m] offset perpendicular to street direction randRot = false, -- [bool] random rotation oneSideOnly = true, -- [bool] place only on one side of the road alignToElevation = false, -- [bool] align to elevation avoidFaceEdges = false, -- [bool] asset not placed at street segment border... -- ... (avoid overlaps with bigger assets, i.e. tree beds) placeOnBridge = true, -- [bool] place on bridges }, -- more asset definitions... },
Usually assets are not aligned to the elevation when they are trees or (lamp) posts. Aligned assets could be the tree beds.