From FilterWML, this is the standard way of filtering on locations. The term StandardLocationFilter means that the set of such keys and tags (see below) can appear at that point. Sometimes a StandardLocationFilter needs to be included in a [filter_location] tag. There are however many tags which accept the StandardLocationFilter directly as an argument such as [store_locations]. Generally, if the tag [filter_location] is not mentioned to be a possible subtag of the outer tag in question, then don't put it.
The following attributes and sub-tags are permitted:
- time_of_day: filter matches only on a given time of day (one of lawful, chaotic, or neutral). Note: chaotic, lawful, and neutral; these are not times of day, these are alignments. To match against 'dawn', 'dusk', 'first watch' etc., use the time_of_day_id key described below.
- time_of_day_id: this accepts a list of one or more actual times of day, separated by commas. These IDs are taken from data/core/macros/schedules.cfg. Permissible values are case-sensitive: dawn, morning, afternoon, dusk, first_watch, second_watch, indoors, underground and deep_underground.
- terrain: comma separated list of terrains. (See also: Filtering Terrains).
- x,y: the same as in the unit filter; supports any range (notes)
- location_id: (Version 1.13.? and later only) Matches a special location set in the map. This can also be a side number to match that side's starting location. Note: this does not accept a comma separated list, one has to use [or] tags. (Version 1.15.0 and later only) Accepts a comma separated list.
- area: matches locations assigned to the [time_area] with the given id.
- include_borders: (Version 1.13.0 and later only) whether the SLF will include border hexes or not. Will override the default behavior of the tag this appears in.
- [filter] with a StandardUnitFilter as argument; if present a unit must also be there
- owner_side: If a valid side number, restricts stored locations to villages belonging to this side. If 0, restricts to all unowned locations (the whole map except villages which belong to some valid side). A hex is considered a village if and only if its [ terrain_type ]gives_income= parameter was set to yes (which means a side can own that hex).
- [filter_vision]: this tests whether or not the location is currently visible
- visible: yes or no, default yes. "yes" filters for visible locations, "no" filters for invisible locations.
- respect_fog: yes or no, default yes. "yes" filters for locations that are clear of both fog and shroud, "no" filters for locations that are clear of shroud.
- StandardSideFilter tags and keys as arguments. If there is *at least one* matching side which can see the location then the filter matches, and otherwise it fails to match.
- [filter_owner]: If present, inline owner_side= is ignored. Restricts stored locations to villages, each of which must belong to any of the matching sides. If no sides match, restricts to unowned villages (and only these).
- StandardSideFilter tags and keys as arguments
- find_in: name of an array or container variable; if present, the location will not match unless it is also found stored in the variable
- radius: matches if any location within the radius matches this filter (notes)
- [filter_radius]: a standard location filter; normally the radius extends outwards from matching locations one step at a time without checking any additional information-- however, if this tag is present, the radius will be restricted so that it can only expand outwards in the directions where it passes the given location filter
- [and]: an extra location filter. Unless a location matches the [and] filter, then it will be excluded. Note: [and],[or],and [not] extra location filters are considered after everything else in the containing filter (except radius, which is considered last in 1.3.8 and greater); they are then processed in the order encountered.
- [or]: an extra location filter. If a location matches the [or] filter, then it will count as a match regardless of conditions in previous filters or the containing filter.
- [not]: an extra location filter. If a location matches the [not] filter, then that location will be excluded.
- [filter_adjacent_location]: a standard location filter; if present the correct number of adjacent locations must match this filter
- count: a number, range, or comma separated range; default "1-6"
- adjacent: a comma separated list of directions; default "n,ne,se,s,sw,nw" (see notes)
- formula: (Version 1.13.5 and later only) a Wesnoth Formula Language formula. Some terrain-specific variables, for example "light" and "castle", can be used in the filter (see list below).
- lua_function: (Version 1.13.5 and later only) the name of a Lua function in the global environment that takes arguments
x, yand returns true if the given location matches the filter. Non-global functions can now be used here by building a dot-separated "path". Note that this is not actually interpreted as Lua code even though it superficially resembles it, so using a Lua keyword in the path will work, for example "my_filter_functions.goto" will correctly use the function which in actual Lua code would need to be referenced as
Notes about Coordinate Usage
When specifying coordinates, the following keys are used:
- x: the first coordinate
- y: the second coordinate
While some locations should only be one hex (like the starting position of a unit), others filter over multiple hexes. The following syntax is used to filter over multiple hexes:
Dashes(-) are used to have the location be a range of hexes. There must be values before and after the dash; everything in between these numbers (inclusively) is part of the range.
Commas(,) are used to separate coordinates into a list. The x and y lists are then paired up, with each pair representing one hex or range. E.g. in order to specify multiple locations 1,4 and 2,5, use:
[tag] x=1,2 y=4,5 [/tag]
You should have the same number of commas in each list, and both x and y are always lists. For example, this does not mean the locations (1,4) and (2,4):
[tag] x=1,2 y=4 # bad example, implementation-defined behavior [/tag]
A pair can have a single value for one coordinate and a range for the other. This matches (1,4) and the entire column from (2,1) downwards:
[tag] x=1, 2 y=4,1-999 [/tag]
Providing only x or only y is valid. This matches the entire columns from (1,1) and (2,1) downwards:
[tag] x=1,2 [/tag]
Note: although the ordering of locations in a list generally does not matter, the action [move_unit_fake] takes in a list of hexes, and moves an image onto each of those hexes in order.
Notes about Radius Usage
If you aren't storing any locations successfully, it may be because you put the radius or filters in the wrong place for them to combine correctly.
[have_location] terrain=Gg^Vh [and] x=$x1 y=$y1 radius=1 [/and] [/have_location]
Note that the use of [and] here causes the radius to have a very different meaning. Normally, all of the criteria besides radius are checked, producing a set of hexes to which the radius is applied. This means, for example, that if you're trying to find "a hex without a unit on it within 5 hexes of (15, 23)", the code:
[have_location] x,y=15,23 radius=5 # oops... this time it won't work as expected [not] [filter] [/filter] [/not] [have_location]
will not work! First, it looks for a hex with x=15, y=23 without a unit on it. Then, it returns that hex and all hexes within 5 of it. If (15, 23) happens to be occupied, then it will return no hexes, because "all hexes within 5 hexes of (no hexes)" is still "no hexes". Instead, put an [and] around the x,y and radius requirements, and it will separately find "(15, 23) and all hexes within 5 of it" and "each of those hexes that doesn't have a unit on it", producing the desired result.
Some attributes expect a direction or list of directions. Valid base directions are n, ne, nw, s, se, sw, and there are three operators supported as well:
- To take the opposite direction, use - (eg -n is the same as s)
- (Version 1.13.2 and later only) To rotate clockwise, use :cw (eg n:cw is the same as ne)
- (Version 1.13.2 and later only) To rotate counterclockwise, use :ccw (eg n:ccw is the same as nw)
You can't apply multiple rotation operators - for example, "n:cw:ccw" is not a valid direction. If for some reason you really need multiple rotations, you can use parentheses (so, "(n:cw):ccw" is valid and is the same as n). Similarly, "--n" is not valid, but "-(-n)" is valid and is the same as n.
This syntax is mainly useful when used in conjunction with variable substitution in the adjacent key in [filter_adjacent_location] and in [filter_adjacent] (in StandardUnitFilter), but will work anywhere a direction is expected. For example, using [modify_unit] to change a unit's direction:
[modify_unit] [filter] # ... Whatever filter you need [/filter] facing=-$this_unit.facing [/modify_unit]
That will cause the matched units to turn around.
The terrain= key allows you to filter based on the terrain of a space, for example:
[event] [filter] [filter_location] terrain=Ch [/filter_location] [/filter] [/event]
At some places the terrains can be filtered with a match list. This list is a comma separated list of terrain strings and patterns which will be processed in order. As soon as a pattern matching the reference terrain is found, the result of the filter will be determined.
Normally, if one of the patterns matches, the filter is considered successful. However, the special pattern ! inverts this every time it is encountered – when inverted, the filter is considered unsuccessful when one of the patterns matches. In other words, Gg matches only basic grass, while !,Gg matches anything but basic grass.
When the end of the list is reached without any matches, normally the result is an unsuccessful match. However, if the match is currently inverted, ie there are an odd number of !, then the result is a successful match.
An individual terrain pattern consists of two parts, the base and the overlay, separated by the ^ character. The overlay (including the preceding ^) is optional; if omitted, only terrains without overlays can be matched. The pattern may end with the wildcard character * (or be composed solely of the wildcard character). The pattern to match any terrain is *^*.
ww* matches ww, www, wwW but not WWW
!, ww returns false if ww found and true if not
!, ww, wa, !, aa returns false if ww or wa found and true if aa found and false if none found.
*^V* matches all village-terrain
Notice how the * can be used separately for both layers (base and overlay layers are separated by the ^-character).
For a list of terrain types and their string codes see TerrainCodesWML.
Wesnoth Formula Language
When using SLF's formula attribute, the context object is a terrain hex object with the following properties:
- x, y, loc: the latter is a location object such as what would be returned by loc().
- village: a boolean containing the value of [terrain_type]gives_income=
- healing: an integer containing the value of [terrain_type]heals=
For an up-to-date list, check the C++ function terrain_callable::get_value(const std::string& key) const.