General functions are feature-independent functions, e.g. for parameter and error handling, branching inside the newGRF, definition of text strings, etc. Unlike global functions, they are never used inside a control chain, but either stand-alone or as parameters to other functions:
Function | Description |
Initialisation | Initialisation functions |
Flow of control | Flow of control functions and parameter handling |
Error handling | Functions for error handling and newGRF de-activation |
Auxiliary functions | Auxiliary functions |
Callback helper functions | Callback helper functions |
Sound handling | Sound handling functions |
Recolouring | Functions for recolouring purposes |
Price and cost handling | Functions for including 'real' prices and costs |
basecost(<List::(<Label>,<Byte>)>) | Setting base costs |
grf_override(<block>) | Define newGRF overrides |
insertcomment(<String>) | Insert a permanent comment into the generated nfo code |
random_[im]pair(<range>) | get even/odd random number from range |
readregister(<register>, <reference>) | read register and chain |
setproperties(<ID> | <Range::ID>) | Apply single property function to feature ID(s) |
setrefreshbox(<block>) | setrefreshbox |
setregisters(<register>, <List::value>, <reference>) | set register(s) and chain |
snowlinetable(<Byte*12*32>) | Set snow line height data |
basecost(<List::(<Label>,<Byte>)>)
This function allows to set base costs, which define how much everything in game costs. Each cost is calculated from a (fixed) factor times the base cost, which is adjusted by inflation every month.
The function takes as its parameter a list of pairs of cost entries and factors. The default factor of a base cost entry is '1', which leaves the base cost unchanged. Doubling the factor doubles the base cost, negative factors will halve it (i.e., -64,-32,-16,-8,-4,-2,1,2,4,8,16,32,64,128).
Available base cost entries are:
ID | Label | Default | Description |
0x01 | BUILD_TRACK | 100 | build track tile |
0x02 | BUILD_ROAD | 95 | build road tile |
0x03 | BUILD_SIGNAL | 65 | place signal |
0x04 | BUILD_BRIDGE | 275 | build bridge tile |
0x05 | BUILD_DEPOT | 600 | build rail depot |
0x06 | BUILD_RVDEPOT | 500 | build road vehicle depot |
0x07 | BUILD_SHIPDEPOT | 700 | build ship depot |
0x08 | BUILD_TUNNEL | 450 | build tunnel unit |
0x09 | BUILD_PLAT | 200 | build station platform tile |
0x0B | BUILD_AIRPORT | 600 | build airport tile |
0x0C | BUILD_BUS | 200 | build bus station |
0x0D | BUILD_LORRY | 200 | build lorry loading area |
0x0E | BUILD_DOCK | 350 | build dock |
0x0F | BUILD_ENGINE | 400,000 | locomotive purchase |
0x10 | BUILD_WAGON | 2000 | wagon purchase |
0x11 | BUILD_PLANE | 700,000 | build aircraft |
0x12 | BUILD_RV | 14,000 | road vehicle purchase |
0x13 | BUILD_SHIP | 65,000 | ship purchase |
0x14 | BUILD_TREE | 20 | plant tree |
0x15 | BUILD_LAND | 250 | raise/lower land |
0x16 | CLEAR_GRASS | 20 | clear grass tile |
0x17 | CLEAR_ROUGH | 40 | clear rough land tile |
0x18 | CLEAR_ROCK | 200 | clear rocky tile |
0x19 | CLEAR_FIELD | 500 | clear field tile |
0x1A | DEL_TREE | 20 | remove tree |
0x1B | DEL_TRACK | -70 | remove track tile |
0x1C | DEL_SIGNAL | 10 | remove signal |
0x1D | DEL_BRIDGE | 50 | remove bridge tile |
0x1E | DEL_DEPOT | 80 | remove rail depot |
0x1F | DEL_RVDEPOT | 80 | remove road vehicle depot |
0x20 | DEL_SHIPDEPOT | 90 | remove ship depot |
0x21 | DEL_TUNNEL | 30 | remove tunnel tile |
0x22 | CLEAR_WATER | 10,000 | clear water tile |
0x23 | DEL_PLAT | 50 | remove station platform tile |
0x24 | DEL_AIRPORT | 30 | remove airport tile |
0x25 | DEL_BUS | 50 | remove bus station |
0x26 | DEL_LORRY | 50 | remove lorry loading area |
0x27 | DEL_DOCK | 55 | remove dock |
0x28 | DEL_HOUSE | 1600 | remove house |
0x29 | DEL_ROAD | 40 | remove road tile |
0x2A | RUN_STEAM | 5600 | steam engine running cost |
0x2B | RUN_DIESEL | 5200 | diesel engine running cost |
0x2C | RUN_ELECTRIC | 4800 | electric engine running cost |
0x2C | RUN_ENGINE | 4800 | locomotive running cost |
0x2D | RUN_PLANE | 9600 | aircraft running cost |
0x2E | RUN_RV | 1600 | road vehicle running cost |
0x2E | RUN_WAGON | 1600 | wagon/coach running cost |
0x2F | RUN_SHIP | 5600 | ship running cost |
0x30 | BUILD_INDUSTRY | 1,000,000 | fund industry |
0x31 | DEL_INDUSTRY | 1600 | remove industry |
0x32 | BUILD_OBJECT | 40 | build object |
0x33 | DEL_OBJECT | 40 | remove object |
0x34 | BUILD_WAYP | 600 | build waypoint |
0x35 | DEL_WAYP | 80 | remove waypoint |
0x36 | BUILD_BUOY | 350 | build buoy |
0x37 | DEL_BUOY | 50 | remove buoy |
0x3C | BUILD_CANAL | 5000 | build canal |
0x3D | DEL_CANAL | 5000 | remove canal |
0x3E | BUILD_ACQUAE | 10,000 | build aquaeduct |
0x3F | DEL_ACQUAE | 2000 | remove aquaeduct |
0x40 | BUILD_LOCK | 7500 | build lock |
0x41 | DEL_LOCK | 2000 | remove lock |
basecost( {BUILD_SIGNAL,4}, {BUILD_BRIDGE,2}, {BUILD_DEPOT,4}, {BUILD_TUNNEL,8}, {BUILD_ENGINES,2}, {BUILD_WAGGONS,4}, {DEL_SIGNAL,2}, {DEL_BRIDGE,4}, {DEL_DEPOT,2}, {DEL_TUNNEL,8}, )
Be aware that using basecost() with multiple parameters will produce the same number of nfo code 'sprites'. Therefore, if a basecost() function needs to be skipped, the same number has to be used in a skipif() function, not just "1". For an example, see here.
This function needs to be used to enable newGRFs to modify data of another newGRF in OpenTTD. It provides a list of 'source' and 'target' newGRF IDs to let engines in the source newGRF "override" those in the target newGRF, but only when OpenTTD's "dynamic engines" feature is enabled.
The parameter block is set up by one or more entries of function maymodify().
Multiple entries may be used, and different newGRFs can be set to override the same 'target' newGRF, but only the last instance of a 'source' newGRF is active. newGRF IDs that are not present will have no effect.
The scope of this feature is quite limited and it should be used only for sets that modify data of another set, for example the DBSetXL ECS addon for DBSetXL, or the censored version of LV4.
This function takes a pair of newGRF IDs (1. source-ID, 2. dest-ID), and has to be used in the context of grf_override(), see above.
// "enginepool" only available in OTTD skipif(1, PLATFORM, ==, PATCH) // if OTTD: DBXL_ECS may override DBXL grf_override( maymodify(GRF_DBXLECS, GRF_DBXL) )
These are two functions which return even or odd random numbers for a given range. The return value is a callback, to be used as input to other functions.
E.g., possible results from
random_pair(4 .. 11) might be 4, 6, 8, or 10 and
random_impair(4 .. 11) could be 5, 7, 9, or 11.
A nice use case would be to include randomisation into the setregisters() function when working with ASL:
def(1) setregisters(5,4, ref(RESOLVE)) def(2) setregisters(5,6, ref(RESOLVE)) def(3) setregisters(5,8, ref(RESOLVE)) def(4) setregisters(5,10, ref(RESOLVE)) def(5) setregisters(5,12, ref(RESOLVE)) def(6) setregisters(5,14, ref(RESOLVE)) def(7) setregisters(5,16, ref(RESOLVE)) def(8) setregisters(5,18, ref(RESOLVE)) def(9) setregisters(5,20, ref(RESOLVE)) def(10) setregisters(5,22, ref(RESOLVE)) def(11) setregisters(5,24, ref(RESOLVE)) def(12) setregisters(5,26, ref(RESOLVE)) def(13) setregisters(5,28, ref(RESOLVE)) def(14) setregisters(5,30, ref(RESOLVE)) def(15) setregisters(5,32, ref(RESOLVE)) def(16) setregisters(5,34, ref(RESOLVE)) def(10) random(BUILT,16, ref(1),ref(2),ref(3),ref(4),ref(5),ref(6),ref(7),ref(8), ref(9),ref(10),ref(11),ref(12),ref(13),ref(14),ref(15),ref(16))
Or, better yet, setting registers 5 (for x-) and register 6 (for y-direction) in one go:
Note that for stations, there are only 4 random bits available per tile. So, to get tile-based randomness, don't use ranges larger than 16.
setproperties(<ID> | <Range::ID>)
This function is used to set (or overwrite) a single property function, either for a single ID or a continuous range of IDs. It is useful in cases where one single property has to be modified due to external reasons, for example based on the value of a parameter.
IDs may be for any of TTD's features (vehicles, stations, houses, ...).
// main line electrified setproperties(_BR111, railtype(SACE) ) // branch line setproperties(_BR92 .. _BR38, railtype(SABN) )
skipif(1, PLATFORM, !=, NMF) setproperties(ANDRAE .. BUIR, bridge_height({3,3,3,3}) )
setregisters(<register>, <List::value>, <reference>)
This function sets registers, starting with <register>, to values given in the list, and chains to <reference>. By supplying '-' as a value, setting of associated registers are suspended, which might be useful in some applications. Instead of a value, a subroutine call might be included as well, by using helper function sub(<reference>). As usual, a list consisting of more than one value has to be quoted.
// set register "4" to value "1" and chain to ref(0x14) def(6) setregisters(4, 1, ref(0x14)) // set registers "4 .. 6" to values "1,2,3" and chain def(6) setregisters(4, {1,2,3}, ref(0x14)) // set registers "4 .. 6" to values "1,2,3" and register "8" to "4", // leave register "7" untouched def(6) setregisters(4, {1,2,3,-,4}, ref(0x14)) // set register "4" to result of subroutine "5" def(6) setregisters(4, sub(5), ref(0x14)) // set registers "4 .. 6" to values "1,2,3" and register "8" to // result of subroutine "__randomsprite", leave register "7" untouched def(6) setregisters(4, {1,2,3,-,sub(__randomsprite)}, ref(0x14))
This function is likely to be used in connection with advanced sprite layouts (ASL). See example, or tutorials.
This function installs a so-called "snow line height table", which allows to specify the snow line height for every day of the year. The table must contain 12*32 = 384 bytes, values will be read as hexadecimal numbers.
To simplify things for TTDPatch, every month has 32 entries, and the impossible combinations (like 32th January or 31th April) will never be read. The entries should be a multiply of 8 or else some visual glitches may appear. Values below "10" (hex!) and above "EF" may result in overflow and should not be used. Since the highest possible land is 0x78 high, giving "88" or above will effectively disable the snow line.
If the temperate snow line is enabled, this table applies on temperate as well.
snowlinetable( 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 // jan 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 // feb 20 20 20 20 20 20 20 20 20 20 20 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 // mar 28 28 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 38 38 38 38 38 38 38 38 38 38 38 38 38 38 // apr 38 38 40 40 40 40 40 40 40 40 40 40 40 40 40 40 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 // may 48 48 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 58 58 58 58 58 58 58 58 58 58 58 // jun 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 // jul 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 // aug 58 58 58 58 58 58 58 58 58 58 58 58 58 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 // sep 50 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 // oct 40 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 // nov 30 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 20 20 20 20 20 20 20 20 20 20 20 20 // dec )