Callbacks
List of available callbacks
Callbacks
{maketoc}
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 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|Trains|Powered wagons and visual effect
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 fund window
15D|Objects|Disable autosloping||
<nowiki>*</nowiki> Generic callbacks are called for the feature, not any specific vehicle ID. Read the Action 3 entry on how to define these.
Powered wagon callback (10)
This callback is used to determine whether a wagon is powered (adding power and weight to the train) and what visual effect to use for the wagon. It only applies if the wagon would by default be powered (i.e. property 1B is set), and is only called when loading a game, when the train reverses, or when rearranging the train in a depot. If the callback fails for any reason (e.g. not defined, action 2 does not return callback result etc.), the value of property 22 is used instead. For possible return values, refer to train property 22.
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 TTDP and OTTD before r14672.
Since OTTD 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 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 OTTD 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.
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.
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.
If any of the above animation callbacks return a nonzero value in the high byte, it will be interpreted as a sound effect number, and the corresponding sound effect will be played on the house tile.
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 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 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.
This callback is used always and does not need setting a bit in the action 0 property to activate it.
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 -+<nowiki><nowiki>sqrtAction 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)| 2.6 rev 1990 |r9806|
|0B (Speed)|2.5 beta 6|r9671|
|0D (Cargo capacity)| 2.6 rev 1990 |r9828|See also callback 15
|0F (Running cost factor)| 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 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 industry fund window (38/15C)
This callback allows you to display extra information in the industry fund window about 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 three lines (automatic line breaks are provided, but you can use char 0D for a manual line break). The industry isn't built yet, so you can't access any industry variables during this callback.
Since OpenTTD r20086, the contents of registers 100h..105h are copied onto the text reference stack.
{cookie}
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 for industry tiles (3C/14F/15D)
With this callback, you can prevent the autoslope feature from altering the ground below the industry/house tiles. 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.
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.
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.
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:~pp~
bit 7 - N corner is elevated
bit 6 - E corner is elevated
bit 5 - S corner is elevated
bit 4 - W corner is elevated~/pp~
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 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).