Difference between revisions of "VariationalAction2"
(Clean up descriptions that are now at the storages page) |
(→Type: Related objects for airport (tiles)) |
||
(25 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
==Introduction== |
==Introduction== |
||
− | To support changes in graphics based on other factors than just the load states, you use a |
+ | To support changes in graphics based on other factors than just the load states, you use a VarAction2. This provides a sophisticated way of deciding what graphics to use. |
− | A |
+ | A VarAction2 can be used like any other action 2, but it provides an additional step in-between: instead of defining the action 1 sets right away, it instead specifies a list of additional action 2 entry, one of which is used depending on the kind of variation that is defined. These action 2 entries that are referred can in turn be variational or random (to provide chains of decisions), or they can be the final element, that is a regular action 2 which contains definitions of action 1 sets, or a callback result. |
− | ==Format== |
+ | == Format == |
The data looks as follows: |
The data looks as follows: |
||
Line 24: | Line 24: | ||
|<set-id>||B||The ID of this action 2 (used like a cargo ID) |
|<set-id>||B||The ID of this action 2 (used like a cargo ID) |
||
|- |
|- |
||
− | |<type>||B||Type of |
+ | |<type>||B||Type of VarAction2, see below |
|- |
|- |
||
|<variable>||B||Which variable we base the decision on |
|<variable>||B||Which variable we base the decision on |
||
Line 40: | Line 40: | ||
|<default>||W||Action 2 set-id to use if no range matches |
|<default>||W||Action 2 set-id to use if no range matches |
||
|} |
|} |
||
+ | |||
+ | The size of <varadjust> depends on <type> as well as the adjustments to be performed and must always provide an AND mask. For <type> 81, a "do nothing" <varadjust> would be 00 FF. |
||
You repeat the sequence of <set-id> <low-range> <high-range> as often as <nvar> specifies. |
You repeat the sequence of <set-id> <low-range> <high-range> as often as <nvar> specifies. |
||
Line 45: | Line 47: | ||
<low-range> and <high-range> have a size of B, W, or D, depending on <type>. See that entry for more information. |
<low-range> and <high-range> have a size of B, W, or D, depending on <type>. See that entry for more information. |
||
− | ==Description== |
+ | == Description == |
− | ===Sprite-number=== |
+ | === Sprite-number === |
This is just the number you are at. |
This is just the number you are at. |
||
− | ===Length=== |
+ | === Length === |
Count the number of bytes in this action. |
Count the number of bytes in this action. |
||
− | === |
+ | === Feature === |
− | This sets the type of feature that you wish to change. Set it to: |
+ | This sets the type of [[Features|feature]] that you wish to change. Set it to: |
+ | {|- | |
||
− | 00 for trains |
||
+ | !Value!![[Features|Feature]] |
||
− | |||
− | 01 for road vehicles |
||
− | |||
− | 02 for ships |
||
− | |||
− | 03 for planes |
||
− | |||
− | 04 for stations |
||
− | |||
− | 05 for canals |
||
− | |||
− | 06 for bridges |
||
− | |||
− | 07 for houses |
||
− | |||
− | 09 for industry tiles |
||
− | |||
− | 0A for industries |
||
− | |||
− | 0B for cargos |
||
− | |||
− | 0E for signals |
||
− | |||
− | 0F for objects |
||
− | |||
− | 10 for railtypes |
||
− | |||
− | ===Set-ID=== |
||
− | |||
− | This defines the number of this action 2. The ID can then be used as target in an action 3 or another variational/random action 2. |
||
− | |||
− | ===Type=== |
||
− | |||
− | The access type specifies both the size of the variable access, and selects between general variables and the object's innate variables, or variables of a specific "related" object. |
||
− | |||
− | Use 81/85/89 to decide upon a general variable, or a variable of the object in question. |
||
− | |||
− | Use 82/86/8A to refer to the "related" object: |
||
− | |||
− | {| |- |
||
− | !Feature!!Related object |
||
|- |
|- |
||
+ | |00||[[VariationalAction2/Vehicles | Trains]] |
||
− | |Vehicles (00-03)||First vehicle of consist |
||
|- |
|- |
||
+ | |01||[[VariationalAction2/Vehicles | Road Vehicles]] |
||
− | |Stations (04)||Town to which station belongs |
||
|- |
|- |
||
+ | |02||[[VariationalAction2/Vehicles | Ships]] |
||
− | |Canals (05)||N/A |
||
|- |
|- |
||
+ | |03||[[VariationalAction2/Vehicles | Aircraft]] |
||
− | |Bridges (06)||Town of bridge |
||
|- |
|- |
||
+ | |04||[[VariationalAction2/Stations | Stations]] |
||
− | |Houses (07)||Town of building |
||
|- |
|- |
||
+ | |05||[[VariationalAction2/Canals | Canals/Rivers]] |
||
− | |Generic (08)||(no action 2 support) |
||
|- |
|- |
||
+ | |06||[[VariationalAction2/Bridges | Bridges]] |
||
− | |Industry tiles (09)||Industry containing tile |
||
|- |
|- |
||
+ | |07||[[VariationalAction2/Houses | Houses]] |
||
− | |Industries (0A)||Town to which industry belongs |
||
|- |
|- |
||
+ | |09||[[VariationalAction2/Industry Tiles | Industry Tiles]] |
||
− | |Cargos (0B)||N/A |
||
|- |
|- |
||
+ | |0A||[[VariationalAction2/Industries | Industries]] |
||
− | |Sounds (0C)||(no action 2 support) |
||
|- |
|- |
||
+ | |0B||Cargos (no feature specific variables) |
||
− | |Airports (0D)||Town of airport |
||
|- |
|- |
||
+ | |0C||Sound Effects (no feature specific variables) |
||
− | |Signals (0E)||N/A |
||
|- |
|- |
||
+ | |0D||[[VariationalAction2/Airports | Airports]] |
||
− | |Objects (0F)||Town of object |
||
|- |
|- |
||
+ | |0E||[[VariationalAction2/Signals | Signals]] |
||
− | |Railtypes (10)||N/A |
||
+ | |- |
||
+ | |0F||[[VariationalAction2/Objects | Objects]] |
||
+ | |- |
||
+ | |10||[[VariationalAction2/Railtypes | Railtypes]] |
||
+ | |- |
||
+ | |11||[[VariationalAction2/Airport Tiles | Airport Tiles]] |
||
+ | |- |
||
+ | |12||[[VariationalAction2/Roadtypes | Roadtypes]] |
||
+ | |- |
||
+ | |13||[[VariationalAction2/Tramtypes | Tramtypes]] |
||
+ | |- |
||
+ | |14||[[VariationalAction2/Road Stops | Road Stops]] |
||
|} |
|} |
||
+ | === Set-ID === |
||
− | This number also tells what size the checked variable is: |
||
+ | This defines the number of this action 2. The ID can then be used as target in an action 3 or another variational/random action 2. |
||
− | For 81/82, the lowest byte of the value is accessed |
||
+ | === Type === |
||
− | For 85/86, the lowest word is accessed |
||
+ | {| |- |
||
− | For 89/8A, the lowest doubleword is accessed. |
||
+ | ! !! B<br/>Access lowest byte !! {{ottdp|0.6|2.5}} W<br/>Access lowest word !! {{ottdp|0.6|2.5}} D<br/>Access lowest doubleword |
||
+ | |- |
||
+ | !align="left"| Access general variable or<br/>variable of the primary object |
||
+ | |align="center"| 81 |
||
+ | |align="center"| 85 |
||
+ | |align="center"| 89 |
||
+ | |- |
||
+ | !align="left"| Access variable of "related" object |
||
+ | |align="center"| 82 |
||
+ | |align="center"| 86 |
||
+ | |align="center"| 8A |
||
+ | |} |
||
+ | The access type specifies both the size of the variable access, and selects between general variables and the object's innate variables, or variables of a specific "related" object. |
||
− | If the accessed variable is smaller than the size given here, the extra bits may contain junk, and should probably be <and-masked> out. |
||
+ | {|- | |
||
− | On this page, the size B/W/D means the field is byte-sized for types 81 and 82, word-sized for types 85 and 86, and doubleword-sized for types 89 and 8A. |
||
+ | !colspan="2"|[[Features|Feature]]!!Related object |
||
− | |||
− | ===Variable=== |
||
− | |||
− | Which variable to use for this decision. The following variables are always available: |
||
− | |||
− | {| |- |
||
− | !'''Number'''!![[GRFActionsDetailed|'''Size''']]!!'''Meaning''' |
||
|- |
|- |
||
+ | |00-03||[[VariationalAction2/Vehicles | Vehicles]]||First [[VariationalAction2/Vehicles | vehicle]] of consist |
||
− | |00||W||current date (counted as days from 1920) |
||
|- |
|- |
||
+ | |04||[[VariationalAction2/Stations | Stations]]||[[VariationalAction2/Towns | Town]] to which station belongs |
||
− | |01||B||current year (count from 1920, max. 2175 even with eternalgame) |
||
|- |
|- |
||
+ | |05||[[VariationalAction2/Canals | Canals/Rivers]]||N/A |
||
− | |02||B/D||current month (0-11) in bits 0-7; the higher bytes contain unusable junk. Since OTTD r13594 'day of month' (0-30) is stored in bits 8-12, bit 15 is set in leapyears and 'day of year'(0-364 resp. 365) is stored in bits 16-24. All other bits are reserved and should be masked. |
||
|- |
|- |
||
+ | |06||[[VariationalAction2/Bridges | Bridges]]||[[VariationalAction2/Towns | Town]] of bridge |
||
− | |03||B||current climate, 0=temp, 1=arctic, 2=trop, 3=toyland |
||
|- |
|- |
||
+ | |07||[[VariationalAction2/Houses | Houses]]||[[VariationalAction2/Towns | Town]] of house |
||
− | |09||W||date fraction, incremented by 0x375 every engine tick |
||
|- |
|- |
||
+ | |09||[[VariationalAction2/Industry Tiles | Industry Tiles]]||[[VariationalAction2/Industries | Industry]] containing tile |
||
− | |0A||W||animation counter, incremented every tick |
||
|- |
|- |
||
+ | |0A||[[VariationalAction2/Industries | Industries]]||[[VariationalAction2/Towns | Town]] of industry |
||
− | |0C||W||current [[Callbacks|callback]] ID (feature-specific), set to 00 when not in a callback |
||
|- |
|- |
||
+ | |0B||Cargos||N/A |
||
− | |10||D||extra callback info 1, as described in the callback specs |
||
|- |
|- |
||
+ | |0C||Sound Effects||N/A |
||
− | |11||B||current rail tool type (for station callbacks) |
||
|- |
|- |
||
+ | |0D||[[VariationalAction2/Airports | Airports]]||[[VariationalAction2/Towns | Town]] to which airport belongs |
||
− | |12||B||Game mode, 0 in title screen, 1 in game and 2 in editor |
||
|- |
|- |
||
+ | |0E||[[VariationalAction2/Signals | Signals]]||N/A |
||
− | |18||D||extra callback info 2, as described in the callback specs |
||
|- |
|- |
||
+ | |0F||[[VariationalAction2/Objects | Objects]]||[[VariationalAction2/Towns | Town]] of object |
||
− | |1A||D||always -1 (that is, all bits are set). Useful to create constants (see [[VarAction2Advanced]]) |
||
|- |
|- |
||
+ | |10||[[VariationalAction2/Railtypes | Railtypes]]||N/A |
||
− | |1B||B||display options; bit 0=town names, 1=station names, 2=signs, 3=animation, 4=transparency, 5=full detail |
||
|- |
|- |
||
+ | |11||[[VariationalAction2/Airport Tiles | Airport Tiles]]||[[VariationalAction2/Airports | Airport]] containing tile |
||
− | |1C||D||result from most recent variational action 2 |
||
|- |
|- |
||
+ | |12||[[VariationalAction2/Roadtypes | Roadtypes]]||N/A |
||
− | |20||B||snow line height, FFh if snow isn't present at all |
||
|- |
|- |
||
+ | |13||[[VariationalAction2/Tramtypes | Tramtypes]]||N/A |
||
− | |23||D||current date; long format, since OpenTTD r13376, 2.6 r2049 |
||
+ | |} |
||
+ | |||
+ | Every variable specifies a size for it. Not every variable is a doubleword. |
||
+ | If the accessed variable is smaller than the size given here, the extra bits may contain junk, and should be <and-masked> out. |
||
+ | |||
+ | === Variable === |
||
+ | |||
+ | Variational Action 2 allows accessing these variables: |
||
+ | |||
+ | {| |- |
||
+ | !'''Number'''!![[GRFActionsDetailed|'''Size''']]!!Version!!'''Meaning''' |
||
|- |
|- |
||
+ | |00-3F|| || ||See [[GlobalVariables| global variables page]]. |
||
− | |24||D||current year; long format, year zero based since OpenTTD r13376, 2.6 r2049 |
||
|- |
|- |
||
+ | |40+x||D|| ||specially calculated feature-specific variable, see following feature-specific pages |
||
− | |25||D||GrfID of the grf that contains the corresponding Action3. Useful when accessing the "related" object. Currently only supported for vehicles (OpenTTD r15739) |
||
|- |
|- |
||
+ | |5F||D||{{ottdp|0.7|2.6|ttdprev=r1928}}||Feature-specific random data: triggers in low byte, bits in other three bytes. Bits of the variable not associated with random or trigger bits are reserved. |
||
− | |40+x||D||specially calculated feature-specific variable, see following feature-specific pages |
||
|- |
|- |
||
+ | |60+x||D|| ||similar to 40+x variables, but the variable number must be followed by a byte, which will be given to the variable handler as parameter. |
||
− | |5F||D||Feature-specific random data: triggers in low byte, bits in other three bytes. Bits of the variable not associated with random or trigger bits are reserved. (2.5 r1927, 2.6 r1928) |
||
|- |
|- |
||
+ | |7B||-||{{ottdp|1.1|2.6|ottdrev=r21604|ttdprev=r2359}}||A special 60+x variable to be used in Advanced Variational Action 2. It allows to evaluate any other 60+x variable using a non-constant parameter from a register. The parameter of variable 7B specifies another 60+x variable which is evaluated. The parameter for that variable is read from the accumulator ('val1'), i.e. the result from the preceding operations of the same Advanced Variational Action 2. Hence variable 7B may not be the first variable used in the calculation. Variable 7B itself and 7E (procedure call) are not allowed to be used as parameter for variable 7B. |
||
− | |60+x||D||similar to 40+x variables, but the variable number must be followed by a byte, which will be given to the variable handler as parameter. |
||
+ | |||
+ | {{ottdp|1.2|no|ottdrev=r23138}} Since OpenTTD r23138 you can use this to pass 32 bit parameters to 60+x variables. Currently this is only useful for a few variables, e.g. vehicle variable 60. For most variables the higher bits of the parameter are considered reserved. So, make sure to mask the higher bits in the preceding calculations. |
||
|- |
|- |
||
+ | |7C||D||{{ottdp|0.6|2.6|ttdprev=r1315}}||A special 60+x variable used to access values stored in the registers of [[Storages#Persistent storage|persistent storage]]. |
||
− | |7B||-||A special 60+x variable to be used in Advanced Variational Action 2. It allows to evaluate any other 60+x variable using a non-constant parameter from a register. The parameter of variable 7B specifies another 60+x variable which is evaluated. The parameter for that variable is read from the accumulator ('val1'), i.e. the result from the preceding operations of the same Advanced Variational Action 2. Hence variable 7B may not be the first variable used in the calculation. Variable 7B itself and 7E (procedure call) are not allowed to be used as parameter for variable 7B. Also note that you can pass non-byte parameters to 60+x variable here. While current 60+x variables only use byte parameters, the higher bits of the parameter are considered reserved. So, make sure to mask the higher bits in the preceding calculations. Available since TTDPatch r2359 and OpenTTD r21604. |
||
|- |
|- |
||
− | | |
+ | |7D||D||{{ottdp|0.6|2.6|ttdprev=r1246}}||A special 60+x variable used to access values stored in the registers of [[Storages#Temporary storage|temporary storage]]. Available in the purchase list. |
|- |
|- |
||
− | | |
+ | |7E||D||{{ottdp|0.6|2.5}}||A special 60+x variable indicating a [[VarAction2Advanced#Using procedures|procedure call]]. Available in the purchase list. |
|- |
|- |
||
− | | |
+ | |7F||D||{{ottdp|0.6|2.5}}||A special 60+x variable that reads GRF parameter whose number is given by the 60+x parameter. Available in the purchase list. |
|- |
|- |
||
+ | |80+x|| || ||Feature-specific variable, see following feature-specific pages. While most of these variables actually refer to raw memory locations of original TTD structures, you cannot rely on that. Some variables were added later, some were moved or replaced. Only the variables listed in the specs are somewhat set to not be changed in the future. |
||
− | |7F||D||A special 60+x variable that reads GRF parameter whose number is given by the 60+x parameter. Available in the purchase list. |
||
− | |- |
||
− | |80+x|| ||feature-specific variable, see following feature-specific pages |
||
|} |
|} |
||
− | |||
− | The definition of variable 1B is slightly feature-dependent. For features that can be drawn transparently (stations, bridges, houses, industry tiles and objects) bit 4 is set if the current feature will be drawn normally, and clear if the current feature will be drawn transparently. For these purposes, airports are stations. For all other features, bit 4 is undefined. |
||
For all features, the 80+x variables are offsets into the corresponding structure in TTD's game data. The 40+x and 60+x variables are special variables that are computed on-the-fly, and aren't actually stored anywhere in memory, unless stated otherwise. Therefore they should be used as little as necessary so as not to slow down the game too much with the calculation of these variables (which can be called thousands of times per second, whenever any vehicle moves). |
For all features, the 80+x variables are offsets into the corresponding structure in TTD's game data. The 40+x and 60+x variables are special variables that are computed on-the-fly, and aren't actually stored anywhere in memory, unless stated otherwise. Therefore they should be used as little as necessary so as not to slow down the game too much with the calculation of these variables (which can be called thousands of times per second, whenever any vehicle moves). |
||
Line 211: | Line 200: | ||
When displaying a vehicle (etc.) in the purchase list, the game will show those variations based on external variables (dates etc.) correctly, but variations based on vehicle variables (variables 40+x, 60+x and 80+x) will always show the first (not the default) cargo-ID unless otherwise specified for the given variable. If you do a calculation, the first cargo-ID will be selected if any of the needed variables is inaccessible. |
When displaying a vehicle (etc.) in the purchase list, the game will show those variations based on external variables (dates etc.) correctly, but variations based on vehicle variables (variables 40+x, 60+x and 80+x) will always show the first (not the default) cargo-ID unless otherwise specified for the given variable. If you do a calculation, the first cargo-ID will be selected if any of the needed variables is inaccessible. |
||
− | The lists of 80+x variables on the following pages are not exhaustive; only the useful variables are listed there. For a full list check the definition of corresponding structures in TTD. Marcin Grzegorczyk has a pretty good list of the structure definitions on his [http://marcin.ttdpatch.net/sv1codec/TTD-locations.html |
+ | The lists of 80+x variables on the following pages are not exhaustive; only the useful variables are listed there. For a full list check the definition of corresponding structures in TTD. Marcin Grzegorczyk has a pretty good list of the structure definitions on his [http://marcin.ttdpatch.net/sv1codec/TTD-locations.html savegame internals page]. |
− | ===varadjust=== |
+ | === varadjust === |
Adjust variable to a more useful range. It has the following format: |
Adjust variable to a more useful range. It has the following format: |
||
Line 236: | Line 225: | ||
{| |- |
{| |- |
||
− | !Bit(s)!! |
+ | !Bit(s)!!Value!!Version!!Meaning |
|- |
|- |
||
− | |0..4||0..1F||number of bits to right shift <variable> |
+ | |0..4||0..1F||{{ottdp|0.6|2.0}}||number of bits to right shift <variable> |
|- |
|- |
||
− | |5||20||This is an [[VarAction2Advanced|advanced |
+ | |5||20||{{ottdp|0.6|2.5}}||This is an [[VarAction2Advanced|advanced VarAction2]] |
|- |
|- |
||
− | |6||40||This is a shift-and-add-divide adjustment. |
+ | |6||40||{{ottdp|0.6|2.5}}||This is a shift-and-add-divide adjustment. |
|- |
|- |
||
− | |7||80||This is a shift-and-add-modulo adjustment. |
+ | |7||80||{{ottdp|0.6|2.5}}||This is a shift-and-add-modulo adjustment. |
|} |
|} |
||
Line 251: | Line 240: | ||
Note that for the add and divide operations, both the variable and the divisor are taken to be signed numbers. This means that if the high bit is set, the number is taken to be negative, so you may need to mask out the most significant bit to do an unsigned division. |
Note that for the add and divide operations, both the variable and the divisor are taken to be signed numbers. This means that if the high bit is set, the number is taken to be negative, so you may need to mask out the most significant bit to do an unsigned division. |
||
− | ===nvar=== |
+ | === nvar === |
Here you set how many different ranges to check for. If the value of the variable, after the above manipulations, is not within one of these ranges, the default will be used. When displayed in the purchase window, the game will always show the first range if the variable is of the 40+x or 80+x type (because the variable is undefined since the vehicle doesn't exist yet). |
Here you set how many different ranges to check for. If the value of the variable, after the above manipulations, is not within one of these ranges, the default will be used. When displayed in the purchase window, the game will always show the first range if the variable is of the 40+x or 80+x type (because the variable is undefined since the vehicle doesn't exist yet). |
||
− | Since 2.0.1 alpha 57, nvar=0 is a special case. Instead of using ranges, nvar=0 means that the result of an [[VarAction2Advanced|advanced]] calculation (or, if no calculation is performed, the adjusted variable value itself) is returned as callback result, with bit 15 set. This is useful for those callbacks where many different return values are possible and it is easier to calculate them than list them in ranges. The default value must still be specified, and will be used in case the variable(s) used are not available. |
+ | {{ottdp|0.6|2.5|ttdprev=2.0.1 alpha 57}} Since TTDPatch 2.0.1 alpha 57, nvar=0 is a special case. Instead of using ranges, nvar=0 means that the result of an [[VarAction2Advanced|advanced]] calculation (or, if no calculation is performed, the adjusted variable value itself) is returned as callback result, with bit 15 set. This is useful for those callbacks where many different return values are possible and it is easier to calculate them than list them in ranges. The default value must still be specified, and will be used in case the variable(s) used are not available. |
− | ===sets and ranges=== |
+ | === sets and ranges === |
For each of the ranges to check, you give the set-id as a '''WORD''' value (i.e. with a 00 following, e.g. set-id 5 becomes 05 00, or - in case of a callback result - by setting the high bit, e.g. 05 80), followed by the low and high limits of this range. The first range that matches will be used. |
For each of the ranges to check, you give the set-id as a '''WORD''' value (i.e. with a 00 following, e.g. set-id 5 becomes 05 00, or - in case of a callback result - by setting the high bit, e.g. 05 80), followed by the low and high limits of this range. The first range that matches will be used. |
||
− | The various \b, \w, and \d escape sequences can be useful for <min-range> and <max-range>. See [[GRFActionsDetailed# |
+ | The various \b, \w, and \d escape sequences can be useful for <min-range> and <max-range>. See [[GRFActionsDetailed#Byte order|the discussion of escape sequences]] for further information. |
− | ===default=== |
+ | === default === |
The set-id to use if none of the ranges matches. |
The set-id to use if none of the ranges matches. |
||
=Example= |
=Example= |
||
+ | <pre> |
||
+ | -1 * 15 02 05 03 81 // Action2, Feature 05 (canals), action2ID 03, 1-byte variable |
||
+ | 81 00 04 // variable 81 (terrain type), shift 00, mask 0x04 (=bit for "on or above snowline") |
||
+ | 01 // check one range |
||
+ | 02 00 04 04 // snowy tile: link to action2ID 02 |
||
+ | 01 00 // default: link to action2ID 01 |
||
+ | |||
+ | </pre> |
Latest revision as of 17:57, 10 September 2023
Introduction
To support changes in graphics based on other factors than just the load states, you use a VarAction2. This provides a sophisticated way of deciding what graphics to use.
A VarAction2 can be used like any other action 2, but it provides an additional step in-between: instead of defining the action 1 sets right away, it instead specifies a list of additional action 2 entry, one of which is used depending on the kind of variation that is defined. These action 2 entries that are referred can in turn be variational or random (to provide chains of decisions), or they can be the final element, that is a regular action 2 which contains definitions of action 1 sets, or a callback result.
Format
The data looks as follows:
<Sprite-number> * <Length> 02 <feature> <set-id> <type> <variable> <varadjust> <nvar> (<set-id> <low-range> <high-range>){n} <default>
Element | Size | Description |
---|---|---|
<Sprite-number> | dec | A sequential sprite number |
<length> | dec | The total number of bytes used in this action. |
02 | B | Defines action 02 |
<feature> | B | For what type of vehicle/station should this definition be used? |
<set-id> | B | The ID of this action 2 (used like a cargo ID) |
<type> | B | Type of VarAction2, see below |
<variable> | B | Which variable we base the decision on |
<varadjust> | V | How to manipulate the value before deciding. |
<nvar> | B | Number of different ranges of the value (not counting the default) |
<set-id> | W | Action 2 set-id to use for the following range. |
<low-range> | B/W/D | Minimum (inclusive) of the range for which to use the above set-id |
<high-range> | B/W/D | Maximum (inclusive) of the range |
<default> | W | Action 2 set-id to use if no range matches |
The size of <varadjust> depends on <type> as well as the adjustments to be performed and must always provide an AND mask. For <type> 81, a "do nothing" <varadjust> would be 00 FF.
You repeat the sequence of <set-id> <low-range> <high-range> as often as <nvar> specifies.
<low-range> and <high-range> have a size of B, W, or D, depending on <type>. See that entry for more information.
Description
Sprite-number
This is just the number you are at.
Length
Count the number of bytes in this action.
Feature
This sets the type of feature that you wish to change. Set it to:
Value | Feature |
---|---|
00 | Trains |
01 | Road Vehicles |
02 | Ships |
03 | Aircraft |
04 | Stations |
05 | Canals/Rivers |
06 | Bridges |
07 | Houses |
09 | Industry Tiles |
0A | Industries |
0B | Cargos (no feature specific variables) |
0C | Sound Effects (no feature specific variables) |
0D | Airports |
0E | Signals |
0F | Objects |
10 | Railtypes |
11 | Airport Tiles |
12 | Roadtypes |
13 | Tramtypes |
14 | Road Stops |
Set-ID
This defines the number of this action 2. The ID can then be used as target in an action 3 or another variational/random action 2.
Type
B Access lowest byte |
0.6 2.5 W Access lowest word |
0.6 2.5 D Access lowest doubleword | |
---|---|---|---|
Access general variable or variable of the primary object |
81 | 85 | 89 |
Access variable of "related" object | 82 | 86 | 8A |
The access type specifies both the size of the variable access, and selects between general variables and the object's innate variables, or variables of a specific "related" object.
Feature | Related object | |
---|---|---|
00-03 | Vehicles | First vehicle of consist |
04 | Stations | Town to which station belongs |
05 | Canals/Rivers | N/A |
06 | Bridges | Town of bridge |
07 | Houses | Town of house |
09 | Industry Tiles | Industry containing tile |
0A | Industries | Town of industry |
0B | Cargos | N/A |
0C | Sound Effects | N/A |
0D | Airports | Town to which airport belongs |
0E | Signals | N/A |
0F | Objects | Town of object |
10 | Railtypes | N/A |
11 | Airport Tiles | Airport containing tile |
12 | Roadtypes | N/A |
13 | Tramtypes | N/A |
Every variable specifies a size for it. Not every variable is a doubleword. If the accessed variable is smaller than the size given here, the extra bits may contain junk, and should be <and-masked> out.
Variable
Variational Action 2 allows accessing these variables:
Number | Size | Version | Meaning |
---|---|---|---|
00-3F | See global variables page. | ||
40+x | D | specially calculated feature-specific variable, see following feature-specific pages | |
5F | D | 0.7 2.6 | Feature-specific random data: triggers in low byte, bits in other three bytes. Bits of the variable not associated with random or trigger bits are reserved. |
60+x | D | similar to 40+x variables, but the variable number must be followed by a byte, which will be given to the variable handler as parameter. | |
7B | - | 1.1 2.6 | A special 60+x variable to be used in Advanced Variational Action 2. It allows to evaluate any other 60+x variable using a non-constant parameter from a register. The parameter of variable 7B specifies another 60+x variable which is evaluated. The parameter for that variable is read from the accumulator ('val1'), i.e. the result from the preceding operations of the same Advanced Variational Action 2. Hence variable 7B may not be the first variable used in the calculation. Variable 7B itself and 7E (procedure call) are not allowed to be used as parameter for variable 7B.
1.2 Since OpenTTD r23138 you can use this to pass 32 bit parameters to 60+x variables. Currently this is only useful for a few variables, e.g. vehicle variable 60. For most variables the higher bits of the parameter are considered reserved. So, make sure to mask the higher bits in the preceding calculations. |
7C | D | 0.6 2.6 | A special 60+x variable used to access values stored in the registers of persistent storage. |
7D | D | 0.6 2.6 | A special 60+x variable used to access values stored in the registers of temporary storage. Available in the purchase list. |
7E | D | 0.6 2.5 | A special 60+x variable indicating a procedure call. Available in the purchase list. |
7F | D | 0.6 2.5 | A special 60+x variable that reads GRF parameter whose number is given by the 60+x parameter. Available in the purchase list. |
80+x | Feature-specific variable, see following feature-specific pages. While most of these variables actually refer to raw memory locations of original TTD structures, you cannot rely on that. Some variables were added later, some were moved or replaced. Only the variables listed in the specs are somewhat set to not be changed in the future. |
For all features, the 80+x variables are offsets into the corresponding structure in TTD's game data. The 40+x and 60+x variables are special variables that are computed on-the-fly, and aren't actually stored anywhere in memory, unless stated otherwise. Therefore they should be used as little as necessary so as not to slow down the game too much with the calculation of these variables (which can be called thousands of times per second, whenever any vehicle moves).
When displaying a vehicle (etc.) in the purchase list, the game will show those variations based on external variables (dates etc.) correctly, but variations based on vehicle variables (variables 40+x, 60+x and 80+x) will always show the first (not the default) cargo-ID unless otherwise specified for the given variable. If you do a calculation, the first cargo-ID will be selected if any of the needed variables is inaccessible.
The lists of 80+x variables on the following pages are not exhaustive; only the useful variables are listed there. For a full list check the definition of corresponding structures in TTD. Marcin Grzegorczyk has a pretty good list of the structure definitions on his savegame internals page.
varadjust
Adjust variable to a more useful range. It has the following format:
<shift-num> <and-mask> [<add-val> <divide-val>/<modulo-val>]
Element | Size | Description |
---|---|---|
shift-num | B | value to right-shift the variable, and some special bits. See below. |
and-mask | B/W/D | value with which to AND the variable after shifting. Return this value if neither bit 6 nor bit 7 of shift-num are set. |
add-val | B/W/D | value to add to the variable after ANDing. Only present if bits 6 or 7 are set in shift-num. |
divide-val | B/W/D | return the sum divided by this value. Only present if bit 6 is set in shift-num. |
modulo-val | B/W/D | return the sum modulo (remainder of division by) this value. Only present if bit 7 is set in shift-num. |
<shift-num> is a partial bit-mask; its bits have the following meanings:
Bit(s) | Value | Version | Meaning |
---|---|---|---|
0..4 | 0..1F | 0.6 2.0 | number of bits to right shift <variable> |
5 | 20 | 0.6 2.5 | This is an advanced VarAction2 |
6 | 40 | 0.6 2.5 | This is a shift-and-add-divide adjustment. |
7 | 80 | 0.6 2.5 | This is a shift-and-add-modulo adjustment. |
Bits 6 and 7 may not both be set. If neither are set, this varadjust is a shift-and adjustment.
Note that for the add and divide operations, both the variable and the divisor are taken to be signed numbers. This means that if the high bit is set, the number is taken to be negative, so you may need to mask out the most significant bit to do an unsigned division.
nvar
Here you set how many different ranges to check for. If the value of the variable, after the above manipulations, is not within one of these ranges, the default will be used. When displayed in the purchase window, the game will always show the first range if the variable is of the 40+x or 80+x type (because the variable is undefined since the vehicle doesn't exist yet).
0.6 2.5 Since TTDPatch 2.0.1 alpha 57, nvar=0 is a special case. Instead of using ranges, nvar=0 means that the result of an advanced calculation (or, if no calculation is performed, the adjusted variable value itself) is returned as callback result, with bit 15 set. This is useful for those callbacks where many different return values are possible and it is easier to calculate them than list them in ranges. The default value must still be specified, and will be used in case the variable(s) used are not available.
sets and ranges
For each of the ranges to check, you give the set-id as a WORD value (i.e. with a 00 following, e.g. set-id 5 becomes 05 00, or - in case of a callback result - by setting the high bit, e.g. 05 80), followed by the low and high limits of this range. The first range that matches will be used.
The various \b, \w, and \d escape sequences can be useful for <min-range> and <max-range>. See the discussion of escape sequences for further information.
default
The set-id to use if none of the ranges matches.
Example
-1 * 15 02 05 03 81 // Action2, Feature 05 (canals), action2ID 03, 1-byte variable 81 00 04 // variable 81 (terrain type), shift 00, mask 0x04 (=bit for "on or above snowline") 01 // check one range 02 00 04 04 // snowy tile: link to action2ID 02 01 00 // default: link to action2ID 01