NML:Stations

From GRFSpecs
Jump to navigationJump to search
Props, Vars and CBs

Stations are supported since NML 0.7.

Station sections

Stations can be built from multiple sections. Station tiles will remember, which tiles were built together in one action.

  • Building a 2x5 station in one action creates a single station section of size 2x5.
  • Building a 2x5 station by placing two 1x5 areas next to each other in two actions creates two station sections of size 1x5; even when using the same station type from the same NewGRF.

Station sections.png

Overbuilding stations and removing station tiles will remove tiles from station sections.

  • On construction all station sections are contiguous rectangular NxM tile ares. (regular station section)
  • When tiles are overbuilt or tiles are removed, station sections may end up non-rectangular and non-contiguous. (irregular station section)

Station tiles can query their position inside a contiguous line of tiles from the same section.

  • This is great as long as the section remains regular.
  • If tiles are non-contiguous, they are indistinguishable from tiles of other sections.

For irregular sections the "position" inside the section will become rather arbitrary. The picture shows the perspective of each tile of a irregular section as "(platform, position)/(num-platforms, length)":

Station sections irregular.png

Tile types

When station sections are built, they can store a "tile type" for each tile using the select_tile_type callback.

Tile types have multiple usages:

  • The type can be read via the tile_type variable, and can act as persistent storage.
  • It decides whether the tile is traversible by trains, or whether it is a building without tracks.
  • It decides whether catenary pylons and/or wires shall be drawn/hidden on the tile. Note: even non-track station buildings have a rail type, and can draw catenary.

The tile type is immutable after construction. So, unlike the platform/position information, the tile type will never change after construction, even if tiles of the station section are removed or overbuilt.

The number of tile types is quite limited: 4 per orientation, 8 in total.

  • Tile types 0, 2, 4 and 6 are used for station sections with tracks in X direction (⤢).
  • Tile types 1, 3, 5 and 7 are used for station sections with tracks in Y direciton (⤡).
  • Callback select_tile_type decides between the pairs (0,1), (2,3), (4,5), (6,7) during construction. The orientation is always picked by the player.

Station properties

property value range comment
class String literal of length 4

This property must be set first, before any other properties or graphics.
Stations belonging to the same class are grouped in the GUI.
There is one special class:

  • "WAYP": The station type will be shown in the waypoint construction window, instead of the station construction window.
classname string You only need to set this for one station in every class.
name string For example: string(STR_50S_STATION)
disabled_platforms
disabled_length
bitmask(1, 2, 3, 4, 5, 6, 7, 8)

Restricts the possible number-of-platforms and platform-lengths the player can build as one section.

  • Sizes 1 to 7 can be disabled individually,
  • "size 8" is used for anything bigger than 7.

To put restrictions on sizes bigger than 7 (for example, only allow even sizes), you can use callback tile_check.
Note: Players can remove single tiles from any station, so stations sections can end up with forbidden sizes anyway.

cargo_threshold 0..4095 Threshold between little and lots spritesets, see spritegroup for details.
draw_pylon_tiles
hide_wire_tiles
non_traversable_tiles
bitmask(0, 1, 2, 3, 4, 5, 6, 7) Specifies which tile types are traversible/non-traversible, and whether pylons and/or catenary shall be drawn for electrified rail types.

Note: it is common that all tile types behave the same, you may want to use the short cuts

  • 0 for no tile types, and
  • 0xFF for all tile types.
cargo_random_triggers Array of cargo labels from the cargotable Cargo types, which will trigger re-randomization when delivered, loaded or unloaded at the station.
general_flags bitmask(STAT_FLAG_XXX, STAT_FLAG_YYY, ...)
STAT_FLAG_DISTRIBUTED_CARGO
Specifies whether waiting cargo amounts are scaled by station size for spriteset selection, see spritegroup for details.
STAT_FLAG_RANDOM_ANIMATION
If set, callback anim_next_frame will get random data in extra_callback_info1
STAT_FLAG_CUSTOM_FOUNDATIONS
Enables callback foundations, see below.
STAT_FLAG_EXTENDED_FOUNDATIONS
Selects between two possible spriteset formats for callback foundations, see below.
animation_info Array [ANIMATION_XXX, frame-count] XXX = [LOOPING | NON_LOOPING], 1..253 frames
animation_speed 0..16

Speed of animation, see animation speed table for the meaning of the values.

animation_triggers bitmask(STAT_ANIM_XXX, STAT_ANIM_YYY, ...) Enables callback anim_control for specified triggers:
STAT_ANIM_IS_BUILT
Tile is built. (all new-built/overbuilt tiles)
STAT_ANIM_CARGO_ARRIVES
Cargo is deliverd from industry to station. (all station tiles)
STAT_ANIM_CARGO_REMOVED
All cargo was loaded onto a vehicle, no more cargo (of this type) is waiting. (all station tiles)
STAT_ANIM_TRAIN_ENTERS
Train stops at station. (all tiles of platform)
STAT_ANIM_TRAIN_LEAVES
Train leaves station. (all tiles of platform)
STAT_ANIM_TRAIN_LOAD_UNLOAD
Train is loading or unloading. (all tiles of platform)
STAT_ANIM_250_TICKS
Every 250 ticks. (synchronized for all tiles of the station)

Station variables

Base station variables

The following variables are shared between stations and airports:

name value range comment
random_bits_station 0..65535 16 random bits, shared between all station sections (rail station sections, airports, ...)
had_vehicle_of_type bitmask(HAD_VEHICLE_OF_TYPE_XXX, ...) Bitmask of vehicle types that have visited the station. XXX = [TRAIN | BUS | TRUCK | AIRCRAFT | SHIP].
is_waypoint [0 | 1] Whether the station is a waypoint
facilities bitmask(FACILITY_XXX, ...) Bitmask of facilities associated with the station. XXX = [TRAIN | TRUCK_STOP | BUS_STOP | AIRPORT | DOCK].
airport_type AIRPORTTYPE_XXX Type of airport, contains a bogus value if the station has no airport. XXX = [SMALL | LARGE | HELIPORT | OILRIG].
build_date date(yyyy,mm,dd) Date when the station was built. Is clamped to the 1920-2099 range.


The following variables are also shared with airports. They all require a single argument: a cargo type from your cargo translation table.

name value range comment
cargo_amount_waiting 0..32767 Units of cargo of waiting
cargo_rating 0..100 Rating for this cargo type (in %)
cargo_time_since_pickup 0..255 Time since the cargo was last picked up. 1 unit equals 185 ticks, or about 2.5 game days.
cargo_time_en_route 0..255 Time this cargo has spent en-route. 1 unit equals 185 ticks, or about 2.5 game days.
cargo_last_vehicle_speed 0..255 Speed of the last vehicle picking up this cargo type. The unit depends on the type of vehicle. For trains and road vehicles, one unit is 1 km/h; for ships, it's 0.5 km/h; for aircraft, it's 8 mph. If the max. speed is above 255 speed units, 255 is used instead. 0 if no vehicle as picked up the cargo type yet.
cargo_last_vehicle_age 0..255 Age of the last vehicle picking up this cargo type, in years. 255 if no vehicle has picked up the cargo type yet.
cargo_accepted [0 | 1] 1 if this cargo type is currently being accepted at the station, 0 otherwise.
cargo_accepted_ever [0 | 1] 1 if this cargo type has ever been accepted at the station, 0 otherwise.
cargo_accepted_last_month [0 | 1] 1 if this cargo type was accepted last month at the station, 0 otherwise.
cargo_accepted_this_month [0 | 1] 1 if this cargo type was accepted this month at the station, 0 otherwise.
cargo_accepted_bigtick [0 | 1] 1 if this cargo type was accepted at the station since the last periodic processing, which happens every 250 ticks. 0 otherwise.


Variables without a parameter

name value range comment
tile_type 0..7 The type of tile, as decided by select_tile_type. Bit 0 also tells the orientation.
terrain_type TILETYPE_XX TILETYPE_NORMAL, TILETYPE_DESERT, TILETYPE_RAIN_FOREST, TILETYPE_SNOW
track_type Entry from railtype translation table
company_num 0 ... 14 company number of the vehicle owner. TTDPatch only supports up to 8 companies (0 ... 7)
company_type PLAYERTYPE_XX
PLAYERTYPE_HUMAN
human player
PLAYERTYPE_AI
AI player
PLAYERTYPE_HUMAN_IN_AI
human managing AI company
PLAYERTYPE_AI_IN_HUMAN
AI managing human company

OpenTTD only uses PLAYERTYPE_HUMAN and PLAYERTYPE_AI. If you cheat yourself to be part of an AI company OpenTTD will still report PLAYERTYPE_AI for the company with yourself and the AI and it'll report PLAYERTYPE_HUMAN for the now uncontrolled company.

company_colour1 COLOUR_XXX

Refer to the table here for possible values.

company_colour2 COLOUR_XXX

Same as company_colour1, if no 2nd company colour is chosen. Refer to the table here for possible values.

pbs_reserved [0 | 1] 1 if the tile has been reserved by a train for PBS (Path-based signalling) purposes, 0 otherwise.
pbs_reserved_or_disabled [0 | 1] 1 if the tile has been reserved by a train for PBS (Path-based signalling) purposes, or if PBS is not enabled. Currently PBS is always considered enabled if the game version used supports it, but in the future, this may change to check if the current signal block actually uses PBS-signals.
pbs_enabled [0 | 1] 1 if PBS is enabled. Currently PBS is always considered enabled if the game version used supports it, but in the future, this may change to check if the current signal block actually uses PBS-signals.
rail_continuation bitmask(0, ... 7) see below
rail_present bitmask(0, ... 7) see below
animation_frame 0..255 Animation frame of the current tile.
random_bits_tile 0..15 4 random bits, specific to this station tile.

Rail continuation

Variables rail_continuation and rail_present both contain a bitmask, with 8 possible bits set. Each bit corresponds to one of the adjacent tiles, refer to the table or picture below. The bit in rail_present is set if the tile contains any rail track. Bits 0..3 in rail_continuation are only set if there is rail track on the tile and if that track connects to the current tile (note that this tile has no connection to the tiles corresponding to bits 2 and 3, but that doesn't matter). Bits 4..7 in rail_continuation are set if there is track on the tile and if that track connects to tile 2 or 3, whichever is applicable.

Bit Set if rail continues in direction of...
0 +Length
1 -Length
2 +Platforms
3 -Platforms
4 +Length, +Platforms
5 -Length, +Platforms
6 +Length, -Platforms
7 -Length, -Platforms

The following picture illustrates which bits represent which tile for the two possible station orientations:

Station var45.png

Variables that require one or more arguments

name arguments value range comment
nearby_tile_slope tile- and platform-offset [1] SLOPE_XXX See tile slopes for an overview of possible values. Note that the slope is 'mirrored' in the NW-SE orientation, i.e. the bits for CORNER_W and CORNER_E are swapped.
nearby_tile_is_water tile- and platform-offset [1] [0 | 1] 1 if the tile is water, 0 otherwise
nearby_tile_terrain_type tile- and platform-offset [1] TILETYPE_XX TILETYPE_NORMAL, TILETYPE_DESERT, TILETYPE_RAIN_FOREST, TILETYPE_SNOW
nearby_tile_water_class tile- and platform-offset [1] WATER_CLASS_XXX XXX = [NONE | SEA | CANAL | RIVER] Note that tiles for which nearby_tile_is_water is 0 may still have a water class, e.g. industry tiles with water beneath them.
nearby_tile_height tile- and platform-offset [1] 0..255 (currently limited to 0..15) Height of the lowest corner of the tile. 1 unit is one height level of 8 pixels.
nearby_tile_class tile- and platform-offset [1]

Tile class

nearby_tile_animation_frame tile- and platform-offset [1] 0..255 Animation frame of the given tile
nearby_tile_is_station tile- and platform-offset [1] [0 | 1] 1 if the given tile is a station tile, 0 otherwise
nearby_tile_station_id tile- and platform-offset [1] 0..255 If the given tile is a station tile defined by this NewGRF, the item ID. Else, the content is undefined.
nearby_tile_same_grf tile- and platform-offset [1] [0 | 1] 1 if the given tile is a station tile defined by this NewGRF, 0 otherwise.
nearby_tile_other_grf tile- and platform-offset [1] [0 | 1] 1 if the given tile is a station tile defined by a different NewGRF, 0 otherwise.
nearby_tile_grfid tile- and platform-offset [1] 32-bit GRFID GRFID of the NewGRF defining the given station tile.
nearby_tile_original_gfx tile- and platform-offset [1] [0 | 1] 1 if the given tile is a station tile with original graphics, 0 otherwise.
nearby_tile_same_station tile- and platform-offset [1] [0 | 1] 1 if the given tile is part of the same station, 0 otherwise. Undefined if the tile is not a station tile.
nearby_tile_perpendicular tile- and platform-offset [1] [0 | 1] 1 if the given tile a station tile aligned perpendicular to this tile, 0 if it is aligned parallel. Undefined if the tile is not a station tile.
nearby_tile_tile_type tile- and platform-offset [1] 0..7 Tile type of the given tile. The orientation bit is adjusted to be relative to the current tile's orientation:
  • 0, 2, 4, 6: Tracks are parallel.
  • 1, 3, 5, 7: Tracks are perpendicular.
platform_length PLATFROM_SAME_XXX[2] 0..15 Length of the platform (along the platform direction) in tiles
platform_count PLATFORM_SAME_XXX[2] 0..15 Number of platforms (counted perpendicular to the platform direction)
platform_position_from_start PLATFORM_SAME_XXX[2] 0..15 Position along the platform, 0 for the first (northernmost) tile.
platform_position_from_end PLATFORM_SAME_XXX[2] 0..15 Position along the platform, 0 for the last (southernmost) tile.
platform_position_from_middle PLATFORM_SAME_XXX[2] -8..7 Position along the platform, 0 for the middle tile. When the number of tiles is even, the southernmost of the two middle tiles is assigned number 0, so there is one more negative than positive number. Using PLATFORM_SAME_DIRECTION is not possible here.
platform_number_from_start PLATFORM_SAME_XXX[2] 0..15 Platform number, counting from top to bottom, so 0 for the northernmost platform.
platform_number_from_end PLATFORM_SAME_XXX[2] 0..15 Platform number, counting from bottom to top, so 0 for the southernmost platform.
platform_number_from_middle PLATFORM_SAME_XXX[2] -8..7 Platform number, counting top to bottom, using 0 for the middle platform. When the number of platforms is even, the southernmost of the two middle platformsis assigned number 0, so there is one more negative than positive number. Using PLATFORM_SAME_DIRECTION is not possible here.
  1. 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 1.11 1.12 1.13 1.14 1.15 The first parameter is the distance to move along the platform, the second parameter is the distance to move sideways (between platforms). Both parameters are signed numbers with range -8..7, negative numbers go northwards.
  2. 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 Possible values are:
    PLATFORM_SAME_STATION
    Consider all tiles that are part of the same station
    PLATFORM_SAME_SECTION
    Consider all tiles that are part of the same individually built section
    PLATFORM_SAME_DIRECTION
    Consdier all tiles that are part of the same station and have the same platform direction.

Station callbacks

The following table contains a list of available station callbacks.

Additionally, it's possible to provide cargo-specific graphics, using the identifier from the cargo table as callback name. These callbacks will be used if the cargo is waiting at the station. If multiple cargo types are waiting at the station, OpenTTD will pick one of the options the station provides. If none of the listed cargo types is waiting at the station, the default callback will be used.

Cargo-specific graphics callbacks are never called from the purchase menu, refer to the purchase callback below instead.

Note that the above affects graphics only, other callbacks are unaffected.

callback return value comment
default spritegroup See below.
purchase spritegroup or spriteset See below. If a spritegroup is linked instead of a spriteset, the "zero cargo amount" spriteset is used.
custom_spritesets Array of spritesets See below.
sprite_layouts Array of spritelayouts See below. The number of sprite_layouts must be even, alternating X (⤢) and Y (⤡) orientations.
select_sprite_layout index into sprite_layouts[] See below. The result's even-/oddness is ignored. The orientation is always adjusted by OpenTTD.
purchase_select_sprite_layout index into sprite_layouts[] See below. The result's even-/oddness is ignored. The orientation is always adjusted by OpenTTD.
prepare_layout expression list See below.
purchase_prepare_layout expression list See below.
foundations sprite set See below.
availability [0 | 1] Return 1 to make the station show up in the build window
tile_check Same as for the location_check industry callback Decide whether station may be built on this tile. This is an additional check to all built-in checks (like slope checks), you can only further restrict construction, not lessen conditions.

Called before constructing the station section, so nothing exists on the map yet. Since the station isn't built yet, so you can't access station variables. Only these variables are available: company-information, and the class, height, slope, terrain type and water status of nearby tiles.

  • getbits(extra_callback_info1, 4, 4): The tile slope of the tile.
  • getbits(extra_callback_info1, 0, 4): The tile slope of the tile, adjusted by station orientation:
    • unmodified in X direction (⤢)
    • mirrored in Y direction (⤡)
  • getbits(extra_callback_info2, 0, 8): Tile position along the new-built platform. (0 = north tile)
  • getbits(extra_callback_info2, 8, 8): Platform number within the new-built section. (0 = north platform)
  • getbits(extra_callback_info2, 16, 8): Length of the new section being built.
  • getbits(extra_callback_info2, 24, 8): Number of platforms in the new section being built.
select_tile_type [0 | 2 | 4 | 6] Decides which tile type to store for each tile during construction. The lowest bit is always defined by the station orientation, no matter the callback result. See also tile type above.
anim_next_frame Next animation frame or CB_RESULT_XXX Called for every animation frame, returns the next frame to display. Alternatively, return CB_RESULT_NEXT_FRAME or CB_RESULT_STOP_ANIMATION to show the next frame or stop animation, respectively.
  • extra_callback_info1: 32 random bits, if enabled in the general_flags property.

Returning a sound effect in the high byte will cause that sound effect to be played.

anim_control Next animation frame or CB_RESULT_XXX

Called whenever an animation trigger happens. Return the animation frame to show, or CB_RESULT_XXX with XXX = [CB_RESULT_START_ANIMATION | STOP_ANIMATION | DO_NOTHING] to respectively start the animation in its current frame, stop the animation or do nothing. Returning a sound effect in the high byte will cause that sound effect to be played.

  • extra_callback_info1: 32 random bits. The low 16 bits are always different for each station tile, but the high 16 bits are the same for all triggered tiles.
  • getbits(extra_callback_info2, 0, 8): Reason for the callback trigger (STAT_ANIM_xxx). Note that you need to enable the wanted triggers in the animation_triggers property.
  • getbits(extra_callback_info2, 8, 8): Cargo-type involved in the trigger. Only applies to STAT_ANIM_CARGO_ARRIVES, STAT_ANIM_CARGO_REMOVED, STAT_ANIM_TRAIN_LOAD_UNLOAD.
anim_speed 0 .. 16 Decide the time an animation frame should last. Return value is interpreted as (num_ticks = 2^anim_speed), which each tick lasting 30 ms. Avoid using this callback if possible, since it has to be called each tick for every animated tile. This can be used to create animation frames that last between 30 ms and 33 minutes.

Graphics

Nml station graphics.dot.png

foundations

If STAT_FLAG_CUSTOM_FOUNDATIONS is enabled in general_flags you can draw custom foundation for station tiles on sloped terrain.

There are two options for providing foundation sprites:

STAT_FLAG_EXTENDED_FOUNDATIONS not set

The callback should return a spriteset looking like this:

Simple foundations.png

The foundations will be drawn by combining multiple sprites, as needed for the slope.

STAT_FLAG_EXTENDED_FOUNDATIONS

The callback should return a spritset looking like this:

Extended foundations.png

In addition you will have to check

  • getbits(extra_callback_info2, 16, 2):
    • 0: sprites as in template above.
    • 1: sprites like before, but with no wall on NW edge.
    • 2: sprites like before, but with no wall on NE edge.
    • 3: sprites like before, but with no walls on either north edge.