Industries work similarly to town buildings, except that the maximum number of possible industries is 37 in TTDPatch and 64 in OpenTTD. The non-overridden original industries are counting towards this limit. Industries don't have a climate mask, so you should simply not define an industry if it would be for the wrong climate.
Defining industries 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 defineindustry()) 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.
All industry properties are defined inside the defineindustry() function. Depending on the type of industry, different properties would have to be used. See the example. All properties are given by the property functions below.
| Property function | Description |
| callbacks(<List::callback>) | List of callbacks used |
| cargomultipliers((<Word>, <Word>)*3) | Input cargo multipliers for input cargo types |
| conflicting(<Byte>*3) | Conflicting industry types |
| destructioncost(<Dword>) | Destruction cost multiplier |
| flags(<List>) | Industry flags |
| fundingcost(<Byte>) | Fund cost multiplier |
| incargotypes(<CargoType>*3) | Acceptance cargo types |
| industrytext(<Label>, <String>) | Set various industry-related texts |
| industrytype(<List>) | Type of industry |
| mapcolour(<Byte>) | Colour of industry on mini map |
| mindistribution(<Byte>) | Minimal amount of cargo distributed |
| outcargotypes(<CargoType>*2) | Production cargo types |
| overridetype(<Industry-ID>) | Override type |
| probgame/probstart(<Byte>) | Probabilities during gameplay and for new games |
| productionmultipliers(<Byte>*2) | Production multipliers |
| prospectingsuccess(<Unit-term>) | Prospecting success chance |
| randomsounds(<List::Sound-ID>) | Random sound effects |
| substitutetype(<Industry-ID>) | Substitute type |
For industries, the following callbacks can be defined by setting the corresponding parameter list:
| Callback | Meaning |
| CB_ARRIVE | Call the production callback when cargo arrives at the industry |
| CB_BUILD | Determine whether the industry can be built |
| CB_CARGOSUBTEXT | Cargo sub-type display |
| CB_COLOUR | Decide industry colour |
| CB_EFFECTS | Control special industry effects |
| CB_FUNDTEXT | Additional text in industry fund window |
| CB_INCARGO | Decide input cargo types |
| CB_LOCATION | Determine whether the industry can be built on given spot |
| CB_PERIODIC | Call the production callback every 256 ticks |
| CB_MONTHLYPROD | Monthly random production change |
| CB_OPTOUT | Opt out of accepting cargo |
| CB_OUTCARGO | Decide output cargo types |
| CB_RANDOMPROD | Control random production changes |
| CB_TEXT | Show additional text in industry window |
cargomultipliers((<Word>, <Word>)*3)
Parameters of this function are two Words for each of the three possible input cargo types. Given W1 and W2 are the parameters for the first input cargo type, and X is the units of the corresponding cargo delivered to the industry, the output amounts for the two output cargo types are calculated like this:
The parameters define 3 industry types that won't appear in the vicinity of this industry. If a parameter has bit 7 set (e.g., 0x80 + ID), the bottom 6 bits are the ID of a new industry type already defined in the current newGRF file. If bit 7 is clear, the bottom 6 bits specify an original TTD industry type. Value 0xFF can be used to fill unused entries. You shouldn't modify the override type by function overridetype() after the type has been referenced by function conflicting().
This value specifies the cost of removing the industry when the ctrl-dynamite function of morebuildoptions.removeindustry is enabled. This value is multiplied by the house removal cost multiplier to get the final cost. The default value is 1000 in TTDPatch, and 0 in OpenTTD.
This function defines special behaviour of the industry in question.
| Value | Meaning |
| AFTER1960 | The industry is built only after 1960 (oil rig) |
| AIBEHAVIOUR | AI players will attempt to establish air and ship routes going to this industry (oil rig) |
| AIRPLANE | Disaster: the industry can be exploded by a military airplane (oil refinery) |
| AUTOMATIC | Automatic production multiplier handling (No industry has this bit set by default) |
| BEFORE1950 | The industry is built only before 1950 (oil wells) |
| HASFIELDS | Fields are planted around the industry when it is built (all farms) |
| HELICOPTER | Disaster: the industry can be exploded by a military helicopter (factory) |
| INTOWNS | The industry can only be built in towns, i.e. it has to replace houses (arctic and tropic banks, water tower) |
| LASTINSTANCE | (since r1925) Allow closing down the last instance of this type (No industry has this bit set by default) |
| NEARTOWNS | The industry is always built near towns, i.e. near town sign; additionally the industry is allowed to replace houses (toy shop) |
| NOINCREASE | The industry cannot increase its production on the temperate climate (oil wells) |
| NOINSTANCE | (since r1925) Do not force one instance of this type to appear during initial map generation (No industry has this bit set by default) |
| ONWATER | The industry is built on water (oil rig) |
| PLANTFIELDS | The industry periodically plants fields around itself (temperate and arctic farms) |
| POP1200 | The industry can only be built in towns with population larger than 1200, i.e. it has to replace houses (temperate bank) |
| RANDOMBITS | The production callback needs random bits from function randombits() (No industry has this bit set by default) |
| SUBSIDENCE | Disaster: the industry can cause a subsidence (coal mine) |
| TREECUTTING | The industry cuts trees around itself and produces its first output cargo from them (lumber mill) |
If AUTOMATIC is set, functions cargowaiting() will be divided by the industry's "production multiplier" (TTD var 93), and the result will be multiplied by the same amount before applying them. If you set AUTOMATIC, please use small amounts in your instructions, since the production multiplier is set to 16 for default production, and can get as high as 128.
By default, TTDPatch tries to ensure that cargo chains (e.g., extracting industry -> processing industry) don't get broken. To achieve this, TTDPatch always generates at least one instance from every available industry type during random map generation, and prevents the last instance from closing down even when the production change callbacks (CB_MONTHLYPROD or CB_RANDOMPROD) say it should. If the industry type isn't essential for gameplay, or the newGRF wants to handle this situation itself, NOINSTANCE and/or LASTINSTANCE can be set to turn off the default TTDPatch behavior.
If you supply a lot of industry types but also want to support OpenTTD's small map sizes you should set NOINSTANCE for the less important industry types which can be ommitted (there will likely not be enough space for an industry of every type).
The parameters define what cargo types the industry accepts. Type of cargo is according to the current climate. If you don't need all three cargo types, just mark them unused (NONE).
These cargo types will only be really accepted if the according acceptance of the industry tiles adds up to 8/8 or more.
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 type ID. If the newGRF has a cargo translation table installed, then this ID is the index in that table; otherwise, it's the cargo bit. Acceptance of cargo types not currently present will automatically be disabled.
industrytext(<Label>, <String>)
This function defines various industry-related text strings, depending on its first parameter. Texts would have to be defined previously by function deftxt().
| Label | Meaning |
| CLOS | Industry closure message, shown if the industry announces its closedown |
| DECR | Production decrease message, shown if the industry decreases production |
| INCR | Production increase message, shown if the industry increases production |
| NAME | Industry name |
| NEW | New industry text |
| STAT | Default text for nearby station |
The text string(s) for NAME will be attached to the town name when TTD texts refer to this industry.
The text associated with NEW will be shown if the industry is generated during the game. For the generation message, by default, all industries have "New xxx is being constructed near yyy", except forests, that have "New Forest is being planted near yyy".
If non-zero, the text associated with STAT specifies an additional name option for stations built near this industry, which will be used before any of the standard TTD names. The text should contain "\80", which will represent the name of the nearby town.
If the newly built station cannot use the specified text (because that name has already been used for another station in the same town), the default TTD naming system will be used, but without the names "\80 Oilfield" or "\80 Mines".
Setting this to zero disables "\80 Oilfield" and "\80 Mines" without adding any additional station name options.
This function sets the industry type and arranges for specific behaviour, both in naming convention and in mode of production:
| Value | Meaning | Effect on nearby stations | Effect if CB_RANDOMPROD is disabled |
| EXTRACTIVE | extractive industry (e.g. coal mine) | suffix 'Mines' if some non-liquid, non-passenger, non-mail cargo is produced | Standard primary-industry production change |
| ORGANIC | organic industry (e.g. forest) | suffix 'Forest' or 'Woods' if wood is produced | Standard primary-industry production change |
| PROCESSING | processing industry (e.g. steel mill) | none | Standard processing-industry closing behaviour |
| STATIC | static industry (e.g. power plant) | none | no production changes and no closing |
The parameter must be a colour index from the DOS palette. The following values are used by TTD's default industries:
| Index | Label | Colour | Example |
| 01 | BLACK | Black | Coal mine |
| 0A | GRAY | Gray | Steel mill |
| 0F | WHITE | White | Bank |
| 25 | DKBEIGE | Dark beige | Water supply |
| 27 | LTBEIGE | Light beige | Rubber plantation |
| 30 | PINK | Pink | Farm |
| 37 | BROWN | Brown | Food processing plant |
| 56 | GREEN | Green | Forest |
| 98 | BLUE | Blue | Oil wells/oil rig |
| AE | PURPLE | Purple | Factory |
| B8 | RED | Red | Power station |
| BF | YELLOW | Yellow | Oil refinery |
| C2 | ORANGE | Orange | Saw mill |
| D0 | LTGREEN | Light green | Water tower |
The produced cargo will be distributed to stations only after it exceeds this amount.
Two climate-dependent cargo types the industry can produce. Unused slots can be filled with 0xFF.
Setting this property function makes this industry appear instead of the given old TTD industry type.
The overridden industry type won't be built in new random games. If the newGRF file becomes active after the game was started, industries of the overridden new type won't be replaced by the new type.
By overriding an old type, you're saying "my type is a substitute for that old type". When newGRFs ask information about the old type you've overridden, they will get information about your type instead. If you want to replace an old industry type with something completely different, use substitutetype(), then define the new industry type without using overridetype(). A rule of thumb: if your industry accepts or produces different cargoes than the original one, it should not override the original one.
For example, if you want to replace the old coal mine with something that changes its coal production more dynamically, use overridetype() to override industry type "0x00". This way, other industries that want to be far from coal mines will stay far from your industry type too. If, however, you want to replace the coal mine with a potash mine, do not use overridetype(). This will ensure that other industries don't consider your type as a coal mine.
Please note, however, that only one new industry can override an old type. If two new types want to override the same old type, the first one wins, and the second is added normally, ignoring its overridetype().
These two functions set the probability of this industry either for industries spawned during game or initialized at game start. TTD default industry types have probabilities between 0 and 10. If the random game probability value is nonzero, at least one instance of this type is guaranteed to appear on the map.
These probabilities are "relative probabilities". That is, if you set the probability of industry A to twice the probability of industry B, industry A will appear about twice as often as B. Increasing the probabilities of all industries on the other hand changes nothing. The appearance probabilities have no influence on how many industries are placed in total.
productionmultipliers(<Byte>*2)
If nonzero, the industry periodically (every 256 ticks, that is 8 or 9 times in a month) produces the given amount from the according cargo type. Parameters specify the amount produced at default production level, they are scaled equally on production changes.
prospectingsuccess(<Unit-term>)
This function sets the rate of success, given as a percent value, when prospecting a new industry of this type. Currrently, it is used only for extractive and organic industries. The higher this value is, the higher the chance that your industry can be built on a random place after prospecting.
randomsounds(<List::Sound-ID>)
TTD periodically picks one of the available effects randomly, and plays it.
The first assignment by this property function copies all properties of the old industry type to this new type. Unlike for houses, the substitute type won't replace this new type if the definition becomes unavailable.
There's a special use of this function since TTDPatch alpha 70: if you set it to 0xFF (or DISABLE), you can disable an original industry. In this case, the ID used must be the number of industry you want to disable. Disable requests are ignored for industries not present on the current climate and industries already overridden.