7.5. Template functions

The following functions are available inside entity properties:

7.5.1. Instance ID

When creating multiple instances of the same template, entities in different instances often need to have distinct names. For example, a landmine template that contains a trigger_once and an env_explosion should produce triggers that only activate the explosion of the current landmine, not the explosions of all landmines.


string id()

Returns the targetname of the macro entity that is creating the current instance, or the unique ID of the current instance if the targetname is empty. The return value is always a string.

For example, if a macro_insert with the name fire1 is creating an instance of a template, and that template contains an env_beam entity with the name {id()}_beam, then the resulting instance will have an env_beam entity with the name fire1_beam.


number iid()

Returns the unique ID of the current instance, as a number.

For example, if a macro entity creates an instance of a template that contains a func_button entity with the name btn_{iid()}, and the current instance ID happens to be 15, then the resulting func_button will have the name btn_15.


number parentid()

Returns the unique ID of the macro entity that is creating the current instance. This ID is not related to instance IDs.

For example, if a macro_insert or a macro_cover creates multiple instances of a template, and that template contains an env_sprite with the name spr_{parentid()}, and the unique ID of that macro entity happens to be 20, then the resulting sprites will all have the same name: spr_20.


number nth()

Returns the sequence number of the current instance. The first instance that is created by a macro entity has sequence number 0. The second instance created by that same macro entity has sequence number 1, and so on.

For example, if a macro_insert with an instance_count of 5 creates instances of a template that contains an env_sprite entity with the name spr_{nth()}, then the result will be 5 env_sprite entities named spr_0, spr_1, spr_2, spr_3 and spr_4 respectively.

This function can also be used in the macro entity itself: setting the instance_offset property of the above macro_insert to {nth() * 32} 0 0 will put each subsequent instance 32 units to the right of the previous instance.


7.5.2. Randomness

An easy way to add variety is to use randomness. For example, randomizing the angles and scale of props can help to make them look less repetitive.

Randomness in MESS is determistic, which means that compiling the exact same map will always produce the same output. Random numbers are affected by the random_seed property of the current instance-creating macro entity - the same seed will always produce the same sequence of numbers.


number rand()
number rand(number max)
number rand(number min, number max)
number rand(number min, number max, number step)

Returns a random floating-point number. When called without arguments, the result will be a number between 0.0 and 1.0 (exclusive). When called with a single argument, the result will lie between 0.0 and the given number. When called with two arguments, the result will lie between the given numbers. Optionally, a third argument can be given, which controls the difference between each consecutive number that can be returned.

The lower bound is inclusive, the upper bound is exclusive.

For example:

  • rand(5) will return a random number between 0 and 5 (but not exactly 5)
  • rand(2, 4) will return a random number between 2 and 4 (but not exactly 2)
  • rand(0, 2, 0.5) will return either 0, 0.5, 1 or 1.5 (but not 2)

number randi()
number randi(number max)
number randi(number min, number max)
number randi(number min, number max, number step)

randi (short for 'random integer') returns a pseudo-random integer number. When called without arguments, the result is either 0 or 1. When called with a single argument, the result will lie between 0 and the given number. When called with two arguments, the result will lie between the given numbers. Optionally, a third argument can be given, which controls the difference between each consecutive number that can be returned.

The lower bound is inclusive, the upper bound is exclusive.

For example:

  • randi(10) will return a random integer number between 0 (included) and 10 (excluded)
  • randi(5, 15) will return a random integer number between 5 (included) and 15 (excluded)
  • randi(0, 15, 3) will return either 0, 3, 6, 9 or 12 (but not 15)

any randitem(array items)
any randitem(array items, array weights)

Returns a randomly selected item from the given array.

Optionally, an array of weights can be provided, which determines how likely each item is to be chosen. Weights must be numbers larger than or equal to 0. Missing weights - if the weights array is shorter than the items array - and invalid weights are treated as 0, meaning that their corresponding items won't be selected. If no item has a weight above 0 then none will be returned.

For example, randitem([10, 20, 30]) will return either 10, 20 or 30, all with an equal chance. randitem(['a', 'b', 'c'], [5, 2, 1]) will return either 'a' (5/8 chance), 'b' (2/8 chance) or 'c' (1/8 chance).


7.5.3. Parent entity properties

Some entities rely on custom properties. For example, multi_manager uses custom properties for its list of targets. The properties of the macro entity that is creating the current instance are available to scripts inside a template, but that is of little use if the property names aren't known up-front. The below functions provide a list of properties, and access to specific properties regardless of their name.

The opposite - adding a variable number of properties to an entity - can be done with arrays. An entity property whose name consists of a single MScript expression that returns an array will be turned into multiple properties. The property value should also be a single MScript expression that returns an array, so that each property can be given a value.

For example, a property with the name {['a', 'b', 'c']} and a value of {range(1, 4)} (an expression that returns the array [1, 2, 3]) will be turned into 3 separate properties: a with value 1, b with value 2 and c with value 3.


number attr_count()

Returns the number of properties of the parent entity. This only includes the properties that are visible when SmartEdit mode is disabled, and 'special' properties like classname and origin.

For example, if a macro entity creates an instance of a template that contains a game_text entity with a message of Count: {attr_count()}, and the macro entity contains 5 properties, then the resulting game_text will have a message of Count: 5.


array get_attr()
object|none get_attr(number index)
object|none get_attr(string name)

Returns parent entity properties. Each property is returned as a {key: string, value: any} object. When called without arguments, the result is an array that contains all parent entity properties. When called with a number, the property at that index is returned as a single key-value object, or none if the index is out of range (negative indexes are supported). When called with a string, the property with that name is returned, or none if there is no such property.

For example, get_attr() may return an array like [{key: 'classname', value: 'macro_insert'}, {key: 'origin', value: [256, 64, 576]}, {key: 'template_name', value: ''}] - or an array with many more properties, depending on how many properties the parent entity contains.

In the above situation, get_attr(0) would return {key: 'classname', value: 'macro_insert'}, and get_attr('origin'} would return {key: 'origin', value: [256, 64, 576]}.


7.5.4. Spawnflags

The special spawnflags property contains all the flags of an entity. Its value is the sum of the values of the enabled flags. The first flag has value 1, and each subsequent flag's value is double that of the previous flag: 1, 2, 4, 8, 16, and so on.

Because this property can only be adjusted via checkboxes, its value cannot be directly controlled with scripting. That is why MESS recognizes special _mess_spawnflagN properties, where N is a number from 0 to 31, to set specific flags. These special properties are removed after the spawnflags property has been updated.


bool hasflag(number flag)
bool hasflag(number flag, number flags)

Returns 1 (true) if the specified flag is enabled in the given flags value. If the flags argument is not specified, then this will check the spawnflags property of the parent entity. flag must be a number between 0 and 31 (inclusive).

For example, hasflag(0) will return 1 if the first flag of the parent entity is enabled.


number setflag(number flag)
number setflag(number flag, number set)
number setflag(number flag, number set, number flags)

Returns a new flags value, which is the given flags value (or the parent entity's spawnflags value) with the specified flag enabled or disabled.

For example, setflag(2, 1) will return the parent entity's spawnflags value, but with the third flag enabled.


7.5.5. Directories

There are several directories of importance when MESS is processing a map:

  • The MESS executable directory, which contains the default mess.config file.
  • The templates directory, which contains (standard) template entity maps. Any relative template map path is relative to this directory.
  • The directory where the current map file is located.

It is often not necessary to reference these directories in scripts, but they are available via the following functions just in case.


string map_path()

Returns the path of the current map file. When used inside a template map, the path of that template map is returned, not the path of the 'main' map that is being processed.

For example, map_path() may return something like 'C:\HL\my maps\test.map'.


string map_dir()

Returns the directory that the current map file is in. When used inside a template map, the directory of that template map is returned, not the directory of the 'main' map that is being processed.

For example, map_dir() may return something like 'C:\HL\my maps'.


string templates_dir()

Returns the templates directory. By default, this is the templates folder next to MESS.exe, but it can also be set explicitly in the config file or via a command-line option.

For example, templates_dir() may return something like 'C:\HL\Tools\MESS\templates'.


string mess_dir()

Returns the directory that MESS.exe is in.

For example, mess_dir() may return something like 'C:\HL\Tools\MESS'.


7.5.6. Globals

Sometimes it's useful to share information between entities across multiple template instances. This can be useful for templates that contain parts that only need to be inserted once, or for keeping track of how many times a certain template has been instantiated so far, or for controlling the behavior of certain templates via a config file.


any getglobal(string name)

Returns the value of the specified global variable, or none if it does not exist.

For example, getglobal('landmine_count') may return 5, depending on what value was set previously.


any setglobal(string name, any value)

Sets the value of the specified global variable, and returns that value.

For example, setglobal('landmine_count', 9) will set the global variable landmine_count to 9, and it will then return 9.


bool useglobal(string name)

If the specified global variable does not yet exist (or if it has a none value), then this function will set it to 1, and return none to indicate that the variable was not set already. Otherwise, it will return 1.

For example, useglobal('landmine_brush_model') will return none the first time it is called, and it will return 1 on subsequent calls. This is useful for templates that contain content that does not need to be duplicated for each instance.


7.5.7. Debugging

Sometimes a script or a template doesn't work as expected. In that case it can be helpful to see the values of specific properties.


any trace(any value)
any trace(any value, string message)

Writes the given value and an optional message to the log file, and returns the given value. This can be useful for tracking down problems in scripts and templates.

For example, trace(targetname, 'Landmine name') may write something like 'mine1' ('Landmine name', trace from instance: #14, sequence number: #0). to the log file, and return mine1, if the targetname of the parent entity is mine1. Because the given value is also returned, a trace call does not change how a piece of script works.