The m4nfo User manual and Technical Report

Object callbacks

Using callbacks for objects

Introduction

This is an in-depth description of object callbacks. More basic information about callbacks can be found here.

A 'callback' is a special action that TTDPatch 'calls' in order to modify various attributes of a feature (e.g., an object) previously defined. Examples would be the modifications of the visual effect of a train vehicle, its speed, or its capacity.

This is done by identifying the incidence and the possible type of a callback in the callback() function. Depending on the type of the callback, control is eventually handed over to a function which handles the callback, or lets it fail. In the latter case, the value previously set by the appropriate property function will be kept using.

In addition, all animation callbacks also allow to trigger sound effects by returning a sound-ID value in the high byte of the callback result. This could be achieved in m4nfo by shifting the sound-ID value 8 bits to the left and OR-ing it with the appropriate animation state value, like this: cbr(eval((<sound_ID> <<8) | <animstate>)).

Instead, one of m4nfo's helper functions could be used, supplying a second parameter (in addition to the callback result) which will be interpreted as a sound effect ID, like this: animcontrol(0, SND_HORN) if(CB_ACONTROL). The corresponding sound effect will then be played on the appropriate object tile, according to the state of the corresponding animation.

Here's a list of all available callbacks for objects. Please note, that not all of them need to be explicitly activated in the callbacks() property function during the object definition stage:

Callback Description
CB_ACONTROL Set frame the animation should jump to
CB_AFRAME Set next animation frame
CB_ASPEED Set animation speed
CB_AUTOSLOPE Allow/disallow autosloping
CB_COLOUR Set colour of object
CB_SLOPE Custom slope check
CB_TEXT Additional text in purchase screen

Please also note that CB_SLOPE and CB_TEXT are to be used in the MENU branch.

Description

CB_ACONTROL - set frame the animation should jump to

This Callback is called periodically or when an animation trigger happens. It returns the number of the frame the animation should jump to, or one of the following special values:

ValueLabelMeaning
255A_STOPstop animation in its current frame
254A_STARTstart animation with its current frame
253A_NOPleave the animation in its current state (do nothing)

Callback values have to be specified as usual by cbr(), or by using the helper function animcontrol().

From TTDPatch 2.5 beta 2, you can ask for random bits by function obj_randombits(). To enable this, set RANDOMBITS in the object property function flags().

This callback is always available, it doesn't need to be defined in the object's callbacks() property function.

CB_AFRAME - set next animation frame

Called in every animation frame, this callback returns the number of the next frame to display. Additionally, it can return these special values:

ValueLabelMeaning
255A_STOPstop animation. The current frame stays on screen until the animation is restarted.
254A_NEXTcontinue with next frame as usual. You can return this for stages where you don't want to do anything special.

Callback values have to be specified as usual by cbr(), or by using the helper function animframe().

Since TTDPatch 2.5 beta 2, you can ask for random bits by function obj_randombits(). To enable this, set RANDOMBITS in the object property function flags().

CB_ASPEED - set animation speed

Called to decide how long the current animation frame should last. The value of the delay should be given in the same way as for property 1B/10/17. Decreasing the return value speeds the animation up instantly. Increasing, on the other hand, doesn't slow it down instantly: the actual duration of the current frame will be somewhere between the old and the new delays. The new delay is applied correctly for later frames.

Note: This is one of the most time consuming callbacks as it is called for every animated tile every ~30 milliseconds. For better performance try to avoid using it where reasonable, e.g. try to use only the properties and put multiple identical looking animation frames after each other.

CB_AUTOSLOPE - allow/disallow autosloping

Use of this callback prevents the autoslope feature from altering the ground below an object tile. To prevent altering the ground, return DISALLOW_AUTOSLOPE. Returning ALLOW_AUTOSLOPE will allow land modifications.

Example (Don't allow autosloping):
def(50) callback(
	DISALLOW_AUTOSLOPE if(CB_AUTOSLOPE) // do not allow change of slope
	ref(49) else // graphics
)

CB_COLOUR - set colour of object

This callback allows you to set/modify the colour of an object upon construction. Function colour() returns the current company colour or a random colour for when there is no company, i.e. in the scenario editor. If the object wants a 2CC colour mapping two nibbles, i.e. two colours, are passed in variable 10, otherwise one nibble (colour).

CB_SLOPE - custom slope check

This callback is called for each tile the object will be built. Return ALLOW to accept the current tile or DISALLOW to make the object building fail with the "Land sloped in wrong direction" error message. Other return values are reserved for future use, don't use them for now.

Since the object isn't built yet, most of the object performance functions can't be accessed. Functions testposition() and testslope() will work though.

The callback is called only after the normal checks TTD does for slopes, so it's not possible to allow a slope that isn't allowed by default; you can only narrow the set of allowed slopes. If the callback fails, the tile will be accepted.

This callback is always available and will be used automatically just before object construction, it does not require to be flagged in the object's callbacks() property function.

Example (Check if object may be built on slope):
def(49) testslope(
	ref(47) if(FLAT) // test if on water
	ref(48) if(WEST+SOUTH, NORTH+EAST) // in x: back + front
	DISALLOW else
)

def(51) callback(
	ref(49) if(CB_SLOPE) // check slope
	ref(30) else 	     // icon graphics
)

CB_TEXT - additional text in purchase menu

This callback is called when TTDPatch displays the stats of an object in the purchase menu. The return value is a grftext(), previously defined by defgrftxt(), to be shown below all other stats. The callback is always used when defined, it needs not to be defined by property function callbacks() in the object definition stage.

How many lines of text are available depends on the type of object and its other properties. Lines are wrapped automatically, or may be broken explicitly using the newline character CRLF.

If cargo MENU is handled explicitly for an object, then it must be used in the function chain for the purchase menu, not for the object graphics.

Example (Additional text in purchase menu):
deftxt(warn_coast,
	US, T_BLACK "Mole with stairs cannot be built on coast tiles.",

...

	RUS, UTF8 T_BLACK "Волнорез с лестницей не может быть построен на берегу."
)

def(62) callback(
	reftxtcb(warn_coast) if(CB_TEXT)
	ref(61) else
)