Industry tiles work similarly to town buildings, except that they are not stand-alone. This means an industry tile is always part of an industry.
Defining industry tiles follows the same schema as houses do: to start using an ID, you first need to define it by setting property function substitutetype() for it. If you try to reference an ID (either by a property function or by defineindustrytile()) that isn't defined, your request is ignored, but not reported as an error, either. This means that if you want to conditionally define an ID, all you need to do is skipping property function substitutetype(), and everything else gets skipped automatically.
Industry tile IDs are unique within each grf file. In total, TTDPatch can have up to 256 new industry tile IDs (i.e. old tile types don't count). OpenTTD can have 512 IDs for all active grf files, but that includes non-overridden original tiles. The per-GRF ID is specified as a byte, which means no GRF can define more than 256 tile IDs, i.e. you should use your industry tile IDs sparingly.
Performance function position() for industry tiles can help you limiting tile consumption per industry. Try to avoid using tile 255 (FFh), so it can be turned into an extended byte in the distant future without breaking your NewGRF.
All industry tile properties are defined inside the defineindustrytile() function. Depending on the type of industry tile, different properties would have to be used. See the example. All properties are given by the property functions below.
| Property function | Description |
| anim_info(<Byte> [,LOOP]) | Animation information |
| anim_speed(<Byte>) | Animation speed |
| anim_triggers(<List::trigger>) | Animation triggers |
| callbacks(<List::Callback>) | List of callbacks used |
| cargoamounts([0 .. 8]*3) | Accepted cargo amounts |
| cargotypes(<CargoType>*3) | Accepted cargo types |
| climate(<List::Climate>) | Climate availability |
| flags(<List>) | Industry tile flags |
| overridetype(<Industrytile-ID>*) | Override type |
| substitutetype(<Industrytile-ID>*) | Substitute type |
The parameter specifies the number of animation frames to use. Maximum number of frames is 128. The optional second parameter LOOP may be added for looping animations.
A looping animation starts again from the first frame after showing the last frame. Non-looping animations stop after the last frame, leaving it on the screen. Both kinds of animations start automatically when the industry of that tile is created. It's recommended to use callback CB_ACONTROL with non-looping animations, so they are played multiple times.
This is the amount of time between switching frames. The meaning is the same as for house anim_speed(), but the lower limit is 0 instead of 2, so the fastest possible animation changes frames every game tick (27ms). The default value is 2.
In game, animation speed can be set by using callback CB_ASPEED.
anim_triggers(<List::trigger>)
Parameter is a list of events that should trigger callback CB_ACONTROL:
| Trigger | Meaning |
| STATECHANGE | construction state changes |
| PERIODIC | Periodic tile loop |
| SYNCHRON | Synchronised periodic tile loop |
| CARGO_IN | the industry of the tile receives input cargo from a station |
| CARGO_OUT | the industry distributes its output cargo to one of the stations nearby |
The industry of the tile is processed in the periodic processing loop
callbacks can be defined by setting the corresponding parameter list:
| Callback | Meaning |
| CB_ACONTROL | Periodically start/stop the animation |
| CB_AFRAME | Decide next animation frame |
| CB_ASPEED | Decide animation speed |
| CB_AUTOSLOPE | Allow/disallow autosloping |
| CB_BUILD | Decide whether the industry tile can be built on a given spot |
| CB_CARGOTYPES | Decide the cargo types accepted |
| CB_FOUNDATION | Decide if default foundations need to be drawn |
Controlling the animation doesn't need to be flagged in function callbacks(). Instead, callback events for starting/stopping the animation have to be set in function anim_triggers.
These three cargo type values define what cargo types the tile accepts. Type of cargo is according to the current climate. If you don't need all three cargo types, just zero out the unneeded ones.
From GRF version 7 and above, the meaning of the cargo type had changed: instead of a climate-dependent cargo slot number, you have to give a climate-independent cargo ID. If your GRF has a cargo translation table installed, 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.
These three values define the amount of the appropriate cargo type the tile accepts. Amount of acceptance is given in 1/8 units (0 .. 8).
For industry tiles, the following flags can be set:
| Label | Meaning |
| NORTHWEST | NW edge cannot be lowered |
| NORTHEAST | NE edge cannot be lowered |
| SOUTHWEST | SW edge cannot be lowered |
| SOUTHEAST | SE edge cannot be lowered |
| FLAT | Can only be built on flat land |
| ONWATER | The tile is allowed on both land and water |
| RANDOMBITS | Enables the use of random bits in callback CB_AFRAME |
overridetype(<Industrytile-ID>)
Setting this property function makes this industry tile appear instead of the given old TTD industry tile type. Setting this property is ignored if the given old industry tile type is already overridden. You can set this property more than once to override more old industry tile types.
substitutetype(<Industrytile-ID>)
This industry tile type will be used instead of your new one if your definition isn't available for any reason. Valid values are 00h .. AEh. Assigning this property copies the properties of the old type just like it does with houses. If this tile's defineindustrytile() function appears before this property is set, defineindustrytile() will have no effect.