NewGRF Road Stops Addition to NewGRF Specifications in JGR's Patchpack in NML

This document describes the non-standard addition of the NewGRF road stops feature to the Official OpenTTD NML Specifications, as implemented in this patchpack, and the associated NML fork
This feature does not match OpenTTD PR #7955 in a number of key areas, this feature may not necessarily match implementations of NewGRF road stops in other patches, branches, etc.
This feature as implemented here MAY also be present in other patchpacks.

The feature identifier is FEAT_ROADSTOPS, (the PARENT scope for this feature is the road stop's station's town).
There is no permanent storage associated with this feature.

See the NewGRF additions (NML) document for background information on additions to NML.

See the associated non-NML document for more details on the NewGRF road stops feature.

This feature will be automatically skipped when loaded into a version of OpenTTD which does not support this feature.
If this feature is the only significant thing in this GRF, then extended_feature_test("road_stops") SHOULD be called and some message, error or other form of signalling to the user used to inform the user that this version of OpenTTD does not support the feature, if the return value is false.
Otherwise the GRF could silently do nothing instead of the expected functionality, creating confusion for end users.

Sections:

Road Stop IDs

A road stop is allocated by setting the 'class'-property, which should therefore be set first.
Road stop IDs are NewGRF-local and can be freely chosen in the 0..63999 range, as of version 7 of the road_stops feature.
When loaded into a version of OpenTTD with versions 1 to 6 of the road_stops feature, IDs are limited to the range: 0..254. Any road stops with IDs outside this range will be skipped.

Road Stop Properties

PropertyValue rangeComment
classString literal of length 4 This property must be set first, before any other properties or graphics. Characters allowed in the IDs are A-Z, 0-9.
Predefined classes include:
  • DFLT - Default class
  • WAYP - Waypoints: All road waypoints must be put in this class
classnamestringYou only need to set this for one object in every class.
namestring
availability_typeRST_AVAILABILITY_TYPE_XXXXXX = PASSENGER | FREIGHT | ALL
This is ignored for stops in the WAYP waypoint class
draw_modebitmask(RST_DRAW_FLAG_XXX, ...)

RST_DRAW_FLAG_BAY_ROAD
Draw road type ground sprite for bay stops.

RST_DRAW_FLAG_DRIVE_THROUGH_ROAD_OVERLAY
Draw road overlays for drive-through stops.

RST_DRAW_FLAG_WAYPOINT_GROUND
Draw spritelayout ground sprite on top of underlying road (if unset, the spritelayout ground sprite is not drawn).

cargo_random_triggerscargo bitmaskCargo bitmask to use for random triggers
animation_infoArray [ANIMATION_XXX, frame-count]XXX = [LOOPING | NON_LOOPING], 1..253 frames
animation_speed0..16Speed of animation, see animation speed table for the meaning of the values.
animation_triggersbitmask(ANIM_TRIGGER_ROAD_STOP_XXX, ...)Bitmask of triggers that will trigger the anim_control callback, see the table below.
general_flagsbitmask(RST_GENERAL_FLAG_XXX, ...)

RST_GENERAL_FLAG_RANDOM_ANIMATION
Animation callback requires random bits in variable extra_callback_info1.

RST_GENERAL_FLAG_NO_ONE_WAY_OVERLAY
Do not show one way road overlay sprites, this should only be set if different graphics are provided for the different one-way states using the one_way_info variable.

RST_GENERAL_FLAG_NO_CATENARY
Do not show catenary graphics. (This only takes effect from road_stops version 2).

RST_GENERAL_FLAG_DRIVE_THROUGH_ONLY
Only allow drive-through stops (not bay stops). (This only takes effect from road_stops version 2).

RST_GENERAL_FLAG_NO_AUTO_ROAD_CONNECTION
Do not automatically build connecting road pieces. (This only takes effect from road_stops version 3).

RST_GENERAL_FLAG_BUILD_MENU_ROAD_ONLY
Only show in the road build menu (not tram). (This only takes effect from road_stops version 4).

RST_GENERAL_FLAG_BUILD_MENU_TRAM_ONLY
Only show in the tram build menu (not road). (This only takes effect from road_stops version 4).

RST_GENERAL_FLAG_BUILD_MENU_DRAW_DISABLED_VIEWS
Use custom graphics for disabled road stop views. (This only takes effect from road_stops version 8).

minimum_bridge_heightArray of 6 items [0..255, ...]Minimum clearances required for a bridge for each of the 6 views/rotations (or 0 to not allow any bridge). Values are given in height level units (1 level == 8px).
disallowed_bridge_pillarsArray of 6 items [bitmask(RST_BRIDGE_PILLAR_FLAG_, ...), ...]

Which bridge pillars are disallowed on the tile for each of the 6 views/rotations.

RST_BRIDGE_PILLAR_FLAG_CORNER_W
Pillar in west corner

RST_BRIDGE_PILLAR_FLAG_CORNER_S
Pillar in south corner

RST_BRIDGE_PILLAR_FLAG_CORNER_E
Pillar in east corner

RST_BRIDGE_PILLAR_FLAG_CORNER_N
Pillar in north corner

RST_BRIDGE_PILLAR_FLAG_EDGE_NE
Pillar along entire north-east edge

RST_BRIDGE_PILLAR_FLAG_EDGE_SE
Pillar along entire south-east edge

RST_BRIDGE_PILLAR_FLAG_EDGE_SW
Pillar along entire south-west edge

RST_BRIDGE_PILLAR_FLAG_EDGE_NW
Pillar along entire north-west edge

cost_multipliers[build_cost, clear_cost]Build and clear cost multipliers, 16 is the same as a non-NewGRF road stop
height0..255Road stop height (in the build window), in height level units (1 level == 8px), see also: object height property.

Road Stop Variables

A number of variables are shared between road stops and stations. These are listed on the stations page.

NameValue rangeComment
view0..5The view/rotation of the road stop
stop_typeRST_TYPE_XXXXXX = BUS | TRUCK | WAYPOINT
terrain_typeTILETYPE_XXXXXX = NORMAL | DESERT | RAIN_FOREST | SNOW
tile_slopeSLOPE_XXXSee tile slopes for an overview of possible values
has_road0 | 11 is this road stop has road
has_tram0 | 11 is this road stop has tram
road_typeroad type | 0xFFRoad type. If there is no road the value will be 0xFF. If the roadtype has no entry in the roadtype translation table of the GRF, this value will be 0xFF. If no translation table is present, the raw value will be returned.
tram_typetram type | 0xFFTram type. If there is no tram the value will be 0xFF. If the tramtype has no entry in the tramtype translation table of the GRF, this value will be 0xFF. If no translation table is present, the raw value will be returned.
town_manhattan_distManhattan distance to the associated town
town_euclidean_distSquared euclidean distance to the associated town
town_zonetown zoneThe town zone of the current tile in the associated town.
company_num0..14Company number of the road stop owner
company_typePLAYERTYPE_XX
company_colour1COLOUR_XXX
company_colour2COLOUR_XXX
animation_frame0..255Animation frame of the current tile
waiting_triggers0..255Waiting triggers
random_bits0..16777215All random bits
random_bits_tile0..255Random bits (per tile), see also random_bits_station
one_way_infoRST_OWI_XXXOne-way road information of drive-through stop tile
XXX = TWO_WAY | WEST_BOUND | EAST_BOUND | NO_ENTRY
one_way_info_inferredRST_OWI_XXXInferred one-way road information of drive-through stop tile
XXX = TWO_WAY | WEST_BOUND | EAST_BOUND | NO_ENTRY

Variables that require one or more parameters:
NameArgumentsValue rangeComment
nearby_tile_slopex, y offset (-8..7)SLOPE_XXXSlope of a nearby tile
nearby_tile_is_waterx, y offset (-8..7)0 | 1Is nearby tile a water tile?
nearby_tile_terrain_typex, y offset (-8..7)See terrain_type
nearby_tile_water_classx, y offset (-8..7)WATER_CLASS_XXXXXX = [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_heightx, y offset (-8..7)The minimum height of the given tile in height level units
nearby_tile_classx, y offset (-8..7)tile class
nearby_tile_infox, y offset (-8..7)Above nearby tile variables in one variable (all of variable 0x67)
nearby_tile_animation_framex, y offset (-8..7)0..255Animation frame of a nearby road stop tile
nearby_tile_is_road_stopx, y offset (-8..7)0 | 1Is nearby tile a road stop?
nearby_tile_road_stop_idx, y offset (-8..7)Is nearby_tile_same_grf is true, ID of a road stop on a nearby tile
nearby_tile_same_grfx, y offset (-8..7)0 | 1Is a road stop on a nearby tile defined by the same GRF?
nearby_tile_other_grfx, y offset (-8..7)0 | 1Is a road stop on a nearby tile defined by another GRF?
nearby_tile_original_gfxx, y offset (-8..7)0 | 1Is a road stop on a nearby tile using original graphics?
nearby_tile_same_stationx, y offset (-8..7)0 | 1Is a road stop on a nearby tile the same station as this?
nearby_tile_viewx, y offset (-8..7)0..5The view/rotation of a nearby road stop tile
nearby_tile_different_viewx, y offset (-8..7)0 | 1Is the view/rotation of a road stop on a nearby tile different to that of this tile?
nearby_tile_is_drive_throughx, y offset (-8..7)0 | 1Is nearby road stop tile a drive-through road stop?
nearby_tile_stop_typex, y offset (-8..7)RST_TYPE_XXXSee stop_type
nearby_tile_same_stop_typex, y offset (-8..7)0 | 1Is the stop type of a nearby road stop tile the same as this tile?
nearby_tile_one_way_infox, y offset (-8..7)RST_OWI_XXXOne-way state of nearby drive-through road stop tile
nearby_tile_road_stop_infox, y offset (-8..7)Above nearby road stop tile variables in one variable (all of variable 0x68)
nearby_tile_grfidx, y offset (-8..7)-1, 0 or a GRFIDReturn value is -1 if the tile is not a road stop, 0 if the tile is a non-custom road stop, or else the GRFID of the NewGRF defining the road stop
nearby_tile_is_plain_roadx, y offset (-8..7)0 | 1Is nearby tile a plain road tile
nearby_tile_road_bitsx, y offset (-8..7)bitmask(ROADBIT_XXX, ...)XXX = [NW | SW | SE | NE]
Present road bits on nearby tile
nearby_tile_tram_bitsx, y offset (-8..7)bitmask(ROADBIT_XXX, ...)XXX = [NW | SW | SE | NE]
Present tram bits on nearby tile
nearby_tile_road_piecex, y offset (-8..7)0..18 | 0xFFPresent road piece and slope in sprite order, or 0xFF if none
nearby_tile_tram_piecex, y offset (-8..7)0..18 | 0xFFPresent tram piece and slope in sprite order, or 0xFF if none
nearby_tile_road_stop_infox, y offset (-8..7)Above nearby road tile variables in one variable (all of variable 0x6B)
nearby_tile_road_stop_info_v2x, y offset (-8..7)Above nearby road tile variables in one variable (all of variable roadstop_road_stop_info_nearby_tiles_v2)

Road Stop Callbacks

CallbackReturn valueComment
defaultSprite layoutNormal graphics for a road stop placed on the map
purchaseSprite layoutGraphics shown in the build menu
availability0 | 1Whether this road stop type is available in the build menu, 1 is available, 0 is unavailable
anim_controlNext 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, if the general flag RST_GENERAL_FLAG_RANDOM_ANIMATION is set.
getbits(extra_callback_info2, 0, 8): Reason for the callback trigger, see the table below.
anim_next_frameNext 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.
Returning a sound effect in the high byte will cause that sound effect to be played (e.g. return (sound("mysound.wav") << 8) | CB_RESULT_NEXT_FRAME;).
extra_callback_info1: 32 random bits, if the general flag RST_GENERAL_FLAG_RANDOM_ANIMATION is set.
anim_speed0 .. 16Decide 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.

Road Stop Animation Triggers

Animation triggerDescriptionHappens onextra_callback_info2
ANIM_TRIGGER_ROAD_STOP_BUILTRoad stop is builtnewly built tile
ANIM_TRIGGER_ROAD_STOP_NEW_CARGONew cargo arrives at stationall tilesBits 8..15 contain the triggering cargo type
ANIM_TRIGGER_ROAD_STOP_CARGO_TAKENCargo removed from stationall tilesBits 8..15 contain the triggering cargo type
ANIM_TRIGGER_ROAD_STOP_VEH_ENTERRoad vehicle enters stop (starts loading/unloading)tile where the vehicle is
ANIM_TRIGGER_ROAD_STOP_VEH_LEAVERoad vehicle leaves stop (done loading/unloading)tile where the vehicle is
ANIM_TRIGGER_ROAD_STOP_VEH_LOADRoad vehicle loads/unloads cargotile where the vehicle is
ANIM_TRIGGER_ROAD_STOP_250_TICKSEvery 250 ticksall tiles

Road stop views/rotations

The 6 road stop views/rotations are described below:
Views/rotationValueTypeDescription
RST_VIEW_BAY_NE0BayFacing north-east
RST_VIEW_BAY_SE1BayFacing south-east
RST_VIEW_BAY_SW2BayFacing south-west
RST_VIEW_BAY_NW3BayFacing north-west
RST_VIEW_DRIVE_THROUGH_X4Drive-throughX-axis: north-east to south-west
RST_VIEW_DRIVE_THROUGH_Y5Drive-throughY-axis: north-west to south-east

Syntax example

grf {
	...
}

if (!extended_feature_test("road_stops")) {
	error(FATAL, string(STR_UNSUPPORTED_VERSION));
}


spritelayout spritelayout_roadstop {
	ground {
		...
	}
	building {
		...
	}
}

switch (FEAT_ROADSTOPS, SELF, switch_roadstop, ...) {
	...
}

item (FEAT_ROADSTOPS, item_roadstop)  {
	property {
		class: "TEST";
		availability_type: RST_AVAILABILITY_TYPE_PASSENGER;
		name: string(STR_ROADSTOP_NAME);
		classname: string(STR_ROADSTOP_TEST_CLASS_NAME);
	}
	graphics {
		default: switch_roadstop;
	}
}