NewGRF Town Feature Additions to NewGRF Specifications in JGR's Patchpack

This document describes the non-standard additions to the town feature in the Official OpenTTD NewGRF Specifications, as implemented in this patchpack.

The town feature is ordinarily only accessible via the parent scope from the features: stations, bridges, houses, industries, objects, road stops.

Mapping a feature ID to the town feature allows referencing it directly, this is useful for:

NewGRFs which use this feature MUST use the feature ID mapping mechanism to map the town feature to a local feature ID.

This feature is indicated by the feature name: town_feature, version 1.
The feature name to use for feature ID mapping is town.

This feature may not necessarily match implementations in other patches, branches, etc.
This feature as implemented here MAY also be present in other patchpacks.

See the NewGRF additions document for background information on additions to the NewGRF specifications.

The functionality listed below is also supported in a fork of NML, see the associated NML town feature and NML additions documents for more details.

Actions:

Variational Action 2 - Town

Note: non-variational action 2 sprites should ONLY be used to implement the return callback failure pattern.

See the Variational Action 2 Specification for background information.

Variables:
Mappable nameDescription
town_house_countNumber of town houses
town_populationTown population
town_zone_0_radius_squareTown zone 0 radius squared
town_zone_1_radius_squareTown zone 1 radius squared
town_zone_2_radius_squareTown zone 2 radius squared
town_zone_3_radius_squareTown zone 3 radius squared
town_zone_4_radius_squareTown zone 4 radius squared
town_xyTown tile X and Y coordinates

Number of town house (mappable variable: town_house_count)

This is the same as town variable B6, except 32 bits and not clamped to a maximum value of 0xFFFF.

This requires town_uncapped_variables, version 1.

Town population (mappable variable: town_population)

This is the same as town variable 82, except 32 bits and not clamped to a maximum value of 0xFFFF.

This requires town_uncapped_variables, version 1.

Town zone [0 .. 4] radius squared (mappable variable: town_zone_0_radius_square, town_zone_1_radius_square, town_zone_2_radius_square, town_zone_3_radius_square, town_zone_4_radius_square)

This is the same as town variables 94, 96, 98, 9A, 9C, except 32 bits and not clamped to a maximum value of 0xFFFF.

This requires town_uncapped_variables, version 1.

Town tile X and Y coordinates (mappable variable: town_xy)

BitsMeaning
0 - 15X coordinate of town tile
16 - 31Y coordinate of town tile

This is similar to town variable 80, except the Y part is in the upper 16 bits and the X part is in the lower 16 bits.

This is the same format as house variable 47.

This requires varaction2_towns_town_xy, version 1.


Action 3 - Town

See the Action 3 Specification for background information.

Only generic callbacks are supported, the "number of IDs" field in the action 3 must be set to 0.

The variational action 2 sprite group referenced must be a callback handler which properly branches on the value of callback variable 0C.

The following callbacks are defined:

Callback IDPurposeEnabled if
0xEC008001Custom town zone radiiThe town_zone_callback feature is tested for

Town zone radii callback 0xEC008001:

The town_zone_callback feature must be tested for to enable this generic callback.

This callback is called whenever the zone radii of a town need to be recalculated.
This can occur when:

The callback is not called if the town zone radii calculations have been manually overriden by settings.

The return value of the callback is the version of the result format returned by the callback.
Currently only version 0 is defined.
The callback must store the values of the town zone radii into registers: 0x100 to 0x104, for zones 0 to 4 respectively.

A callback failure result should be returned to use the default town zone radii calculation (or to allow another GRF to handle the callback).

The town_house_count variable should be used instead of variable B6, otherwise the results may be incorrect for large towns.
Implementers of this callback may assume that the town_uncapped_variables feature is present.