7.1. Entity properties
Almost all MESS scripting occurs within entity properties. The most basic form of scripting is to reference parent entity properties. There are also several special properties that trigger specific MESS behavior, and it's possible to do things like turning one property into multiple properties with scripting.
- 7.1.1. Parent entity properties
- 7.1.2. Special properties
- 7.1.3. Lifted properties
- 7.1.4. Array property keys
- 7.1.5. Empty property keys
7.1.1. Parent entity properties
When a macro entity such as macro_insert
or macro_cover
creates an instance of a template (either a macro_template
or a separate map file), all of its properties can be referenced inside that template.
Templates (macro_template
entities and separate maps) can also have their own properties. These properties can reference parent entity properties, and can themselves be referenced by entities inside the current template. This makes for a good place to initialize common variables, or to set default values for required properties.
Take, for example, the following macro_insert
:
key | value |
---|---|
classname | macro_insert |
targetname | key1 |
template_name | key_template |
color | 255 255 0 |
and the macro_template
that it references:
key | value |
---|---|
classname | macro_template |
targetname | key_template |
color | {color or [255, 255, 255]} |
and finally, an entity inside that template:
key | value |
---|---|
classname | func_wall_toggle |
targetname | {id()} |
rendercolor | {color} |
When the macro_insert
entity is processed, first any expressions in its properties are evaluated. In this case, there are none, so MESS will quickly proceed.
Next, any expressions in the properties of the chosen macro_template
are evaluated (or, if a separate map is used via template_map
, any expressions in the properties of that map). Here, the value of color
consists of the expression {color or [255, 255, 255]}
. This is a common mechanism to provide a default value. It references the color
property of the instance-creating entity, which contains the value 255 255 0
. If the macro_insert
didn't contain a color
property, or if it was empty, then the or [255, 255, 255]
part would ensure a default color of 255 255 255
.
Note that the classname
, targetname
, selection_weight
and anchor
properties of a macro_template
are silently removed, to prevent them from hiding important parent entity properties - specifically the targetname
.
Finally, any expressions in entities inside the template are evaluated. The func_wall_toggle
's targetname
contains the expression {id()}
. This calls the id()
function, which returns either the targetname
of the parent macro entity, or the unique numeric ID of the current instance.
The rendercolor
property references the color
property. Both the macro_insert
and the macro_template
contain a color
property. In that case, the value of the macro_template
's color
property is used - it's essentially hiding macro_insert
's color
property.
7.1.2. Special properties
The following properties can be added to entities to trigger special behavior in MESS. This includes setting spawnflags on the current entity, removing the entity, merging it with others, or inserting a template map at the entity's position:
- _mess_spawnflagN
- _mess_merge_entity_id
- _mess_merge_entity_master
- _mess_remove_if
- _mess_attached_template_map
- _mess_attached_template_name
- _mess_allow_rewrite_rules
- _mess_deny_rewrite_rules
- _mess_replace_texture
_mess_spawnflagN
This set of properties can be used to enable or disable a specific spawn flag with MScript. These properties are removed from the entity after the spawnflag property has been updated. The first spawnflag has number 0, the last has number 31.
If a _mess_spawnflagN
value is empty or 0
, then the corresponding spawn flag will be disabled. Else, it will be enabled. For example, the following entity:
key | value |
---|---|
classname | env_beam |
_mess_spawnflag0 | {start_on} |
_mess_spawnflag2 | {enable_random_strike_time} |
will have its first spawn flag enabled if start_on
is true, and it will have its third spawn flag enabled if enable_random_strike_time
is true. This would be the resulting entity if both are true:
key | value |
---|---|
classname | env_beam |
spawnflags | 5 |
_mess_merge_entity_id
This property is used to merge brush entities together, which can be useful for certain optimization techniques. Merging happens after post-processing rewrite rules have been applied.
Entities that contain a _mess_merge_entity_id
property are grouped by their _mess_merge_entity_id
value. Each group is turned into a single entity. The resulting entity will have the properties of the first entity of that group (or the first entity that is marked as a master, see the _mess_merge_entity_master
property below), and it will contain the brushes of all entities of that group. The resulting entity will not contain a _mess_merge_entity_id
or _mess_merge_entity_master
property.
It is recommended to only merge entities of the same type and with the same properties.
For example, the following two entities will be merged into a single one. Because none of them has been marked as a master, the resulting entity will use the properties of the first entity and so its targetname will be fence1
:
key | value |
---|---|
classname | func_wall |
targetname | fence1 |
_mess_merge_entity_id | outer_fence |
key | value |
---|---|
classname | func_wall |
targetname | fence2 |
_mess_merge_entity_id | outer_fence |
_mess_merge_entity_master
An entity that contains this property will be marked as a master if the value of this property is true (any value other than leaving it empty or setting it to 0
). When merging entities (see the above _mess_merge_entity_id
property), the resulting entity will get the properties of the first master entity in that group.
For example, the following entity is the master of the courtyard_grass
group, and the resulting entity will get the properties of this entity (minus the _mess_merge_entity_id
and _mess_merge_entity_master
properties):
key | value |
---|---|
classname | func_illusionary |
_mess_merge_entity_id | courtyard_grass |
_mess_merge_entity_master | 1 |
_mess_remove_if
Entities that contain this property will be removed if the value of this property is true (which is any value other than leaving it empty or setting it to 0
). If the entity is part of a template, then the value will be re-evaluated for every instance. This is similar to surrounding the entity with a macro_remove_if. This property is removed from the entity afterwards.
For example, the following entity will be removed if the global variable DEBUG
exists and if its value is not none
or 0
:
key | value |
---|---|
classname | func_wall |
_mess_remove_if | {getglobal('DEBUG')} |
_mess_attached_template_map
Adding this property to a normal (non-macro) entity will insert the specified template map (or maps) at the position of that entity. This property is then removed from the entity. This also works for the special worldspawn
entity - adding a _mess_attached_template_map
property to the properties of a map will insert the specified map(s) at the center of the current map.
For brush entities that contain an ORIGIN
brush, the maps will be inserted at the center of that ORIGIN
brush. For brush entities without an ORIGIN
brush, the center of their bounding box will be used instead.
The current entity will behave as a macro entity, in the sense that all of its properties will be available inside the selected template map(s).
When inserting multiple maps, their paths must be separated by a comma (,
). Relative paths are taken to be relative to the templates directory, or relative to the current map when used inside a template map. For paths that contain comma's, use a double comma escape sequence: a, b and c.map
is interpreted as two paths (a
and b and c.map
), whereas a,, b and c.map
is interpreted as a single path (a, b and c.map
).
key | value |
---|---|
classname | worldspawn |
_mess_attached_template_map | TODO.map,TODO2.map |
_mess_attached_template_name
This property is similar to _mess_attached_template_map
, except that it inserts one or more local templates at the position of the entity that contains this property. The same positioning rules apply for brush entities and for inserting multiple templates.
_mess_allow_rewrite_rules
Adding this property to a (template) map will block rewrite directives from all .ted files, except for the paths listed in this property. Paths can cover specific files or entire directories, and do not need to contain a .ted extension. This property is removed afterwards.
Relative paths are relative to the directory that contains the current (template) map. Multiple paths must be separated by comma's (,
). Use the ted_path(relative_path)
function to reference .ted files from other template entity directories.
This is a specific property that is intended for template entity authors. A common use-case is to disallow rewrite rules from all .ted files by setting an empty value:
key | value |
---|---|
classname | worldspawn |
_mess_allow_rewrite_rules | {} |
Some editors will remove custom properties if their value is empty, hence the use of {}
- an MScript expression that evaluates to an empty string.
_mess_deny_rewrite_rules
Adding this property to a (template) map will block rewrite directives from the .ted file paths listed in this property. Paths can cover specific files or entire directories, and do not need to contain a .ted extension. This property is removed afterwards.
Relative paths are relative to the directory that contains the current (template) map. Multiple paths must be separated by comma's (,
). Use the ted_path(relative_path)
function to reference .ted files from other template entity directories.
This is a specific property that is intended for template entity authors. For example, this blocks the rewrite rule that enables target patterns:
key | value |
---|---|
classname | worldspawn |
_mess_deny_rewrite_rules | {ted_path('target_pattern_handler.ted')} |
_mess_replace_texture
This is a set of properties that can be used to replace textures on a brush entity. As with all the other special properties, they are removed from an entity after any textures have been replaced.
There are several ways to use this property. The most basic usage is as following:
key | value |
---|---|
classname | func_wall |
_mess_replace_texture redwall | bluewall |
_mess_replace_texture redfloor | bluefloor |
_mess_replace_texture | null |
This will replace the 'redwall' texture with 'bluewall', the 'redfloor' texture with 'bluefloor', and any other texture with 'null'. If the last property was left out, then only the 'redwall' and 'redfloor' textures would be replaced - any other textures would remain unchanged. Note that texture name comparisons are case-insensitive, so 'redwall' also matches 'REDWALL' and 'REDwall'.
An alternative to the above is to use a single MScript object that contains multiple replacement rules. For example, this achieves the same as the previous set of properties:
key | value |
---|---|
classname | func_wall |
_mess_replace_texture | {{redwall: 'bluewall', redfloor: 'bluefloor', '': 'null'}} |
Finally, it's also possible to use an MScript function to decides which textures to replace:
key | value |
---|---|
classname | func_wall |
_mess_replace_texture | {name => name.contains('red') ? name.replace('red', 'blue') : name.contains('grey') ? 'null' : ''} |
This replaces any texture whose name contains 'red' by replacing the 'red' in their name with 'blue', so not only does it replace 'redwall' with 'bluewall' and 'redfloor' with 'bluefloor', it also replaces 'redceiling' with 'blueceiling' and 'credit' with 'cbluedit'. Any texture that does not contain 'red' but does contain 'grey' will be replaced with 'null', and any other textures are left unchanged.
MScript string comparisons are case-sensitive by default, so to avoid problems, texture names are converted to lowercase before being passed into the replacement function.
7.1.3. Lifted properties
Normally, expressions in properties can only reference properties from their parent entity, but in some cases it's useful to reference properties from the same entity. One particular case is with TrenchBroom linked groups: by default, all copies of a linked group will have the same entity properties, so if a linked group contains a button and a door that is opened by that button, then pressing a button in any of the copies will open the doors in all copies.
Properties in linked group copies can be overridden, but that is somewhat tedious and easily forgotten. Instead, we can tell MESS to lift the special _tb_group
property that gets added to entities that are part of a linked group. This property contains a number that is unique for every linked group copy. With this, a linked group that contains the following entities:
key | value |
---|---|
classname | func_button |
target | door{_tb_group} |
key | value |
---|---|
classname | func_door |
targetname | door{_tb_group} |
will, when two copies of the group are made, produce the following entities:
key | value |
---|---|
classname | func_button |
target | door1 |
key | value |
---|---|
classname | func_door |
targetname | door1 |
and:
key | value |
---|---|
classname | func_button |
target | door2 |
key | value |
---|---|
classname | func_door |
targetname | door2 |
The exact numbers will vary depending on how many other linked groups the map contains, but the point is that each copy now automatically gets unique entity names. In this case that means that a button from one copy will only open the door from that copy, instead of all doors.
See also: configuration file: lifted-properties and Creating interactive linked groups in TrenchBroom.
7.1.4. Array property keys
If a property key consists of a single MScript expression that returns an array, then MESS will turn that property into multiple properties, one for every value in that array. The property value should also produce an array of equal length, so each property can be given a specific value. If the property value array is too short, then the value for the last few properties will be empty.
For example, an entity with the following properties:
key | value |
---|---|
classname | multi_manager |
{['a', 'b', 'c']} | {[1, 2, 3]} |
will, after processing, contain these properties:
key | value |
---|---|
classname | multi_manager |
a | 1 |
b | 2 |
c | 3 |
This can be particularly useful when combined with array functions. For example, the following entity:
key | value |
---|---|
classname | mtl_trigger_random |
{range(0, 5).map(n => 'target' + n)} | {repeat(8, 2).concat(repeat(10, 3))} |
will become:
key | value |
---|---|
classname | mtl_trigger_random |
target0 | 8 |
target1 | 8 |
target2 | 10 |
target3 | 10 |
target4 | 10 |
It's also possible to copy properties from a parent entity, by using the parent entity property functions (a parent entity is the macro entity that is creating an instance of the current template):
key | value |
---|---|
classname | multi_manager |
{get_attr().map(a => a.key)} | {get_attr().map(a => a.value)} |
This will copy all parent entity properties, including standard properties like classname
, origin
, targetname
, and so on. In practice, certain properties will need to be excluded. This can be done with the filter
function. Because both the key and value array must be filtered, it's better to do this in a template property, so the filter doesn't need to be repeated.
7.1.5. Empty property keys
If, after evaluating MScript expressions, a property key is empty, MESS will remove that property. In this case, any MScript expressions in its value will not be evaluated.
In the following example entity, all keys except classname
end up being empty:
key | value |
---|---|
classname | trigger_relay |
{} | empty |
{''} | also empty |
{1 == 0 ? 'killtarget' : ''} | conditionally empty |
So the resulting entity will only contain the classname
property:
key | value |
---|---|
classname | trigger_relay |
The last property shows how the ?:
conditional operator can be used to exclude properties based on certain conditions. For example, a trigger_relay
entity only needs a killtarget
property if it needs to kill another entity.