NML:Switch
Vehicles, Stations, Canals, Bridges, Towns, Houses, Industries (Tiles), Cargos, Airports+Tiles, Objects, Railtypes, Roadtypes, Tramtypes, Terrain
switch (<expression>, (SELF|PARENT), <ID>, <expression>) { (<range>: <return_value>;)* <return_value>; }
The four parameters have the following meaning:
<expression>
: The feature for which this switch is used (see Features).(SELF|PARENT)
Which variables to use. SELF uses the variables of the item itself, while PARENT uses the variables of a related object. This related object differs per feature, refer to the table below.<ID>
Name of this switch block. This (unique) name can be used to refer to the block from other switch- or graphics-blocks.<expression>
The expression that will be evaluated to make a decision. This expression may contain variables. Instead of a single expression this may also be an array of expressions. In that case all of the array elements are evaluated in order and the last one is used to make a decision.
Feature | SELF | PARENT | permanent storage |
---|---|---|---|
FEAT_TRAINS | Engine / wagon / articulated part itself | Front engine | no |
FEAT_ROADVEHS | Road vehicle part | First road vehicle part | no |
FEAT_SHIPS | Ship | Ship | no |
FEAT_AIRCRAFT | Aircraft (a) | Aircraft | no |
FEAT_STATIONS | Station tile | Town | no |
FEAT_CANALS | Canal tile | N/A | no |
FEAT_BRIDGES | Bridge | Town | no |
FEAT_HOUSES | House tile | Town | no |
FEAT_GLOBALVARS | N/A | N/A | no |
FEAT_INDUSTRYTILES | Industry tile | Industry to which the tile belongs | no |
FEAT_INDUSTRIES | Industry | Town | yes |
FEAT_CARGOS | Cargo type | N/A | no |
FEAT_SOUNDEFFECTS | N/A | N/A | no |
FEAT_AIRPORTS | Airport | N/A | yes |
FEAT_SIGNALS | N/A | N/A | no |
FEAT_OBJECTS | Object tile | Town | no |
FEAT_RAILTYPES | Rail tile | N/A | no |
FEAT_AIRPORTTILES | Airport tile | Airport | no |
(a) Except for mail capacity callbacks, where it refers to the mail compartment. To refer to the aircraft itself, use PARENT scope there.
<range>
can either be a single number or two numbers separated by two dots. In the first case, the range matches if the result of the computation is equal to the supplied value. If a range (a .. b
) is supplied, it matches if the computed result is within that range. If several lines of the switch block match the expression being tested the first applicable result will be returned.
Possible values for <return_value>
are the following:
<ID>;
chains to the (random-)switch or spritegroup with the given ID.return (<expression>|<string>);
returns the given expression or string as a result of the callback. A returned expression may contain variables (with the same scope as the switch block itself), parameter accesses and everything else that a normal switch-expression may contain.return;
returns the computed value directly as a callback result. Note that the maximum value for callback results is 32511 (0x7EFF).CB_FAILED;
stops processing and returns an explicit failure code.
Some example code is given below. Note that the code does not have an actual meaning, it is merely meant to demonstrate all the various options available.
switch (FEAT_TRAINS, PARENT, some_vehicle_switch, (position_in_consist + param[1]) % 4) { 0..2: return string(STRING_FOO_BAR); //return a text message 3: return; //return the computed value 5..300: return 42; //42 is always a good answer 400: other_switch; //chain to some other switch block 401: return num_vehs_in_consist + 1; //return a value with a variable access CB_FAILED; //return a failure result as default }
You can also use temporary variables and with some features also pemanent variables to store and retrieve some values by means of STORE_TEMP(value, register)
, LOAD_TEMP(register)
and STORE_PERM(value, register)
and LOAD_PERM(register[, grfid])
respectively. Using temporary storage is useful when you want to use the result of an expensive calculation in various decisions (switches) within the chain (like for example the number of a certain wagon type within a train). Permanent storage might be useful to control the long-term behaviour of an object. Note that it is only available for industries, airports and towns. For towns, you can optionally specify a grfid to load registers belonging to a different grf. Note that accessing (both reading and writing) permanent town registers thrashes the contents of temporary register 0x100.
NML 0.3 As of NML 0.3 it is possible to specify the default value using default: <value>;
as one of the 'ranges'. Specifying multiple default values (either this way or by the classical method) is of course not possible, but omitting a default value is allowed. In that case, if none of the ranges matches, the callback fails.