Callbacks

From GRFSpecs
Revision as of 16:14, 16 June 2011 by Frosch (talk | contribs) (shared cb result for cb 148)
Jump to navigationJump to search

Introduction

A callback is a special action 2 that the patch "calls" in order to modify various features, an example being the visual effect of train vehicles.  See the callback tutorial on how to use them.

In the final action 2 of a chain of variational action 2s, the second byte of the matching entry has to have bit 7 set to identify it as a callback result. (Previously, it was required that the second byte be FF, but now only bit 7 needs to be set.)

For example, 04 00 is not a callback result (but it may be the ID of another chained action 2), whereas 04 80 is a callback result with a value of 4.  For some callbacks, 15 bit results are possible, in which case the upper 7 bits are stored in the second byte.  For example, 54 C2 is a callback result with a value of 4254=16980, where again the second byte has bit 7 set, changing the 42 into C2.

For compatibility with earlier patch versions, FF in the high byte is taken to mean the same thing as 80, so 04 FF also has a callback result of 4.  Note that if your grf file needs to be compatible with versions before TTDPatch 2.0.1 alpha 40, you must set the high byte to FF, and so can use only 8 bit results.

List of callbacks

The following callbacks are defined by the patch.  The number of the callback is what will be stored in variable 0C so that you can return the right results if you have several callbacks.  All callbacks are explained in more detail below.

PLEASE NOTE: Since TTDPatch 2.5 beta 5, the size of variable 0C has changed, and now there are word-sized callback numbers as well. To maintain backwards compatibility, only callbacks 10..3F can be checked using a byte-sized check. Callbacks 140 and above, on the other hand, must be checked using a word or dword sized check, to make sure they are identified uniquely.

Number Feature(s) Meaning
10 Vehicles Visual effect and wagon power
11 Vehicles Wagon length
12 Vehicles Load amount
13 Stations Station availability
14 Stations Use callback to select sprite layout
15 Vehicles Set refitted capacity
16 Trains Build articulated engines
17 Houses House construction check
18 Several (G*) AI construction/purchase selection
19 Vehicles Cargo sub-type display
1A Houses Next animation frame
1B Houses Animation control
1C Houses Construction stage changes
1D Trains Can wagon be attached
1E Houses Decide colour of building
1F Houses Cargo acceptance
20 Houses Length of animation frame
21 Houses Trigger building destruction
22 Industries Availability
23 Vehicles Additional text in purchase screen
24 Stations Custom station layout
25 Industry tiles Animation control
26 Industry tiles Next animation frame
27 Industry tiles Length of animation frame
28 Industries Industry location permissibility
29 Industries Random production change
2A Houses Get accepted cargo types
2B Industry tiles Decide cargo acceptance
2C Industry tiles Get accepted cargo types
2D Vehicles Select colour mapping for vehicle
2E Houses Custom cargo production
2F Industry tiles Custom shape check
30 Industry tiles Decide drawing default foundations
31 Vehicles Start/stop check
32 Vehicles 32-day callback
33 Several Sound effect callback
34 Vehicles (G*) Autoreplace vehicle selection
35 Industries Monthly random production change
36 Vehicles Change vehicle Properties
37 Industries Cargo sub-type display
38 Industries Show additional text in fund window
39 Cargoes Custom profit calculation
3A Industries Show additional text in industry window
3B Industries Control special effects
3C Industry tiles Disable autosloping
3D Industries Opt out of accepting cargo
40..13F --Reserved--
140 Stations Animation control
141 Stations Next animation frame
142 Stations Length of animation frame
143 Houses Protect building conditionally
144 Sounds (G*) Ambient sound effects
145 Cargoes Custom station rating calculation
146 New Signals (G*) New signals sprite drawing
147 Canals Add sprite offset
148 Houses Watched cargo accepted
149 Stations Land slope check
14A Industries Decide industry color
14B Industries Decide input cargo types
14C Industries Decide output cargo types
14D Houses Customized building name
14E Houses Decide drawing default foundations
14F Houses Disable autosloping
150 Airport tiles Decide drawing default foundations
152 Airport tiles Animation control (OpenTTD > r19197)
153 Airport tiles Next Animation frame (OpenTTD > r19197)
154 Airport tiles Length of animation frame (OpenTTD > r19197)
155 Airports Extra information about airport layout in the build gui (OpenTTD > r20372)
156 Airports Airport layout name (OpenTTD > r20373)
157 Objects Land slope check
158 Objects Next animation frame
159 Objects Animation control
15A Objects Length of animation frame
15B Objects Decide colour of building
15C Objects Show additional text in building window
15D Objects Disable autosloping

(*) Generic callbacks are called for the feature, not any specific vehicle ID. Read the Action 3 entry on how to define these.

Visual effect and wagon power (10)

This callback is used to determine the visual effect to use for a vehicle and whether a train wagon is powered (adding power and weight to the train).

The 'powered wagon'-flag only applies for train wagons that would by default be powered (i.e. property 1B is set).

The visual effect applies to all train vehicles (since OpenTTD r21238 for road vehicles and ships as well).

The callback is only called when loading a game, when the train reverses, or when rearranging the train in a depot.

In OpenTTD the 'visual effect' is also updated when the vehicle enters track of a different railtype. The 'powered wagon'-flag may not change in that case.

If the callback fails for any reason (e.g. not defined, action 2 does not return callback result etc.), the value of the corresponding action 0 property ( train property 22, road vehicle property 21, ship property 1C ) is used instead.  For possible return values, refer to these properties as well.

Wagon length callback (11)

This callback is used instead of property 21 whenever the train leaves a depot or is displayed inside a depot. If the callback fails, the value of property 21 is used instead.

Road vehicles do not have a property for this purpose. If the callback fails, a length of 8/8 is used.

The callback result may change only when whole vehicle chain is inside a depot.

Load amount callback (12)

This callback is used instead of property 07 when loading a game or rearranging a train in a depot (or when buying other vehicles). If the callback fails, the value of property 07 is used instead.

Note: For aircraft carrying both passengers and mail this callback is broken (wrt. mail) in TTDPatch and OpenTTD before r14672.

Since OpenTTD r14672 the callback is called for passengers and for mail. The mail compartment behaves like a wagon attached to a train engine. I.e. to read general variables of the aircraft you have to use varaction2 type 82/86/8A (related object), as most variables are not valid for the mail compartment.

Finally to distinguish the passenger and the mail part you can use variable 47 or even 40.

Station availability callback (13)

This sets whether a station can be constructed or not, i.e. whether it can be selected in the station construction window.  A non-zero callback return indicates the station can be built, and a return code of zero removes the station from the selection.

Station sprite layout (14)

Callback 14 selects an entry from the sprite layout (set by prop. 09 or the default if unset), and if its return value is invalid then the sprite layout given from the tile type will be used.  You can use this to have more than 4 different sprite sets to choose from.

Bit 0 (station orientation) of the return value is ignored, and instead set to bit 0 of the actual tile, so that you do not have to check the orientation explicitly and return the two corresponding values, instead just organize the layouts such that even numbers correspond to X orientation (NE-SW) and odd numbers corresponding to Y orientation (NW-SE).

The effect is like having additional tile types that are however not actually built, but only show different graphics depending on this callback.

Refitted capacity callback (15)

This callback is used when a vehicle is refitted, to find the new capacity. It is a 15 bit callback since TTDPatch 2.0.1 alpha 40, and allows return values up to 7EFF=32511 units of cargo.

Vehicle variable B9 (for a variational action 2) will be set to the new, climate-specific cargo type (column 3, type B in the cargo type list), or to FF when only checking whether the vehicle is refittable.

Unlike regular refitted capacities (including those from callback 36), the return value is not subject to the usual division of capacities for cargoes other than passengers on trains and planes, instead the capacity is used exactly as returned by the callback. See also the summary page about  vehicle refitting.

Articulated engine callback (16)

This allows building articulated engines or wagons, i.e. vehicles made from several individual vehicles.  If this callback is in use, additional vehicles will be added until the callback returns FF.

The callback return is interpreted as the ID of the vehicle to add.  If 80 is added to the ID, the vehicle will be reversed (as if Ctrl was held while bought).

Note that since the train is not yet built, you cannot use train variables in action 2. Instead, use variable 10 (extra callback info 1), which is set to 01 for the first articulated part, 02 for the second and so on.

If more than the first vehicle contains cargo, the callback must work in the buy menu as well. (This is only supported since 2.5 beta 8.)  This means that it will be called with cargo type FF in the action 3. Otherwise, the cargo amount shown in the buy menu will only be for the first part of the articulated vehicle.

In OpenTTD the cargo class of the first road vehicles is used to determine whether the vehicle can stop at bus or truck stops regardless of the capacity of the first vehicle. If the cargo class bit for passengers is set it can go to bus stops when the is not set it can go to truck stops. See also the page about  vehicle refitting.

House construction check (17)

This callback is used to determine if the given building type can be built on a position. It should return a nonzero value to allow building and zero to cancel it.

Since the building is not created yet, you can't use variables 40 and 41 (they return zero). You can use variable 42, 43, 44, 45 and all town variables, though. Since OpenTTD r19744 you can also access the random bits via RandomAction2 or variable 5F.

Property 0A and 13 are checked even if the callback returns a nonzero value; they can cancel building as well.

For multi-tile buildings, this callback is always called for the north tile type, but the position you can access through variables 40, 42 and 43 is not guaranteed to be the final position of the north tile. It is guaranteed, though, that if the building really gets built, one of its tiles will occupy that tile. So, for example, if you return zero for desert tiles, this neither means that your building won't occupy any desert tiles, nor that its north tile will be on a non-desert tile; it only means that at least one tile of the building will be on a non-desert tile. (e.g. it can still be built on the very edge of a desert) This restriction was removed in OpenTTD r13489, the callback is now called for the final position of the north tile.

AI construction/purchase selection (18)

This generic feature callback is called for various decisions when the AI is constructing a new route. For example, normally the AI has a hardcoded list of wagons for each cargo type, but with this callback you can make the selection depend on source and destination industries as well as service distance among other things.

Since the vehicle hasn't been bought yet, you cannot use the usual 40+x or 80+x vehicle variables, instead you have the following:

Variable Size Content
80 B cargo type (climate specific, column 3, type B in the cargo type list)
81 B cargo type (climate independent, column 1, type A in the cargo type list)
82 B default selection
83 B source industry type. For new industries the substitute type is returned starting with OpenTTD r20108.
84 B destination industry type. For new industries the substitute type is returned starting with OpenTTD r20108.
85 B distance between source and destination, in (dx+dy)/2
86 B AI construction event
87 B Construction number; for wagons: number of wagon; for stations 0=source station, 1=destination station
88 B Station size in form NL; N=number of platforms, L=length
40 D xxxxxxTT, TT=cargo slot from cargo translation table or same as var.81 if no table, available since r1167/2.5b9

The callback will be called for following construction events, stored in variable 86:

Group Feature Var.86 Type Description
Trains 00 00 Check Regular rail engine
01 Check Electric rail engine
02 Check Monorail engine
03 Check Maglev engine
08 Get Regular rail wagon
09 Get Electric rail wagon
0A Get Monorail wagon
0B Get Maglev wagon
0F Get Track type to build
Road Vehicles 01 00 Check Road vehicle
01 Get First road vehicle ID to try
02 Get Number of road vehicles to try
Ships 02 00 Check Ship
01 Get First ship ID to try
02 Get Number of ships to try
Aircraft 03 00 Check Aircraft
Stations 04 00 Get Station ID

Notes:

  • "Check" means to check if it should try to buy this vehicle (with ID in var.82). Return 00 to disallow purchase, or a non-zero value to allow it. If allowed, the computer will buy the highest-cost (or AI rank for train engines) vehicle it can find that is available and has high enough reliability.
  • "Get" means to find out which ID (etc.) to use. The default in var.82 is what it will use if the callback fails.
  • For train engines and aircraft, the AI always checks all available engines.
  • For road vehicles and ships, the AI has a built-in list of vehicles to try, you can use callback event 01 and 02 to change that list.
  • For trains, the track types (0=regular, 1=electric, 2=monorail, 3=maglev) are automatically mapped as appropriate depending on the electrifiedrailways/unifiedmaglev switches. For best results, assume that all four are available. The game will then use the correct one if it is not available.

This callback is "chained", i.e. if a result is not a callback result (high bit is not set), then the request is passed on to the previous generic callback handler, i.e. they are checked in reverse order. This makes it possible to leave certain decisions to the previous handler and allows some cooperation between several .grf files.

Cargo Subtype Display (19)

This callback allows you to display some text after the cargo name when refitting, and in the vehicle capacity display. This is useful to distinguish several subtypes of a certain cargo, e.g. goods could be cars, petroleum, sheet metal etc.

The return value must be the number of a D0xx string set by an action 4 in the same .grf file.  For example, if you set text ID D006 to some text, return 06 in this callback will make it displayed after the cargo name.

Normally, you would use the vehicle refit cycle/sub type variable F2 to distinguish the various subtypes.  During refitting, the callback is called with successively increased values of variable F2, until the callback returns FF.  All the returned variations are then displayed as refitting options, with all options that have the same cargo type and callback result (irrespective of refit cycle) grouped together in the same line.

Next animation frame (1A/26/141/153/158)

Called in every animation frame, this callback returns the number of the next frame to display. Additionally, it can return these special values:

Value Meaning
FF stop animation. The current frame stays on screen until the animation is restarted.
FE continue with next frame as usual. You can return this for stages where you don't want to do anything special.

From TTDPatch 2.5 beta 2, you can ask for random bits in variable 10. To enable this, set bit 3 of property 19 for houses, bit 0 of property 12 for industry tiles, or bit 2 of property 13 for stations.

Additionally all animation callbacks also allow to trigger sound effects as described in Callback 148.

Animation control (1B/25/140/152/159)

Called periodically, in a time interval specified in property 16 (houses) or when an animation trigger happens (industry tiles and stations). Returns the number of the frame the animation should jump to, or one of the following special values:

Value Meaning
FF stop animation in its current frame
FE start animation with its current frame
FD leave the animation in its current state (do nothing)

For multi-tile town buildings, property 19/bit 2 modifies this callback slightly, see details there.

For industry tiles and stations, the low byte of variable 18 contains the reason for the call, i.e. the bit number of the event from property 11 or property 18, accordingly.

Unlike callback 1B, callbacks 25, 140 and 159 are always used when defined, no bit in the action 0 property needs to be set to activate them.

Since TTDPatch 2.5 beta 2, this callback gets random bits in variable 10, to allow randomizing changes.

For callback 1B, the exact randomness depends on bit 2 of property 19 (synchronized callback 1B). If the callback is synchronized, the high 16 bits will be the same for all tiles and the low 16 bits will be different for each tile. Otherwise, all 32 bits will be independent for each tile.

For callback 25, the randomness depends on the type of the event. For triggers that happen for the whole industry (triggers 2, 3 and 4), the high 16 bits will be the same for all tiles, while the low 16 bits will be different. For other triggers, all 32 bits are independent.

For callback 140, the high 16 bits are the same for all tiles triggered, while the low 16 bits are different for each tile.

Additionally all animation callbacks also allow to trigger sound effects as described in Callback 148.

Construction stage changes (1C)

Called when the building changes its construction stage (during normal gameplay, that means exactly four times). Can return the same values as callback 1B. Variable 40 contains the new stage. You can return FF for stages that don't have animated graphics to save resources.

Can wagon be attached (1D)

This callback is called for the train engine (i.e. from the engine's action 3) when attaching a new vehicle to the current train and determines whether it may in fact be attached to the train. The callback is always used when defined, no bit in the action 0 property needs to be set to activate it.

You may use variational action 2s to check variables 40+x and 80+x. For var. action 2 type 81 (vehicle), they refer to variables of the wagon that is to be attached, not the engine it is being attached to, so you can check the wagon's properties like the cargo type to see whether it is appropriate for the given train engine.

Var. action 2 type 82 (engine) refers to the engine the wagon is being attached to, starting from version TTDPatch 2.0.1 alpha 46. This allows you to for example find out the length of the train it is being attached to. In earlier patch versions, it refers to the engine of the source consist (or the wagon if the wagon is not attached to anything else), which was not really helpful.

Return values:

Return Meaning
xx Disallow attaching and use the D0xx text ID as second line of an error message,
FD Disallow attaching with the standard message (incompatible rail types)
FE Allow attaching
FF Allow attaching if the rail types match (default)

It you return FE, you would allow attaching for example a monorail wagon to a regular rail vehicle, so if that's not what you intend, return FF.

Building colour (1E)

Called to decide what colour mapping the building should use. Should return the number of the colour mapping to be used, for example, 775 for blue->dark blue mapping.

This can be useful if you want something more complex than four random colours.

From TTDPatch 2.0.1 alpha 67, you can return a value of col2*16+col1 plus bit 14 set, where col1 and col2 are two company colours. For example, a return value of 73 C0 uses col1=3=yellow and col2=7=dark green. If no two-company-colour maps have been installed, the colours from prop. 17 are used instead.

Uses 15 return bits.

Cargo acceptance (1F)

Called to decide what the building tile can accept. Uses 15 return bits. The returned word should have the layout of Sgmp, where the letters mean the following:

Symbol Meaning
S 1 if the building should accept food/fizzy drinks instead of goods
g If S is 1, the food acceptance in 1/8 units
If S is 0, the goods acceptance in 1/8 units
m mail acceptance in 1/8 units
p passenger acceptance in 1/8 units

So, for example, giving the ID 8426h means "4/8 goods, 2/8 mail, 6/8 passenger", while giving the ID 9205 means "2/8 food, 5/8 passenger".

If property 1E and/or callback 2A is used, the meaning changes slightly. In this case, p means the acceptance of the first cargo type given, m means the same for the second cargo type, and g is the same for the third cargo type, while S must be zero.

Length of animation frame (20/27/142/154/15A)

Called to decide how long the current animation frame should last. The value of the delay should be given in the same way as for property 1B/10/17. Decreasing the return value speeds the animation up instantly. Increasing, on the other hand, doesn't slow it down instantly: the actual duration of the current frame will be somewhere between the old and the new delays. The new delay is applied correctly for later frames.

Note: This is one of the most time consuming callbacks as it is called for every animated tile every ≈30 milliseconds. For better performance try to avoid using it where reasonable, e.g. try to use only the properties and put multiple identical looking animation frames after each other.

Trigger building destruction (21)

Called periodically, in a time interval specified by property 16. If it returns a nonzero value, the building gets removed from the map as if the town decided to destroy it. You can use this for example to remove a historical building, since those cannot be normally removed by towns.

Industry availability (22)

Called when TTDPatch needs to know if a given industry type is available.

Return zero to make your type available, or any nonzero value to disable it. This callback is intended for limiting your type as a whole, so you can't access any industry-specific variables, just the global ones. A good example for the use of this callback is a nuclear power plant that isn't allowed to appear before 1970.

During this callback, variable 18 (extra callback info 2) can contain the following values:

Variable 18 Meaning
0 TTD is generating a map and needs to know if your type can appear.
1 TTD decided to build a new random industry during regular gameplay and needs to know if it can choose your type.
2 The user tries to build/prospect for your industry via the new industry window. TTD needs to know if the player is allowed to do this.

Additional text in purchase screen (23)

This callback is called when TTDPatch displays the vehicle stats of any vehicle in its purchase screen. The return value is the "xx" of a D0xx text ID to be shown below all other stats. The callback is always used when defined, no bit in the action 0 property needs to be set to activate it. As of r1908, text IDs D100..D3FF may also be returned.

How many lines are available depends on the type of vehicle and its other properties, for instance the presence or absence of a "refittable to" line or powered wagons etc. Lines are wrapped automatically, or may be broken explicitly using the newline character 0D.

If cargo FF (buy menu sprite) is handled explicitly for a vehicle, then the varaction 2 handling callback 23 must be in the buy menu varaction 2 chain.

Custom station layout (24)

After applying the values from station prop. 0E, this callback is used to further customize the tile layout.

It is called once for every tile that is being built, and returns the new tile type to build in its place or to leave the tile as defined by prop. 0E or TTD's default if the callback fails. The only possible return values are 00, 02, 04 and 06. Their meaning is the same as in prop. 0E.

Since the station hasn't yet been built, variables 40+x and 80+x are not available, instead variable 10 (extra callback info 1) contains the same information as variable 41 would contain. For the same reason, it uses the same cargo type in action 3 as the construction menu does (i.e., type FF if defined or else the default).

This callback is used always and does not need setting a bit in the action 0 property to activate it.

Industry location permissibility (28)

Called to decide if the industry can be built on a given spot. Since the industry isn't built yet, you can only use a small subset of the data: you can access the data of the nearest town via action 2/type 82 without any problems, but action 2/type 81 will access different variables than it would normally access:

Variable Size Meaning
40+x Not accessible
5F Since OpenTTD r19744: Random bits the industry starts with after construction. Accessible via RandomAction2 as well.
60+x Only var. 62 and vars 64..68 can be used
80 W Coordinates of the selected position
86 B Number of the selected layout, according to property 0A
87 B Ground type of the selected spot (see canal variable 81 for details)
88 B Town zone of the selected spot (see house variable 42 for details)
89 B Distance between the closest town and the selected position.
8A B Height of the lowest corner of the tile (between 00h and 80h, one land height unit equals 8 units)
8B W Distance to the closest water tile if property 1A bit 2 is clear (built on land); distance to the closest empty dry land tile if property 1A bit 2 is clear (built on water)
8D W Square of the Euclidean distance between the closest town and the selected position
8F D 32 random bits (since r1816 and r11985)

Unless explicitly noted, distances are Manhattan distance, not Euclidean distance, ie. |x-x0|+|y-y0| instead of sqrt((x-x0)^2+(y-y0)^2)

Variable 8B will always be below 80h if prop 1A bit 2 is clear. If bit 2 is set, 8B will be set to its max of 200h in the pathological case of an all-water map.

During this callback, variable 18 (extra callback info 2) contains the following values for OpenTTD r20942 and later:

Variable 18 Meaning
0 TTD is generating a map.
1 TTD decided to build a new random industry during regular gameplay.
2 The user tries to build your industry via the new industry window.
3 The user tries to prospect for your industry via the new industry window.

This callback must return a 15-bit value, which is interpreted as follows:

Value Meaning
0000-03ff Industry can't be built, display the misc. GRF text Dxxx as error message
0400 Industry can be built
0401 Industry can't be built, display the default "site unsuitable" error message.
0402 Industry can't be built, display the "...can only be built in rainforest areas" error message.
0403 Industry can't be built, display the "...can only be built in desert areas" error message.

Since TTDPatch r1755, you can use the text reference stack for your error messages, similarly to callback 3A. The only difference is that only 4 registers are copied instead of 6 because error messages support 20 bytes of reference stack only, and two of those bytes may be used by TTD.

Random production change (29)

Called when TTD chooses the industry for a random production change. Variable 18 contains 32 random bits to help randomizing the decision. The callback must return one of the following results:

Value Meaning Min. Version
00 Do nothing
01 Halve industry production. If production goes below the quarter of the default, the industry is closed instead, as if you returned 03.
02 Double industry production if it hasn't reached eight times of the original yet.
03 The industry announces imminent closure, and is physically removed from the map next month.
04 Do the standard random production change as if this industry was a primary one.
05 Divide production by 4
06 Divide production by 8
07 Divide production by 16
08 Divide production by 32
09 Multiply production by 4
0A Multiply production by 8
0B Multiply production by 16
0C Multiply production by 32
0D Decrement production by 1 OpenTTD r11532, TTDPatch 2.6 r2046
0E Increment production by 1 OpenTTD r11532, TTDPatch 2.6 r2046
0F Set production as returned in bits 16..23 of register 0x100 (clamped to 4..128) OpenTTD r14561, TTDPatch 2.6 r2068

Since TTDPatch 2.5 beta 1, you can set bit 7 of this value to suppress the news message announcing the production change. Be careful with this, especially for closedown messages; most players wouldn't like those being suppressed.

For return values 05..0C, the double/halve news messages are displayed. You should probably replace the defaults with some text that doesn't explicitly say "double" or "halve", or use the message override feature (see below). If a divide operation brings the production below the quarter of the default, the industry is closed down instead. Multiply operations that would bring the production above 8 times of the original will only increase it to that value.

Since r1306, you can override the default news messages that appear after production changes. To do this, you must set bit 8 of the returned result, and put the textID into the low word of GRF register 100h (the high word of the register is ignored). The textID can be of a default TTD text or a DCxx text; it cannot be a D0xx text. If the given action generates a message, it will be the one you specified. It may, however, not generate messages at all; for example, operation 04 may decide not to change the production, and then your message won't be shown. There is one exception: operation 00 would never generate a message, but it still will when bit 8 is set. This is useful in conjunction with callback 35, to tell the player about things that don't change the production multiplier, but are still important enough to require a news message.

Using return values 0Dh, 0Eh and 0Fh you can adjust production rates more smoothly. The production rate is a value between 04h and 80h (initial value 10h). Returning 0Dh when the production is at 4 will close the industry. But returning 0Fh will never close the industry, instead the value is clamped to the allowed range. Note that OpenTTD before r15103 did not properly updated production rates provided by properties 12 and 13.

Get accepted cargo types (2A/2C)

Called when TTD needs to know what cargoes a house/industry tile can accept. The bits of the result must be filled in the following way:

Bit range Meaning
0..4 First cargo type
5..9 Second cargo type
10..14 Third cargo type

If the callback fails, the according values from property 1E is used instead for houses, and properties 0A..0C for industry tiles. This callback is most useful in combination with callback 1F/2B, so you can fully control the acceptance of your house/industry, even allowing dynamic changes

From GRF version 7 and above, the interpretation of the returned value changes: instead of climate-dependent cargo slot numbers, you have to return climate-independent cargo IDs. If your GRF has a cargo translation table, then this ID is the index in that table; otherwise, it's the cargo bit. Acceptance of cargoes not currently present will automatically be disabled.

Decide cargo acceptance (2B)

Called to get the amount of acceptance for the industry tile. The cargo types are defined by properties 0A..0C, or callback 2C if enabled. The callback must return a 15-bit value in the following format:

Bit range Meaning
0..3 Acceptance for the first cargo (0..8)
4..7 Acceptance for the second cargo (0..8)
8..11 Acceptance for the third cargo (0..8)

If the callback fails, properties 0A..0C are used instead.

Select colour mapping for vehicle (2D)

Called while drawing the vehicle. Should return the number of the colour mapping to be used on the vehicle sprite, for example, 775 for blue->dark blue mapping. If the callback fails, the company colour of the owner is used. Since mapping 775 doesn't change any colours, you can return it to disable the company colours and leave all magic blue in your sprite alone.

If bit 14 is set, the company colour will be added to the resulting sprite number. This means the given sprite and the 15 following sprites must be colour maps, one for each of the 16 possible player colours. If the vehicle also has misc.flags bit 1 set (two company colours), the sprite and the 255 following sprites must be appropriate colour maps. Alternatively, use a return value of 00 C0 to use the default two-colour maps.

Uses 15 return bits.

The return value is cached to speed up sprite processing, and only updated via callback 32 bit 1 (or when loading/starting a game or rearranging the consist).

Custom cargo production (2E)

This callback can be used to customize cargo production of house tiles. It is called every 256 ticks when the tile can produce cargo. Because a tile can produce many types of cargo, this callback is called in a loop until it returns 20FFh (the loop count is limited to 256 to avoid endless loops). If the returned value is not 20FFh, the high byte must be a cargo type and the low byte must be the amount to be distributed. You can return a cargo type more than once if needed, so you can distribute more than 255 units from it. During the callback, the lowest byte of variable 10 contains the number of iterations happened so far and variable 18 contains a random value to help randomizing the production. (The old code randomizes production to make it look more natural, you can do the same via a variational action 2 with nvar=0)

This is how the original passenger generation is done: In each periodic processing (i.e. every 256 ticks), a random value 0<=X<=255 is generated for each house tile. If X isn't smaller than the population of the tile, no passengers are generated. Otherwise, X/8+1 passengers are generated (rounded down). If there is a recession going on, the number of generated passengers is halved, but this division gets rounded up instead of down. Mail generation happens in a similar manner, but with a new random value, and checking against the mail generation multiplier instead of the population.

Uses 15 return bits

From GRF version 7 and above, the interpretation of the high byte in the returned value changes: instead of a climate-dependent cargo slot number, you have to return a climate-independent cargo ID. If your GRF has a cargo translation table, then this ID is the index in that table; otherwise, it's the cargo bit. Trying to produce a cargo not currently present is not an error, but will be ignored.

Custom shape check (2F)

This callback is called when TTD checks if a given tile is suitable for the industry tile. Since the tile isn't built yet, you can use variables 41, 42, 43, and 60 only, and you can't access any industry variables, either. Since OpenTTD r19744 however, you can access the random bits of the industry (it would get after construction) via industry variable 5F resp. RandomAction2 type 83. Var. 60 is the most useful here, since you can check the slope of the tile, or even the nearby tiles. This callback is the only way to allow your tile to be built on steep slopes. The callback should return zero if the tile isn't suitable, or any other value if it is suitable.

Since TTDPatch 2.6 r1728, the lowest byte of variable 18 contains the layout number selected for the industry. The other bits of variable 18 remain undefined for now.

Since OpenTTD r20942, the second lowest byte of variable 18 contains the trigger event of the industry construction. The values are the same as the lowest byte of variable 18 of callback 28.

Important: The meaning of the returned value will change in GRF version 7; it will work the same way as callback 28. Also, since TTDPatch r1755, you can use the text reference stack for your error messages, similarly to callback 3A. The only difference is that only 4 registers are copied instead of 6; see callback 28 for details.

PLEASE NOTE: When this callback is called, TTD is just checking, and hasn't placed any industry tiles yet. Therefore, bit 8 (tile belongs to the same industry as current) of variable 60 will always be clear, even for the current tile.

Decide drawing default foundations (30/14E/150)

This callback is called when TTD starts drawing the industry/house/airport tile on sloped land. It should return zero to disable the default slope graphics and any other value to enable them.

If you chose to disable the foundation, you can draw your own by specifying

  • no ground sprite, i.e. a sprite number 00 00 00 00,
  • then a foundation sprite with bit 30 set to make foundations visible even in transparent mode, and the normal TTD foundation height of 7px,
  • then the normal graphics with bounding boxes adjusted with regards to the foundation sprite:
100 * 4 01 09 02 01
// foundation
101 C:\ttdlx\newgrf\sprites\slope.pcx 220 130 09 40 63 -30 -9
// building
102 C:\ttdlx\newgrf\sprites\slope.pcx 80 130 09 31 64 -31 0

103 * 28 02 09 00 02
00 00 00 00 // no groundsprite
00 00 00 C0 00 00 00 10 10 07 // foundation
01 00 00 80 00 00 08 10 10 10 // building

Please note that TTD doesn't have suitable foundation graphics for steep slopes. In any way, variable 60 comes in handy when selecting the correct foundation to draw.

Start/stop check (31)

This callback is called whenever a player (or the AI) tries to start or stop a vehicle. This is mainly useful for preventing vehicles from leaving the depot unless a given condition is met. To check whether a vehicle is being started or stopped, check bit 1 of variable B2. If set, the vehicle is currently stopped and if clear, the vehicle is moving (or at least, not stopped manually).

The return value is a D0xx text to use as second line of an error message, or FF to indicate that the start/stop action should succeed. The callback is always used when defined, no bit in the action 0 property needs to be set to activate it.

32-day callback (32)

This callback is called every 32 game days for each vehicle, although not for all vehicles on the same day. The callback is always used when defined, no bit in the action 0 property needs to be set to activate it.

The return value is a bit mask of the following bits:

Bit Value Meaning
0 1 Trigger vehicle trigger 10
1 2 Update colour map via callback 2D

If no bits are set, nothing happens.

Sound effect callback (33)

This callback is called for all vehicles and as generic callback for bridges, for various events that support playing sound effects. The type of event is stored in variable 10.

The 15-bit return value is the sound effect number. Values from 0 to 72 (dec) are TTD's built-in sound effects, values beyond that refer to the sounds from Action 11.

If the callback returns a failure code (not a callback result), the default TTD sound effect will be played. If the callback returns a sound number that is neither a TTD sound, nor a sound from action 11, nothing will be played.

Var. 10 Event
1 Start sound, called when leaving a station or depot, take-off sound for planes
2 Tunnel sound, called when vehicle enters tunnel
3 Breakdown sound, called when vehicle breaks down (not for planes)
4 Running sound, called once per engine tick, but no more than once per vehicle motion
5 Touchdown sound, for planes only (obviously)
6 Train visual effect generation (steam plume, diesel smoke, electric spark)
7 Running sound, called every 16 engine ticks if in motion
8 Stopped sound, called every 16 engine ticks if stopped (e.g. at signal/in station)
9 Load/unload sound, called when consist loads or unloads cargo
10 Bridge sound, called as generic feature 06 callback every time a consist moves on a bridge. Variables 40+x, 60+x and 80+x refer to the vehicle and bits 0..7 of variable 18 hold the bridge type

For the running sounds, it is advisable to check the motion counter and to only return a successful sound effect number every so many vehicle motion ticks. This way, the sounds will be played more frequently the faster the train is. Alternatively, you can check the tick counter variable and play the sound effect every so many engine ticks, so that it is played at a constant rate, or, of course, switch between both modes depending on vehicle speed.

Note that if the planespeed switch is active, planes move the given number of times per engine tick. This means that their motion counter increases faster than for other vehicles, and thus to get reliable sound effects you need to divide the motion counter by the planespeed setting (readable via action D) before checking the value.

Autoreplace vehicle selection (34)

This callback is called whenever an old vehicle needs replacing. It returns the vehicle IDs to upgrade the current vehicle to. The vehicle variables are available as usual to decide which IDs would be appropriate to upgrade to.

The callback is repeatedly called, with the iteration number stored in variable 10.  The .grf file should return all possible IDs one by one, with the best ones listed first.  The patch will use the first vehicle from the list that is available to the player and has the required minimum reliability as set by the autoreplace switch, and abort the callback sequence at this point.

The callback sequence is also aborted when the returned ID is equal to the current vehicle ID. This is to prevent downgrading, and so you must take care to always return the ID of the vehicle for which the callback is called at the appropriate place in the sequence.

If the callback fails, i.e. if no suitable ID could be found by any of the callbacks in the generic chain, the vehicle is not upgraded, and is simply renewed instead.  If an ID is available but the player lacks the cash to upgrade, the patch waits for the cash to become available instead of either picking a worse engine or renewing the vehicle.

For trains, each engine head will be replaced by one vehicle of the new type.  As such, it is advisable for only return "compatible" IDs for trains that require a particular construction or arrangement of engine heads.

The callback is always used when defined, no bit in the action 0 property needs to be set to activate it.

Monthly random production change (35)

Works exactly the same way as callback 29, except that it's called every month, allowing more frequent production changes.

Change vehicle properties (36)

This common callback allows modification of certain properties of a vehicle for which there exists no specific callback (like CBs 10, 11, 12). The low byte of variable 10 holds the property number from Action 0.

The following properties are supported:

Feature Property Minimum version OpenTTD rev
Trains (00) 07 (Load amount) - - Changeable via callback 12
09 (Speed) 2.5 beta 6 r9671
0B (Power) 2.5 beta 6 r9671
0D (Running cost factor) 2.6 rev 1420 r9671
14 (Cargo capacity) 2.6 rev 1966 r9828 See also callback 15
16 (Weight) 2.6 rev 1887 r9780
17 (Cost factor) r9806
1F (Tractive effort) 2.5 beta 6 r9671
21 (Short wagons) - - Changeable via callback 11
22 (Visual effect & powered wagons) - - Changeable via callback 10
25 (User data) 2.5 beta 6 r11431
Road Vehicles (01) 07 (Load amount) - - Changeable via callback 12
09 (Running cost factor) r18011
0F (Cargo capacity) r9828 See also callback 15
11 (Cost factor) r9806
13 (Power) r21058
14 (Weight) r21058
15 (Speed) r21100
18 (Tractive effort) r21058
Ships (02) 07 (Load amount) - - Changeable via callback 12
0A (Cost factor) TTDPatch 2.6 rev 1990 r9806
0B (Speed) 2.5 beta 6 r9671
0D (Cargo capacity) TTDPatch 2.6 rev 1990 r9828 See also callback 15
0F (Running cost factor) TTDPatch 2.6 rev 1510 r9808
Planes (03) 07 (Load amount) - - Changeable via callback 12
0B (Cost factor) r9806
0C (Speed) 2.5 beta 6 r9671
0E (Running cost factor) 2.6 r1507 r9678
0F (Passenger capacity) r19218 See also callback 15
11 (Mail capacity) r19218

Most properties will only change when the vehicle is bought, serviced (enters a depot), visits a station or on loading of a saved game. Other ones such as TE are called every time a TE calculation is run.

If the callback fails, the corresponding value from the action 0 property will be used. The callback is always used when defined, no bit in the action 0 property needs to be set to activate it.

Before r1758 (both 2.5 and TTDPatch 2.6), callback 36 was sometimes called with the 40+x and 80+x variables unavailable when they should have been available, or with not all 80+x variables properly initialized, causing some 40+x variables to be unsafe.

About the capacity properties see also the summary page about  vehicle refitting.

Cargo sub-type display for industries (37)

This callback allows you to display some text after the cargo name in the industry fund window and in industry windows. Just like callback 19, the return value must be the number of a D0xx string set by an action 4 in the same .grf file. Returning FFh causes no text to be displayed.

During the callback, the lowest byte of var. 18 can have the following values:

Number Meaning
00 Return subtext for first accepted cargo type
01 Return subtext for second accepted cargo type
02 Return subtext for third accepted cargo type
03 Return subtext for first produced cargo type
04 Return subtext for second produced cargo type

Bits 8..15 of var. 18 can have the following values:

Number Meaning
00 The text is to be displayed in the industry fund window. The industry isn't built yet, so you can't access the industry variables
01 The text is to be displayed in the window of the industry. You can use the industry variables here.
02 The text is to be displayed in the industry directory window. You can use the industry variables here.
other values Reserved for future use

Other bits of var. 18 are reserved for future use.

Since OpenTTD r17802, the contents of registers 100h..105h are copied onto the text reference stack.

Show additional text in fund/building window (38/15C)

This callback allows you to display extra information in the industry fund and object building windows. The return value should be the number of a D0xx text to be displayed. The text must begin with a colouring special character and should not be longer than three lines (automatic line breaks are provided, but you can use char 0D for a manual line break). Since the industry isn't built yet, you can't access any industry variables during this callback. Same holds for objects.

Since OpenTTD r20086 and TTDPatch r2354, the contents of registers 100h..105h are copied onto the text reference stack.

Custom profit calculation for cargoes (39)

This callback is called every time cargo is delivered to a station, to get how much income the player should get. The low word of var. 18 contains the distance of the transfer, byte 3 contains the amount of cargo moved and the highest byte contains the time spent en-route (a unit of time is +185 ticks, or ca. 2.5 days). The result should be a signed multiplier that gets multiplied by the amount of cargo moved and the price factor, then gets divided by 8192. Since the highest bit must always be set for a callback result, TTDPatch checks for the second highest bit (bit 14) for the sign. Returning a negative value means that the player has to pay for the transfer instead of getting money from it. For example, the maximum returnable value of 16383 means that the player gets twice the price factor for every unit.

Show additional text in industry window (3A)

This callback allows you to display extra information in the industry window about the state of your industry. The return value should be the number of a D0xx text to be displayed. The text must begin with a colouring special character and should not be longer than one line. For example, you can use this callback to display the current production limit of a secondary industry.

Note that since r11987, OpenTTD allows resizing the window when this callback is enabled.  It allows to specify a text containing more than one line.

Since TTDPatch 2.6 r1370, the contents of registers 100h..105h are copied onto the text reference stack. This allows you to display dynamically calculated values in the text by using the according StringCodes. Please note, though, that the text handler will see it as an array of bytes, not as an array of DWORDs, so you will have to pack two words into a register when you use codes that read words from the stack. In the case of \7D (which gets a byte), you may have to pack more into a register, but it's probably easier to use \7C instead. Please also note that you can use \80 to display textIDs calculated on the fly, but DCxx textIDs won't work correctly. When you need to choose from your own texts dynamically, you must use D0xx IDs, and add 400h to them. (That is, use D400 to refer to D000, D401 for D001 etc.)

Control special industry effects (3B)

This callback allows you to control some aspects of the special effects enabled in property 1A. The lowest byte of variable 18 always contains the number of the special effect, which equals to the bit number being set in property 1A. Currently only effect 0 (plant fields periodically) and effect 1 (cut nearby trees periodically) are supported.

  • For effect 0 you should return zero to avoid planting fields and any other value to plant a field. The callback is called every 256 ticks for a given industry. Variable 10 contains 32 random bits that can be used to randomize the behaviour. Industry variable AAh (word) can be used to make the plantings rarer, but please note that the low byte is always zero at this point. The default behaviour is giving 1/8 chance to plant a new field every 256 ticks.
  • For effect 1 you should return zero to avoid cutting a tree and any other value to try cutting one. The callback is called every 256 ticks for a given industry. You don't get random values this case, but you can still use variable AAh; the low byte is always zero here as well. The default behaviour is trying to cut a tree every 512 ticks.

Disable autosloping (3C/14F/15D)

With this callback, you can prevent the autoslope feature from altering the ground below a house/industry/object tile. To allow altering the ground, return zero. Returning anything other than zero will disallow land modifications.

Opt out of accepting cargo (3D)

With this callback, the industry can refuse accepting a cargo even if it's one of the input cargo types. If there's another industry nearby that accepts this cargo, that one will get it.

The lowest byte of var. 18 contains the ID of the cargo delivered. If your GRF has a cargo translation table installed, you will get the index from that table; otherwise, you will get the cargo bit associated with the cargo type. You must return zero if you don't want to accept the cargo, or 1 to accept it. Other return values are reserved for future use.

This callback should be used in conjunction with callback 2B, since the acceptance of the tiles and the acceptance of the industry itself should always agree. If you disable accepting a cargo via callback 3D, but forget to remove the acceptance from the tiles, the station will keep accepting the cargo and the player will keep getting the money, but the industry won't receive the cargo. On the other hand, if you remove acceptance from the tiles, but forget using callback 3D, your industry may still get the cargo. (For example, there may be another industry nearby whose tiles accept the cargo. This makes the station accept the cargo, and send it to the nearest industry, which happens to be yours, even though its tiles don't accept the cargo.)

Protect building conditionally (143)

This callback is called when someone tries to remove the building from the map. You can use this callback to prevent the town or AI players from removing the building if certain conditions are met. You can return 0 to allow the destruction, or 1 to disallow it, except for human players, who can always remove any building.

If you always return 1 from this callback, you achieve the same effect as turning on bit 1 of property 19. When this callback is enabled, bit 1 of property 19 is ignored. If the callback fails, the destruction is allowed.

For multi-tile buildings, the callback will be called for the type of the tile the player wants to destroy. Therefore, to get consistent behaviour, you must enable this callback for every tile and respond it the same way no matter which tile it is called for.

Since TTDPatch 2.6 r1705, you can use this callback to prevent building "town" industries (banks, water towers, etc.) over your house. The lowest byte of variable 10 is zero for "normal" demolition and one when TTD wants to remove the house for the sake of a new industry. Other values of variable 10 are reserved for future use.

Ambient sound effects (144)

This callback is a generic callback for feature 0C (new sounds) used for playing ambient sound effects.

The 15-bit return value is the sound effect number. Values from 0 to 72 (dec) are TTD's built-in sound effects, values beyond that refer to the sounds from Action 11.

To decide whether to play a sound, and what sound to play, Var.Action 2 variable 10 holds the following information: THRRxxxt

Field Meaning
T Tile class, 0=bare land, 4=trees, 6=water
H Height of north corner of tile
RR 8 random bits
xxx Reserved
t Terrain type;  0 normal (grass), 1 desert, 2 rainforest, 4 on or above snowline

This callback must be enabled by bit 4 in action D var 9E.

Custom station rating calculation (145)

This callback allows you to modify part of the station cargo rating calculation for your cargo. To understand how to use it, you must first understand how the default rating calculation works:

Internally, the station rating is stored in a byte, 0 meaning 0% and 255 meaning 100%. The rating is calculated as the sum of the following components:

Time since the cargo was last picked up
Time units (days) Score (%, rounded)
>21 (>52.5 days) 0 (0%)
13..21 (32.5 days..52.5 days) 25 (10%)
7..12 (17.5 days..32.5 days) 50 (20%)
4..6 (10 days..17.5 days) 95 (37%)
0..3 (0 days..10 days) 130 (51%)

The time unit used equals 185 engine ticks, or 2.5 TTD days. For ships, the time units are divided by 4 before calculating this component, so ships have four times more time before the ratings start dropping.

Amount of cargo waiting
Amount of cargo Score (%, rounded)
>1500 -90 (-35%)
1001..1500 -35 (-14%)
601..1000 0 (0%)
301..600 10 (4%)
101..300 30 (12%)
0..100 40 (16%)
Max. speed of the last vehicle picking up the cargo

This calculation is somewhat complicated. The maximum speed of the vehicle is expressed in "speed units". For trains and road vehicles, the speed 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. If the vehicle is slower than 85 units, no points are awarded; otherwise, you get (speed_units-85)/4 points. Therefore, the maximum you can get is 42 points, or 16%.

Age of the last carrier picking up the cargo

The original calculation goes like this:

Age of vehicle (years) Score (%, rounded)
2 10 (4%)
1 20 (8%)
0 33 (13%)

If the newagerating switch is turned on, the calculation changes. You get 33 points for vehicles younger than 5 years, and get 0 points for vehicles older than 21 years. Between these two ages, score drops slowly, by 2 points per year.

Bonus for AI companies
AI intelligence setting Score (%, rounded)
Low 0 (0%)
Medium 31 (12%)
High 63 (25%)

That is, AI players cheat to get good ratings for their brain-dead routes.

Bonus for statue in nearest town

If your company has erected a statue in the nearest town, you get 26 points (10%) bonus to all cargo ratings.

Clamping

If a human player does everything perfectly, the maximum rating she can get is 271 points, while the worst possible transport service gets -90 points; for "highly intelligent" AI players, the corresponding values are 334 and -27, respectively. The resulting value gets clamped to the 0..255 range. TTD makes sure the ratings change slowly, but steadily: every 2.5 days, the actual rating moves towards the value calculated above, by no more than 2 points. For example, you 'd need at least 320 days to go from 0% to 100%, even if your service is perfect. When a cargo type first appears at a station, its rating is set to 175 points (69%), so it takes some time until it gets adjusted to the actual parameters of the service.

Callback effect

The callback allows you to replace the first three components (days since last pickup, amount waiting and max. speed of last vehicle) in the calculation above. If your callback succeeds, the first three components are skipped and the returned value is used instead their results. Bit 14 is considered the sign bit, so you can return negative numbers (and need not to worry about calculated callback results yielding a negative result, as long as you stay in the range -16384..16383). During the callback, variable 18 has the value ssaaaatt, where

  • tt is the time since the cargo was last picked up, in the time units described above (1 unit = 2.5 days independent of vehicle type)
  • aaaa is the amount of cargo waiting
  • ss is the speed of the last vehicle picking the cargo up, in the speed units described above (if no vehicle entered the station yet, the value is FFh)

The lowest byte of variable 10 contains one of the following values:

value meaning
10h the last vehicle entering the station was a train
11h the last vehicle entering the station was a road vehicle
12h the last vehicle entering the station was a ship
13h the last vehicle entering the station was an aircraft
00h no vehicle entered the station yet, or the last one entering was sold

Please note that there's only one "last vehicle" field per station, so the vehicle this refers to may not have picked up any of your cargo. The original TTD calculation doesn't care about this and just uses the field to get the vehicle type used in the first component.

Currently, you can only use variables 10 and 18 for your decision, since neither vehicle nor station variables are available for a cargo callback. As soon as the architecture of TTDPatch allows this, the callback will be given access to the station and the last vehicle that entered.

New signals sprite drawing callback (146)

This is a generic callback, and thus a generic action 3 must be used. It must be processed by a variational action 2 feature 0E, as indicated in the following link: VarAction2NewSignals.

Add sprite offset callback (147)

Add an offset to the default sprite number to be drawn.

Feature Accessible Variables
Canals 80+x variables are accessible by Canals. See VarAction2Canals

The default number is accessible in variable 10 (extra callback info 1) to decide if the sprite number needs an offset.

Watched cargo accepted (148)

Called when a cargo type specified in property 20 is accepted by a house tile, or to be more specific, in a station that has the house tile in its acceptance area. It will be called for each tile of a multi-tile building whenever a tile with property 20 accepts cargo. This means if more than one tile has cargoes specified in property 20, the callback can be called multiple times on the same tile in the same tick. The low word of variable 18 contains the offset of the trigger tile relative to the current tile; the low byte contains the X offset, the high byte the Y offset. (0 means it's the same tile, negative coordinates mean it's northward, positive southward.) With this, you can tell apart the callings within the same tick. The high word of variable 18 contains random bits, the bits are the same for each tile of multi-tile buildings.

The return values can be the same as for callback 1B. Like all animation callbacks, if the high byte of the result is nonzero, it will be interpreted as a sound effect number, and the corresponding sound effect will be played at the tile.

Due to implementation details, up to 250 game ticks can pass between the actual acceptance and triggering this callback.

This callback isn't available if the station2 structure isn't present - see the property 20 entry for more information.

Land slope check (149/157)

This callback is called for each tile where the new station part will be built. It can return zero to accept the current tile or one to make the station building fail with the "Land sloped in wrong direction" error message. Other return values are reserved for future use, don't use them for now.

Since the station isn't built yet, no 8x variables can be accessed. Only variables 43 and 67 will work from the 4x and 6x variables. You get the following information, though:

  • variable 18:
bit numbers Meaning
0..7 offset of current tile on the platform, 0 is the northmost tile
8..15 bits 8..15: current platform number, 0 is the northmost platform
16..23 total length of station being built
24..31 total number of platforms being built
  • variable 10:
bit numbers Meaning
4..7 Slope info of the current tile:
  • bit 7 - N corner is elevated
  • bit 6 - E corner is elevated
  • bit 5 - S corner is elevated
  • bit 4 - W corner is elevated
0..3 the same information, but "mirrored" (bit 0 and 2 swapped) if the station is built in the NW-SE orientation. This allows you to check slopes without checking the orientation explicitly.
other bits reserved for future use

The callback is called only after the normal checks TTD does for slopes, so it's not possible

to allow a slope that isn't allowed by default; you can only narrow the set of allowed slopes. If the callback fails, the tile will be accepted. It is, however, called for flat tiles, so you can force your station to sloped land. You can't access the station info even if the platform is added to an existing rail station or is overbuilding station tiles. That's because TTD will decide this later in the code, after the slope is already accepted.

This is called if available just before object construction, it does not require that any flags be set in the action0.

Please note that for Objects only the low byte of variable 18 is valid (Offset from north tile (origin), stored as YX) and that variable 10 does not have the reversed version, and bits 0 - 3 contain the actual raised corners (same order as bits 4 - 7).

Decide industry colour (14A)

This callback is called when the industry is being constructed, to override the selected colour of the industry (variable A8). This colour will be used for tile sprites that request recolouring, but don't supply a recolour sprite number. The following industry variables aren't yet filled and contain random junk: 86..87, 93, 9E..A1, A9. (You probably wouldn't need to read anything but 86..87 anyway, since these fields contain information about the past, and the industry doesn't yet have a past.) Industry tiles aren't placed yet, either.

Variables A7 and A8 are filled, however, and provide useful information. Variable A7 contains the number of the funder company, or 10h if the industry wasn't funded. Variable A8 contains the number of the colour scheme randomly picked by TTD, it's between 0 and 15. If you don't want to change the colour picked by default, you can either make the callback fail or just return variable A8 unchanged.

Only the lowest four bits of the returned value are used, the other bits are reserved for future use. Those four bits are copied into variable A8 after the callback returns. You can either use industry variable 45 to get the company colour of the funder (if there's any), use a random action2 to select a random colour scheme from a given list, or of course decide on global variables like position or game year.

Decide input and output cargo types (14B,14C)

These callbacks are called when the industry is built, and allow customizing the input and output cargo types dynamically. Both callbacks are called repeatedly, with the lowest byte of variable 10 starting from zero and increasing after every call; you should return a cargo type each time, or FFh to terminate the list. (A failed callback terminates the list, too.) The same limitations apply as for callback 14A: industry tiles aren't yet placed, and some industry variables contain junk. You can use random action2s, however. The interpretation of the returned value depends on two factors: the current GRF version number and the presence of a cargo translation table:

GRF version Has cargo translation table Interpretation
6 or below Climate-dependent cargo slot number
7 or above No Cargo bit
7 or above Yes Index in the translation table

Although currently callback 14B is called no more than three times, and callback 14C no more than twice, this may change between versions/implementations, to allow more input/output types. To be safe, you should return FFh as the last element even when you use all three input types or both output types.

House customized building name (14D)

This callback is activated from the Tile Description Query tool, when enquiring a house.  Variable 10 will be set to 1 if the house is complete, otherwise it will be 0.  The return value is the "xx" of a D0xx text ID.  If the callback fails, the Query tool will use the house name set in property 12 (Building name ID).

Since this callback is not performed frequently, you do not need to specify a mask.  It will always be performed, and the name will only change when successful.

Available for OpenTTD since r15172, and for TTDPatch since TTDPatch 2.6r2249

Extra information about airport layout in the build gui (155)

This callback allows you to display some extra text in the build airport gui. It should return a D0xx StringID. This callback is always called when available, you do not need to set a bit in any action0 property to enable it. Available for OpenTTD since r20272

Airport layout name (156)

This callback allows you to show a name for an airport layout. It should return a D0xx StringID. This callback is always called when available, you do not need to set a bit in any action0 property to enable it. Available for OpenTTD since r20273.

Decide object colour (15B)

This callback allows you to set/modify the colour of an object upon construction. Variable 10 contains the current company colour or a random colour for when there is no company, i.e. in the scenario editor. If the object wants a 2CC colour mapping two nibbles, i.e. two colours, are passed in variable 10, otherwise one nibble (colour).