label
In m4nfo, 'auxiliary' functions are used inside the context of performance functions, most probably inside their parameter lists, to adjust their results or arrange for special parameters.
Scope | Function | Description |
Block | engine/industry/town | Denoting hierarchies in performance function blocks |
Parameter list | label | turn 4 char <Label> into a DWORD |
little/lots | Station spriteset evaluation | |
load/move | Vehicle spriteset evaluation | |
nibble/pos | Packing and unpacking coordinates | |
signed | entering negative numbers using two's complement | |
sub | entering subroutine call | |
shiftmask/shiftmask_add_div/shiftmask_add_mod | adjusting performance function results |
These functions define a hierarchy level. Most of TTD's features have a related or a "parent" object:
Feature | Related object | Function | |
_TRAIN/_ROADVEHICLE/_SHIP/_AIRCRAFT | First vehicle of consist (if any) | engine() | |
_STATION | Town to which this station belongs | town() | |
_BRIDGE | Town of bridge | ||
_HOUSE | Town of building | ||
_INDUSTRYTILE | Industry containing this tile | industry() | |
_INDUSTRY | Town to which this industry belongs | town() | |
_OBJECT | Town of object |
I.e., "bracketing" a block in m4nfo by any of these functions means to address the features' related object instead of the current one. I.e., in case of feature _TRAIN, the use of engine() would query data not from the current vehicle inside the train's consist, but from the locomotive, and in case of a house, use of town() would query the town the house belongs to.
def(6) yearbuilt( engine( ref(4) if(< 1922) ref(5) else ) )
This function converts a negative number into its two's complement. To be used in function if(), in case the block function returns a negative result, e.g. station performance function plt_midpos():
def(9) plt_midpos( self( ref(6) if(signed(-2)) ref(7) if(signed(-1)) ref(8) if(0) ref(9) if(1) ref(0) else ) )
This function is used to turn a 4 char label, e.g. a grf ID, into a Dword:
def(11) tinfo_grfid(pos(1,0), ref(1) if(label(6D 62 06 01)) // or 6D620601 or GRF_NEWSTATIONS ref(0) else )
Chars of the label have to be given as ascii codes, not as real chars.
This function is used to check a returned byte-packed coordinate value in the usual form (<x>, <y>). Parameter range is [-8 ... +7], both for x- and y-offsets. See example:
def(51) position( ref(47) if(nibble(0,0)) // upper part ref(46) else // lower part )
This function supplies the given coordinates in a byte-packed form to another function. Parameter range is [-8 ... +7], both for x- and y-coordinates. Please note that the coordinate (0,0) refers to the current tile itself. See example:
def(1) objinfo_type(pos(0,-1), cbr(1) if(_MOLE,_QUAY,_QUAYEXT1 .. _QUAYEXT4) cbr(0) else )
This function is used to define a set of loading states for the vehicle. The numbers in the given list must reference sprite set numbers from a previous spriteblock() function. The numbers representing the graphics the vehicle should show while it's loading or unloading. For example, if it has two states, full or empty, this would need two parameters. If it has three states, full, half full or empty, this would need three.
This function is used to define a set of moving states for the vehicle. The numbers in the given list must reference sprite set numbers from a prior spriteblock() function. The meaning is the same as above.
spriteset(move(0),load(0))
spriteset(move(0,1,2,3),load(0,1,2,3))
spriteset(move(0,9,11),load(0,8,10))
In example 1, the coach uses the same sprite (number 0, first sprite of spriteblock) both for its only moving state as for its only loading state. In example 2, the freight wagon uses 4 different sprites for its moving states, and it uses the same sprites for its loading states. In example 3, the freight wagon uses 3 different sprites for its moving states, and it uses 3 different sprites for its loading states.
These two auxiliary functions are used to define sets of loading states for station tiles. The numbers in the given lists must reference sprite set numbers from a previous spriteblock() function.
Likewise for vehicles, this decides the graphics set to use depending on the amount of cargo waiting. There are two caveats, though. Firstly, a station can have 12 different cargoes waiting, not just a single one. Secondly, the maximum amount is 4095 for all stations and all cargo types.
Regarding the first issue, the amount of cargo this refers to depends on the makestation() function that triggered this spriteset():
Regarding the second issue, TTDPatch introduces the distinction between "little" and "lots of" cargo. The amount where this occurs is set by property function threshold(), which is zero by default. But if set to a non-zero value, for example 200, then the range 0 to 199 is divided by <numlittlesets>, and the remaining range 200 to 4095 is divided by <numlotssets>. If threshold() is set to zero, the "little" sets are never used, and so <numlittlesets> may be zero. <numlotssets> must never be zero, however.
def(ALL_NORMAL) spriteset(little(0),lots(0))
def(1) cbset(little(0,0,8,16,24,32,40,48),lots(56)) def(2) cbset(little(0,8,16,24,32,40,48,56),lots(64)) def(3) cbset(little(0,16,24,32,40,48,56,64),lots(64)) def(4) randomcb(__roofs, ARRIVE,16,ref(1),ref(2),ref(2),ref(3))
This function adjusts a performance function result to a more useful range. Its first parameter defines the value to right-shift the result of the function, and the second parameter means the value with which to AND the result after shifting.
Please note that parameter <mask> might be of WORD-size in a given context. See example:
// check if only bit 0 set (long-distance only) def(6) getubits(shiftmask(0,UB_ALL), attach(ATT_OK) if(UB_F) // Fernverkehr ref(5) else )
def(8) tinfo_slope(pos(0,0),shiftmask(0,NORTH+SOUTH), ref(5) if(NORTH) ref(6) if(SOUTH) ref(7) else )
def(22) anim_counter(shiftmask(0,0x1FF), animframe(A_NEXT) if(0) // proceed animframe(1) else // stay in pause )
shiftmask_add_div(<shift>,<mask>,<add>,<div>)
As above, this function adjusts a performance function result to a more useful range. Its first parameter defines the value to right-shift the result of the function, and the second parameter means the value with which to AND the result after shifting.
In addition, the third and fourth parameters define values to adjust the former result even further, by adding to and/or dividing it.
shiftmask_add_mod(<shift>,<mask>,<add>,<mod>)
Likewise, this function works as above, only by applying the modulo function instead division.