## 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:

- IDs
- Properties
- Variables
- Callbacks
- Animation triggers
- Views/rotations
- Syntax example

### 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

Property | Value range | Comment
--- | --- | ---
class | String 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
classname | string | You only need to set this for one object in every class.
name | string |
availability_type | RST_AVAILABILITY_TYPE_XXX | XXX = PASSENGER | FREIGHT | ALL This is ignored for stops in the WAYP waypoint class
draw_mode | bitmask(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_triggers | cargo bitmask | Cargo bitmask to use for random triggers
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(ANIM_TRIGGER_ROAD_STOP_XXX, ...) | Bitmask of triggers that will trigger the anim_control callback, see the table below.
general_flags | bitmask(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).
minimum_bridge_height | Array 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_pillars | Array 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
height | 0..255 | Road 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.

Name | Value range | Comment
--- | --- | ---
view | 0..5 | The view/rotation of the road stop
stop_type | RST_TYPE_XXX | XXX = BUS | TRUCK | WAYPOINT
terrain_type | TILETYPE_XXX | XXX = NORMAL | DESERT | RAIN_FOREST | SNOW
tile_slope | SLOPE_XXX | See tile slopes for an overview of possible values
has_road | 0 | 1 | 1 is this road stop has road
has_tram | 0 | 1 | 1 is this road stop has tram
road_type | road type | 0xFF | Road 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_type | tram type | 0xFF | Tram 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_dist |  | Manhattan distance to the associated town
town_euclidean_dist |  | Squared euclidean distance to the associated town
town_zone | town zone | The town zone of the current tile in the associated town.
company_num | 0..14 | Company number of the road stop owner
company_type | PLAYERTYPE_XX |
company_colour1 | COLOUR_XXX |
company_colour2 | COLOUR_XXX |
animation_frame | 0..255 | Animation frame of the current tile
waiting_triggers | 0..255 | Waiting triggers
random_bits | 0..16777215 | All random bits
random_bits_tile | 0..255 | Random bits (per tile), see also random_bits_station
one_way_info | RST_OWI_XXX | 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:

Name | Arguments | Value range | Comment
--- | --- | --- | ---
nearby_tile_slope | x, y offset (-8..7) | SLOPE_XXX | Slope of a nearby tile
nearby_tile_is_water | x, y offset (-8..7) | 0 | 1 | Is nearby tile a water tile?
nearby_tile_terrain_type | x, y offset (-8..7) |  | See terrain_type
nearby_tile_water_class | x, y offset (-8..7) | 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 | x, y offset (-8..7) |  | The minimum height of the given tile in height level units
nearby_tile_class | x, y offset (-8..7) | tile class |
nearby_tile_info | x, y offset (-8..7) |  | Above nearby tile variables in one variable (all of variable 0x67)
nearby_tile_animation_frame | x, y offset (-8..7) | 0..255 | Animation frame of a nearby road stop tile
nearby_tile_is_road_stop | x, y offset (-8..7) | 0 | 1 | Is nearby tile a road stop?
nearby_tile_road_stop_id | x, y offset (-8..7) |  | Is nearby_tile_same_grf is true, ID of a road stop on a nearby tile
nearby_tile_same_grf | x, y offset (-8..7) | 0 | 1 | Is a road stop on a nearby tile defined by the same GRF?
nearby_tile_other_grf | x, y offset (-8..7) | 0 | 1 | Is a road stop on a nearby tile defined by another GRF?
nearby_tile_original_gfx | x, y offset (-8..7) | 0 | 1 | Is a road stop on a nearby tile using original graphics?
nearby_tile_same_station | x, y offset (-8..7) | 0 | 1 | Is a road stop on a nearby tile the same station as this?
nearby_tile_view | x, y offset (-8..7) | 0..5 | The view/rotation of a nearby road stop tile
nearby_tile_different_view | x, y offset (-8..7) | 0 | 1 | Is the view/rotation of a road stop on a nearby tile different to that of this tile?
nearby_tile_is_drive_through | x, y offset (-8..7) | 0 | 1 | Is nearby road stop tile a drive-through road stop?
nearby_tile_stop_type | x, y offset (-8..7) | RST_TYPE_XXX | See stop_type
nearby_tile_same_stop_type | x, y offset (-8..7) | 0 | 1 | Is the stop type of a nearby road stop tile the same as this tile?
nearby_tile_one_way_info | x, y offset (-8..7) | RST_OWI_XXX | One-way state of nearby drive-through road stop tile
nearby_tile_road_stop_info | x, y offset (-8..7) |  | Above nearby road stop tile variables in one variable (all of variable 0x68)
nearby_tile_grfid | x, y offset (-8..7) | -1, 0 or a GRFID | Return 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_road | x, y offset (-8..7) | 0 | 1 | Is nearby tile a plain road tile
nearby_tile_road_bits | x, y offset (-8..7) | bitmask(ROADBIT_XXX, ...) | XXX = [NW | SW | SE | NE] Present road bits on nearby tile
nearby_tile_tram_bits | x, y offset (-8..7) | bitmask(ROADBIT_XXX, ...) | XXX = [NW | SW | SE | NE] Present tram bits on nearby tile
nearby_tile_road_piece | x, y offset (-8..7) | 0..18 | 0xFF | Present road piece and slope in sprite order, or 0xFF if none
nearby_tile_tram_piece | x, y offset (-8..7) | 0..18 | 0xFF | Present tram piece and slope in sprite order, or 0xFF if none
nearby_tile_road_stop_info | x, y offset (-8..7) |  | Above nearby road tile variables in one variable (all of variable 0x6B)
nearby_tile_road_stop_info_v2 | x, 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

Callback | Return value | Comment
--- | --- | ---
default | Sprite layout | Normal graphics for a road stop placed on the map
purchase | Sprite layout | Graphics shown in the build menu
availability | 0 | 1 | Whether this road stop type is available in the build menu, 1 is available, 0 is unavailable
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, 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_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. 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_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.

### Road Stop Animation Triggers

Animation trigger | Description | Happens on | extra_callback_info2
--- | --- | --- | ---
ANIM_TRIGGER_ROAD_STOP_BUILT | Road stop is built | newly built tile |
ANIM_TRIGGER_ROAD_STOP_NEW_CARGO | New cargo arrives at station | all tiles | Bits 8..15 contain the triggering cargo type
ANIM_TRIGGER_ROAD_STOP_CARGO_TAKEN | Cargo removed from station | all tiles | Bits 8..15 contain the triggering cargo type
ANIM_TRIGGER_ROAD_STOP_VEH_ENTER | Road vehicle enters stop (starts loading/unloading) | tile where the vehicle is |
ANIM_TRIGGER_ROAD_STOP_VEH_LEAVE | Road vehicle leaves stop (done loading/unloading) | tile where the vehicle is |
ANIM_TRIGGER_ROAD_STOP_VEH_LOAD | Road vehicle loads/unloads cargo | tile where the vehicle is |
ANIM_TRIGGER_ROAD_STOP_250_TICKS | Every 250 ticks | all tiles |

### Road stop views/rotations

The 6 road stop views/rotations are described below:

Views/rotation | Value | Type | Description
--- | --- | --- | ---
RST_VIEW_BAY_NE | 0 | Bay | Facing north-east
RST_VIEW_BAY_SE | 1 | Bay | Facing south-east
RST_VIEW_BAY_SW | 2 | Bay | Facing south-west
RST_VIEW_BAY_NW | 3 | Bay | Facing north-west
RST_VIEW_DRIVE_THROUGH_X | 4 | Drive-through | X-axis: north-east to south-west
RST_VIEW_DRIVE_THROUGH_Y | 5 | Drive-through | Y-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;
    	}
    }