Difference between revisions of "ConditionalActionsWML"

From The Battle for Wesnoth Wiki
(Meta Condition Tags)
(Link to the redirect instead of the section (so it still works if we ever make it not a redirect anymore))
 
(66 intermediate revisions by 14 users not shown)
Line 15: Line 15:
 
* '''[then]''': Contains [[ActionWML|actions]] which should be executed if all conditions evaluate as true ''or'' if any single '''[or]''' tag evaluates as true.
 
* '''[then]''': Contains [[ActionWML|actions]] which should be executed if all conditions evaluate as true ''or'' if any single '''[or]''' tag evaluates as true.
  
* '''[else]''': Contains [[ActionWML|actions]] which should be executed if any condition evaluates as false ''and'' '''all''' of the '''[or]''' tags evaluate as false.
+
* '''[elseif]''': {{DevFeature1.13|0}} in case that the conditions inside '''[if]''' aren't met, these tags will be evalutated one by one. If the specified conditions are met, the contained [then] tags will be executed, and the cycle will end.
 +
** [[#Condition Tags|Condition Tags]]: Specifies the conditions, just like in '''[if]'''.
 +
** '''[then]''': Specifies actions, exactly like the '''[then]''' tag inside '''[if]'''.
 +
 
 +
* '''[else]''': Contains [[ActionWML|actions]] which should be executed if all condition tags in the '''[if]''' and any directly nested '''[elseif]''' all evaluate as false.
  
  
 
'''Attention''': There are tags named [if] and [else] inside [animation] (see [[AnimationWML#.5Bif.5D_and_.5Belse.5D|AnimationWML]]), which have a different syntax.
 
'''Attention''': There are tags named [if] and [else] inside [animation] (see [[AnimationWML#.5Bif.5D_and_.5Belse.5D|AnimationWML]]), which have a different syntax.
 +
 +
Example usage:
 +
<syntaxhighlight lang=wml>
 +
[if]
 +
  [variable]
 +
      name=we.gold
 +
      greater_than=$they.gold
 +
  [/variable]
 +
  [elseif]
 +
      [variable]
 +
        name=we.gold
 +
        equals=$they.gold
 +
      [/variable]
 +
      [then]
 +
        [message]
 +
            message=This should be fair!
 +
        [/message]
 +
      [/then]
 +
  [/elseif]
 +
  [else]
 +
      [message]
 +
        message=This will not be easy!
 +
      [/message]
 +
  [/else]
 +
[/if]
 +
</syntaxhighlight>
  
 
=== [switch] ===
 
=== [switch] ===
  
The '''[switch]''' tag is a special case because it does not use [[#Condition Tags|Condition Tags]] to control whether actions are performed. Instead, it executes different sets of actions based on the value of a variable.
+
The '''[switch]''' tag is a special case because it does not use [[#Condition Tags|Condition Tags]] to control whether actions are performed. Instead, it executes different sets of actions based on the value of a variable
  
 
* '''variable''': The name of the variable to check.
 
* '''variable''': The name of the variable to check.
 
* '''[case]''': Case tag which forms a block containing:
 
* '''[case]''': Case tag which forms a block containing:
** '''value''': The value to test the variable's value against.  
+
** '''value''': The value to test the variable's value against. This can be a comma separated list of values.
This can be a comma separated list of values.
 
 
** [[ActionWML|Action WML]]: Action WML to execute if the variable matches the value. (The rest of the '''[case]''' block after the '''value''' attribute.)
 
** [[ActionWML|Action WML]]: Action WML to execute if the variable matches the value. (The rest of the '''[case]''' block after the '''value''' attribute.)
 
* '''[else]''': Else tag which forms a block of [[ActionWML|Action WML]] to execute if no '''[case]''' block contains a '''value''' matching the value of the '''variable'''.
 
* '''[else]''': Else tag which forms a block of [[ActionWML|Action WML]] to execute if no '''[case]''' block contains a '''value''' matching the value of the '''variable'''.
  
 
Example usage:
 
Example usage:
  [switch]
+
<syntaxhighlight lang=wml>
    variable=foo
+
[switch]
    [case]
+
  variable=foo
        value="A"
+
  [case]
        ... WML if foo=A ...
+
      value="A"
    [/case]
+
      # ... WML if foo=A ...
    [case]
+
  [/case]
        value="B"
+
  [case]
        ... WML if foo=B ...
+
      value="B"
    [/case]
+
      # ... WML if foo=B ...
    [else]
+
  [/case]
        ... WML if not foo=A nor foo=B ...
+
  [else]
    [/else]
+
      # ... WML if not foo=A nor foo=B ...
  [/switch]
+
  [/else]
 +
[/switch]
 +
</syntaxhighlight>
  
 
=== [while] ===
 
=== [while] ===
Line 53: Line 84:
 
* [[#Condition Tags|Condition Tags]]: Conditions which must be met for the actions in the '''[do]''' tag to be executed.
 
* [[#Condition Tags|Condition Tags]]: Conditions which must be met for the actions in the '''[do]''' tag to be executed.
  
* '''[do]''': contains [[ActionWML|actions]] that should be executed repeatedly until some condition is false.
+
* '''[do]''': contains [[ActionWML|actions]] that should be executed repeatedly until some condition is false. Multiple '''[do]''' tags can be used, and they will be executed in sequence on each iteration. However, there is usually no reason to do this.
  
 
The '''[while]''' tag is useful for iterating over an array.
 
The '''[while]''' tag is useful for iterating over an array.
Line 62: Line 93:
  
 
==== 'FOREACH' Macro ====
 
==== 'FOREACH' Macro ====
This macro simplifies the use of a '''[while]''' tag to create a ''for-each'' iteration format. This is useful, for example, when you want to iterate over each row in a table. To use it, use the [http://www.wesnoth.org/macro-reference.xhtml#FOREACH FOREACH] and [http://www.wesnoth.org/macro-reference.xhtml#NEXT NEXT] macros.
+
This macro simplifies the use of a '''[while]''' tag to create a ''for-each'' iteration format. This is useful, for example, when you want to iterate over each row in a table. To use it, use the [http://www.wesnoth.org/macro-reference.xhtml#FOREACH FOREACH] and [http://www.wesnoth.org/macro-reference.xhtml#NEXT NEXT] macros. Note: This macro is deprecated; you should just use the '''[foreach]''' WML tag instead.
  
 
==== 'REPEAT' Macro ====
 
==== 'REPEAT' Macro ====
 
This macro simplifies the use of a '''[while]''' tag to execute the same  [[ActionWML|actions]] repeatedly for a specified number of times. To use it, use the [http://www.wesnoth.org/macro-reference.xhtml#REPEAT REPEAT] macro.
 
This macro simplifies the use of a '''[while]''' tag to execute the same  [[ActionWML|actions]] repeatedly for a specified number of times. To use it, use the [http://www.wesnoth.org/macro-reference.xhtml#REPEAT REPEAT] macro.
 +
 +
=== [for] ===
 +
 +
{{DevFeature1.13|2}}
 +
 +
Loops over an integer range. Note that, if iterating over an array to delete several elements, it is best to use '''reverse=yes''' to avoid accidentally skipping some elements.
 +
 +
* '''variable''': The name of the variable containing the current index. Defaults to ''i''. If there is already a variable with this name, it will be automatically saved before the start of the loop, and reset to its previous value when the loop exits. If there wasn't a variable with that name before the loop, it will be automatically deleted, there is no need to do a '''[clear_variable]''' afterwards
 +
* '''start''': The index of the first element to loop over, and sets the starting value of '''variable'''.  Defaults to 0.
 +
* '''end''': The index of the final element to loop over, and sets the maximum allowed value of '''variable'''.  Defaults to '''start'''.
 +
* '''step''': The value added to the current value of '''variable''' after each iteration of the loop.  Defaults to 1 if '''start''' < '''end''', or -1 if '''start''' > '''end'''.
 +
** For example, if '''start=1''' and '''step=2''', then the value of '''variable''' for each iteration will be: 1, 3, 5, ...
 +
* '''array''': Specify an array to iterate over.  This is a shortcut for setting '''start=0''' and '''end=$($array_name.length-1)'''
 +
** If '''array''' is set, then '''start''', '''end''', and '''step''' are ignored.
 +
* '''reverse''': If set to '''yes''', and '''array''' was specified, then this is a shortcut for setting '''start=$($array_name.length-1)''' and '''end=0'''.
 +
* '''[do]''': The actions to execute on each iteration. As with '''[while]''', it is possible to use multiple '''[do]''' tags, but there is usually no reason to.
 +
 +
=== [foreach] ===
 +
 +
{{DevFeature1.13|2}}
 +
 +
Loops over an array variable. This is not used to implement the {FOREACH} macro because [foreach] doesn't support adding or removing elements while looping (and will usually raise an error), use '''[for]''' instead.
 +
 +
* '''array''': The array variable to loop over.
 +
* '''variable''': The name of a variable which refers to the current item. Defaults to ''this_item''. Any changes made to this variable will persist in the array after the loop has completed.
 +
* '''index_var''': The name of a variable which refers to the index of the current item. Defaults to ''i''. Note that this is just for information purposes and should not be used to access the array from within the loop (any such changes made will not persist).
 +
* '''readonly''': If set to yes, this prevents the array from being modified in any way during the loop. (It defaults to no.) That means that changes made through the '''variable''' will ''not'' persist. Changes made through the '''index_var''' will also not persist (as normal). In effect, the array is reverted to its original state once the loop exits.
 +
* '''[do]''': The actions to execute on each iteration. As with '''[while]''', it is possible to use multiple '''[do]''' tags, but there is usually no reason to.
 +
 +
The '''[foreach]''' tag simulates local-scoping of its index variables. If there was already a WML variable with the same name (by default ''i'' and ''this_item'' respectively), it will be automatically saved before the start of the '''[do]''', and reset to its previous value when the loop exits.  If there wasn't a variable with that name before the loop, there is no need to do a '''[clear_variable]''' afterwards.
 +
 +
It's possible to nest '''[foreach]''' loops, however 1.16 does not support using the same ''variable='' name for both loops ([https://github.com/wesnoth/wesnoth/issues/6305 issue 6305], fixed in {{DevFeature1.17|13}}).
 +
 +
=== [repeat] ===
 +
 +
{{DevFeature1.13|2}}
 +
 +
Repeats some actions a fixed number of times. This is a completely stateless loop - there's no way to know which iteration of the loop you're on. (If you need this, use '''[for]''' instead.)
 +
 +
* '''times''': The number of times to repeat the actions.
 +
* '''[do]''': The actions to repeat.  As with '''[while]''', it is possible to use multiple '''[do]''' tags, but there is usually no reason to.
  
 
=== [command] ===
 
=== [command] ===
Line 74: Line 146:
 
== Condition Tags ==
 
== Condition Tags ==
  
===True Condition Tags===
 
 
These tags describe conditions which must be met before an action can take place. Some or all of them are used in the various [[#Conditional Actions|Conditional Actions]].
 
These tags describe conditions which must be met before an action can take place. Some or all of them are used in the various [[#Conditional Actions|Conditional Actions]].
  
; [have_unit]
+
=== [true] ===
: A unit with greater than zero hit points matching this filter exists.
+
 
:* [[StandardUnitFilter]] '''*''': Selection criteria. Do not use a [filter] tag.
+
Represents a condition that always yields true. Takes no arguments.
:* '''count''': ''(Optional)'' If used, a number of units equal to the value must match the filter. Accepts a number, range, or comma separated range. If not used, the default value is "1-99999".
+
 
:* '''search_recall_list''': ''(Optional)'' If 'yes', search through recall list too. (Default is 'no')
+
=== [false] ===
 +
 
 +
Represents a condition that always yields false. Takes no arguments.
 +
 
 +
=== [have_unit] ===
 +
 
 +
A unit with greater than zero hit points matching this filter exists.
 +
 
 +
* [[StandardUnitFilter]] '''*''': Selection criteria. Do not use a [filter] tag.
 +
* '''count''': ''(Optional)'' If used, a number of units equal to the value must match the filter. Accepts a number, range, or comma separated range. If not used, the default value is "1-99999".
 +
* '''search_recall_list''': ''(Optional)'' If 'yes', search through recall list too. (Default is 'no')
 +
 
 +
=== [have_location] ===
 +
 
 +
A location matching this filter exists.
  
; [have_location]
+
* [[StandardLocationFilter]]: Selection criteria.
: A location matching this filter exists.
+
* '''count''': ''(Optional)'' If used, a number of locations equal to the value must match the filter. Accepts a number, range, or comma separated range. If not used, the default value is "1-99999".
:* [[StandardLocationFilter]]: Selection criteria.
+
 
:* '''count''': ''(Optional)'' If used, a number of locations equal to the value must match the filter. Accepts a number, range, or comma separated range. If not used, the default value is "1-99999".
+
=== [has_achievement] ===
 +
 
 +
{{DevFeature1.17|13}}
 +
 
 +
The specified achievement has been completed.
 +
 
 +
* '''content_for''': The [[AchievementsWML|[achievements_group]]] that this achievement is part of.
 +
* '''id''': The id of the achievement.
 +
 
 +
'''NOTE:''' This is not safe to use in online multiplayer since different players can have different achievements completed. As such it will always be treated as if the achievement is not completed.
 +
 
 +
=== [has_sub_achievement] ===
 +
 
 +
{{DevFeature1.17|17}}
 +
 
 +
The specified achievement has been completed.
 +
 
 +
* '''content_for''': The [[AchievementsWML|[achievements_group]]] that this achievement is part of.
 +
* '''id''': The id of the achievement.
 +
* '''sub_id''': The id of the sub-achievement.
 +
 
 +
'''NOTE:''' This is not safe to use in online multiplayer since different players can have different sub-achievements completed. As such it will always be treated as if the sub-achievement is not completed.
 +
 
 +
=== [variable] ===
 +
 
 +
Test the value of a WML [[VariablesWML|variable]] against another value.
 +
 
 +
* '''name''': The name of the variable to test.
 +
* ''<comparison>'': '''One''' of the following keys must be used to compare the value of the named variable, represented as ''$name'' below, against another value:
 +
** '''contains''': ''$name'' contains this string value.
 +
** '''equals''': ''$name'' is equal (string wise) to this value.
 +
** '''not_equals''': ''$name'' is not equal (string wise) to this value.
 +
** '''numerical_equals''': ''$name'' is equal (numerically) to this value.
 +
** '''numerical_not_equals''': ''$name'' is not equal (numerically) to this value.
 +
** '''greater_than''': ''$name'' is numerically greater than this value.
 +
** '''greater_than_equal_to''': ''$name'' is numerically greater than or equal to this value.
 +
** '''less_than''': ''$name'' is numerically less than this value.
 +
** '''less_than_equal_to''': ''$name'' is numerically less than or equal to this value.
 +
** '''boolean_equals''': ''$name'' has an equivalent boolean value.
 +
** '''boolean_not_equals''': ''$name'' does not have an equivalent boolean value.
 +
** '''formula''': {{DevFeature1.15|0}} ''$name'' satisfies the given [[Wesnoth_Formula_Language|WFL]] formula.
  
; [variable]
 
: Test the value of a WML [[VariablesWML|variable]] against another value.
 
:* '''name''': The name of the variable to test.
 
:* ''<comparison>'': '''One''' of the following keys must be used to compare the value of the named variable, represented as ''$name'' below, against another value:
 
:** '''contains''': ''$name'' contains this string value.
 
:** '''equals''': ''$name'' is equal (string wise) to this value.
 
:** '''not_equals''': ''$name'' is not equal (string wise) to this value.
 
:** '''numerical_equals''': ''$name'' is equal (numerically) to this value.
 
:** '''numerical_not_equals''': ''$name'' is not equal (numerically) to this value. '''*'''<br />'''*''' Using equals is faster. The point of numerical_equals and boolean_equals is not performance, it's representation. For instance, "1" and "1.0" are not equal as strings but they are equal as numbers; and "yes" and "true" are not equal as strings but they are equal as booleans. (This also explains why equals is faster: it is a straightforward comparison that doesn't try to understand what you have written.)
 
:** '''greater_than''': ''$name'' is greater than this value.
 
:** '''greater_than_equal_to''': ''$name'' is greater than or equal to this value.
 
:** '''less_than''': ''$name'' is less than this value.
 
:** '''less_than_equal_to''': ''$name'' is less than or equal to this value.
 
:** '''boolean_equals''': ''$name'' has an equivalent boolean value. '''*'''
 
:** '''boolean_not_equals''': ''$name'' does not have an equivalent boolean value. '''*'''
 
 
====Boolean Values====
 
====Boolean Values====
 
When values are evaluated as boolean values they are checked to see if they are ''false'' or ''true''.
 
When values are evaluated as boolean values they are checked to see if they are ''false'' or ''true''.
Line 112: Line 222:
 
'''Warning:''' Do not use "off", "on", integers, floating-point numbers or anything else than the above as booleans.
 
'''Warning:''' Do not use "off", "on", integers, floating-point numbers or anything else than the above as booleans.
  
=== Meta Condition Tags ===
+
====Formulas====
 +
When using a formula, the variable's value can be referenced as '''value''' in the formula. This is a WFL representation of a config object that supports the following fields:
 +
 
 +
* '''__all_children''': A list of key-value pairs, where the key is the tag name and the value is another config object representing the tag content.
 +
* '''__children''': A map from tag name to a list of all children with that tag name.
 +
* '''__attributes''': A map from attribute to value. Only useful if you specifically require a map for some reason.
 +
* ''Any attribute name'': The value of that attribute
 +
* ''Any tag name'': A list of all children with that tag name.
 +
* Note that if there is a tag and an attribute with the same name, accessing it by name will return the attribute. You would need to use '''__children''' to access the tag.
 +
 
 +
For example, suppose you had a variable with the following WML content:
 +
 
 +
<syntaxhighlight lang=wml>
 +
[my_variable]
 +
    stuff=777
 +
    something=a value
 +
    [something]
 +
        value=42
 +
    [/something]
 +
    [another_tag]
 +
        value=21
 +
    [/another_tag]
 +
    [subarray]
 +
        value=8
 +
    [/subarray]
 +
    [subarray]
 +
        value=91
 +
    [/subarray]
 +
    [another_tag]
 +
        value=12
 +
    [/another_tag]
 +
[/my_variable]
 +
</syntaxhighlight>
 +
 
 +
Then the formula could access the following variables on the '''value''' object:
 +
* '''__all_children''': A list of ordered key-value pairs roughly equivalent to <syntaxhighlight lang=wfl inline>['something' -> ['value' -> 42], 'another_tag' -> ['value' -> 21], 'subarray' -> ['value' -> 8], 'subarray' -> ['value' -> 91], 'another_tag' -> ['value' -> 12]]</syntaxhighlight>
 +
* '''__children''': A map roughly equivalent to <syntaxhighlight lang=wfl inline>['something' -> [['value' -> 42]], 'another_tag' -> [['value' -> 21], ['value' -> 12]], 'subarray' -> [['value' -> 8], ['value' -> 91]]]</syntaxhighlight>
 +
* '''__attributes''': A map equivalent to <syntaxhighlight lang=wfl inline>['stuff' -> 777, 'something' -> 'a value']</syntaxhighlight>
 +
* '''stuff''': The number <syntaxhighlight lang=wfl inline>777</syntaxhighlight>
 +
* '''something''': The string <syntaxhighlight lang=wfl inline>'a value'</syntaxhighlight>
 +
* '''another_tag''': A list roughly equivalent to <syntaxhighlight lang=wfl inline>[['value' -> 21], ['value' -> 12]]</syntaxhighlight>
 +
* '''subarray''': A list roughly equivalent to <syntaxhighlight lang=wfl inline>[['value' -> 8], ['value' -> 91]]</syntaxhighlight>
 +
 
 +
{{DevFeature1.17|11}} When using a formula, you can now specify an additional key:
 +
 
 +
* '''as_type''': Specifies the type of the '''value''' object in the formula. The default is ''wml'', which uses the structure as described above. The other supported options are:
 +
** ''unit'': Interprets the variable's value as a stored unit, allowing you to write the formula the same way you would in a [[StandardUnitFilter]].
 +
** ''weapon'': Interprets the variable's value as an attack type, allowing you to write the formula the same way you would in a [[StandardWeaponFilter]].
 +
 
 +
=== [found_item] ===
 +
 
 +
{{DevFeature1.13|2}} Test if an item (i.e., a modification given by <nowiki>[</nowiki>[[DirectActionsWML#.5Bobject.5D|object]]]) has been found yet. Note: This will only detect objects added via ActionWML in an event in the same scenario. It will not detect objects added in [modifications] when a unit is created, nor objects added via [modify_unit] or the Lua wesnoth.add_modification function, nor objects added in a previous scenario in a campaign.
 +
 
 +
* '''id''': The ID of the item to test. It must exactly match an [object] that has been taken for the test to pass.
 +
 
 +
=== [proceed_to_next_scenario] ===
 +
 
 +
{{DevFeature1.13|10}} In SP, true if the scenario has been won.
 +
 
 +
=== [lua] ===
 +
 
 +
{{DevFeature1.13|11}} Evaluate a lua expression, which must return a boolean value. Useful for writing one-off conditions that are difficult to express with other tags, but for much-used conditions it's better to define a custom condition tag using [[LuaAPI/wesnoth#wesnoth.wml_conditionals|wesnoth.wml_conditionals]].
 +
 
 +
* '''code''': The Lua expression.
 +
* '''name''': A name used to identify the tag in error messages.
 +
* '''[args]''': Arbitrary data passed to the expression, accessible via <tt>...</tt> in the Lua code.
 +
 
 +
For example
  
These tags aren't really conditions, themselves. Instead they are wrapped around condition tags to group them into multiple conditions that must all be met, lists of conditions that only one must be met, or conditions that must not be met. These are handled in order in any combination you can think of. One important thing to remember is if you are using '''[or]''' tags, the first conditional statement should ''not'' have an '''[or]''' tag wrapped around it.
+
<syntaxhighlight lang=wml>
 +
[event]
 +
name=new turn
 +
first_time_only=no
 +
[filter_condition]
 +
[lua]
 +
code = << return (wesnoth.get_variable("turn_number") % 2 == 0) >>
 +
[/lua]
 +
[/filter_condition]
 +
[message]
 +
speaker=narrator
 +
message= "Hello world $turn_number|"
 +
[/message]
 +
[/event]
 +
</syntaxhighlight>
 +
 
 +
=== Meta-Condition Tags ===
 +
 
 +
These tags aren't really conditions, themselves. Instead they are wrapped around condition tags to group them into multiple conditions that must all be met, lists of conditions that only one must be met, or conditions that must not be met. These are handled in top-to-bottom order in any combination you can think of. One important thing to remember is if you are using '''[or]''' tags, the first conditional statement should ''not'' have an '''[or]''' tag wrapped around it.
  
 
; [and]
 
; [and]
: A condition which must evaluate to true in addition to any others. Useful as a bracket for complex conditions, but not strictly necessary.
+
: A condition which must evaluate to true in addition to any other conditions that precede it. This is useful as a bracket for complex conditions, but not strictly necessary.
 
:* [[#Condition Tags|Condition Tags]]: If these evaluate to true, the '''[and]''' tag evaluates to true.
 
:* [[#Condition Tags|Condition Tags]]: If these evaluate to true, the '''[and]''' tag evaluates to true.
  
 
; [or]
 
; [or]
: This condition, if true, allows the containing tag to also evaluate as true despite any false conditions preceding this one and without regard to any false conditions in the immediate contents of the containing tag. In other words, if any one [or] tag evaluates as true (and no false [and] or [not] tags come after it) then the [[:Category:ActionsWML|action]] will take place. (See [[AdvancedConditionalWML|Example]]).
+
: A condition which, when false, has no effect, but when true, allows previously failed conditions to be ignored.  
 
:* [[#Condition Tags|Condition Tags]]: If these evaluate to true, the '''[or]''' tag evaluates to true.  
 
:* [[#Condition Tags|Condition Tags]]: If these evaluate to true, the '''[or]''' tag evaluates to true.  
  
 
; [not]
 
; [not]
: A condition which reverses the evaluation of the contained condition(s).
+
: Similar to [and], but its contents must be false. Thus it reverses the evaluation of its contents. Since a normal condition tag without contents is always considered true, an empty [not] is always considered false.
 
:* [[#Condition Tags|Condition Tags]]: If these evaluate to true, the '''[not]''' tag evaluates to false. If these evaluate to false, the '''[not]''' tag evaluates to true.
 
:* [[#Condition Tags|Condition Tags]]: If these evaluate to true, the '''[not]''' tag evaluates to false. If these evaluate to false, the '''[not]''' tag evaluates to true.
 +
 +
 +
When multiple meta-conditions are encountered one after another in a containing tag, the evaluation order is as follows:
 +
# the immediate contents of the containing tag are evaluated first to determine if there is a successful match known as a "true" condition
 +
# this true or false result is combined with the top meta-condition to produce another true or false result
 +
# this result is combined with the next meta-condition, and so on. However, if the engine recognizes that no remaining meta-conditions might reverse the result, it will cleverly skip them.
 +
# if the final result is a successful match, then the [[:Category:ActionsWML|action]] will take place.
  
 
== See Also ==
 
== See Also ==
* [[VariablesWML]]
+
* [[SyntaxWML]]
 
* [[InternalActionsWML]]
 
* [[InternalActionsWML]]
 
* [[DirectActionsWML]]
 
* [[DirectActionsWML]]

Latest revision as of 03:38, 22 February 2024

[edit]WML Tags

A:

abilities, about, achievement, achievement_group, add_ai_behavior, advanced_preference, advancefrom, advancement, advances, affect_adjacent, ai, allied_with, allow_end_turn, allow_extra_recruit, allow_recruit, allow_undo, and, animate, animate_unit, animation, aspect, attack (replay, weapon), attack_anim, attacks (special, stats), avoid;

B:

base_unit, background_layer, berserk, binary_path, break, brush;

C:

campaign, cancel_action, candidate_action, capture_village, case, chance_to_hit, change_theme, chat, checkbox, choice, choose, clear_global_variable, clear_menu_item, clear_variable, color_adjust, color_palette, color_range, command (action, replay), continue, core, credits_group, criteria;

D:

damage, damage_type, death, deaths, default, defend, defends, defense, delay, deprecated_message, destination, difficulty, disable, disallow_end_turn, disallow_extra_recruit, disallow_recruit, do, do_command, drains, draw_weapon_anim;

E:

editor_group, editor_music, editor_times, effect, else (action, animation), elseif, endlevel, end_turn (action, replay), enemy_of, engine, entry (credits, options), era, event, experimental_filter_ability, experimental_filter_ability_active, experimental_filter_specials, extra_anim;

F:

facet, facing, fake_unit, false, feedback, female, filter (concept, event), filter_adjacent, filter_adjacent_location, filter_attack, filter_attacker, filter_base_value, filter_condition, filter_defender, filter_enemy, filter_location, filter_opponent, filter_own, filter_owner, filter_radius, filter_recall, filter_second, filter_second_attack, filter_self, filter_side, filter_student, filter_vision, filter_weapon, filter_wml, find_path, fire_event, firststrike, floating_text, fonts, for, foreach, found_item, frame;

G:

game_config, get_global_variable, goal, gold, gold_carryover;

H:

harm_unit, has_ally, has_attack, has_unit, has_achievement, have_location, have_unit, heal_on_hit, heal_unit, healed_anim, healing_anim, heals, hide_help, hide_unit, hides;

I:

idle_anim, if (action, animation, intro), illuminates, image (intro, terrain), init_side, insert_tag, inspect, item, item_group;

J:

jamming_costs, join;

K:

kill, killed;

L:

label, language, leader, leader_goal, leadership, leading_anim, levelin_anim, levelout_anim, lift_fog, limit, literal, load_resource, locale, lock_view, lua;

M:

male, menu_item, message, micro_ai, missile_frame, modification, modifications, modify_ai, modify_side, modify_turns, modify_unit, modify_unit_type, move, move_unit, move_unit_fake, move_units_fake, movement_anim, movement costs, movetype, multiplayer, multiplayer_side, music;

N:

not, note;

O:

object, objective, objectives, on_undo, open_help, option, options, or;

P:

part, petrifies, petrify, place_shroud, plague, poison, post_movement_anim, pre_movement_anim, primary_attack, primary_unit, print, progress_achievement, put_to_recall_list;

R:

race, random_placement, recall (action, replay), recalls, recruit, recruit_anim, recruiting_anim, recruits, redraw, regenerate, remove_event, remove_item, remove_object, remove_shroud, remove_sound_source, remove_time_area, remove_trait, remove_unit_overlay, repeat, replace_map, replace_schedule, replay, replay_start, reset_fog, resistance (ability, unit), resistance_defaults, resolution, resource, return, role, rule;

S:

save, scenario, screen_fade, scroll, scroll_to, scroll_to_unit, secondary_attack, secondary_unit, section, select_unit, sequence, set_achievement, set_extra_recruit, set_global_variable, set_menu_item, set_recruit, set_specials, set_variable, set_variables, sheath_weapon_anim, show_if (message, objective, set_menu_item), show_objectives, side, skirmisher, slider, slow, snapshot, sound, sound_source, source (replay, teleport), special_note, specials, split, stage, standing_anim, statistics, status, store_gold, store_items, store_locations, store_map_dimensions, store_reachable_locations, store_relative_direction, store_side, store_starting_location, store_time_of_day, store_turns, store_unit, store_unit_defense, store_unit_defense_on, store_unit_type, store_unit_type_ids, store_villages, story, swarm, sub_achievement, switch, sync_variable;

T:

target, team, teleport (ability, action), teleport_anim, terrain, terrain_defaults, terrain_graphics, terrain_mask, terrain_type, test, test_condition, test_do_attack_by_id, text_input, textdomain, theme, then, tile, time, time_area, topic, toplevel, trait, transform_unit, traveler, true, tunnel;

U:

unhide_unit, unit (action, scenario), unit_overlay, unit_type, unit_worth, units, unlock_view, unpetrify, unstore_unit, unsynced;

V:

value, variable, variables, variant, variation, victory_anim, village, vision_costs, volume;

W:

while, wml_message, wml_schema;

Z:

zoom;

Part of ActionWML, Conditional Actions WML is used to describe container actions that create branching and flow control for WML. The conditional actions act as gatekeepers, encapsulating other actions with conditions which must be met before an action can take place. These conditional actions also contain the actions which will take place if those conditions are met and, in some cases, what actions will take place if they are not met.

Conditional Actions

These actions describe actions that should be executed only if certain conditions are met.

[if]

Executes actions only if the contained conditions are met.

  • Condition Tags: Conditions which must be met for the actions in the [then] tag to be executed.
  • [then]: Contains actions which should be executed if all conditions evaluate as true or if any single [or] tag evaluates as true.
  • [elseif]: (Version 1.13.0 and later only) in case that the conditions inside [if] aren't met, these tags will be evalutated one by one. If the specified conditions are met, the contained [then] tags will be executed, and the cycle will end.
    • Condition Tags: Specifies the conditions, just like in [if].
    • [then]: Specifies actions, exactly like the [then] tag inside [if].
  • [else]: Contains actions which should be executed if all condition tags in the [if] and any directly nested [elseif] all evaluate as false.


Attention: There are tags named [if] and [else] inside [animation] (see AnimationWML), which have a different syntax.

Example usage:

[if]
   [variable]
      name=we.gold
      greater_than=$they.gold
   [/variable]
   [elseif]
      [variable]
         name=we.gold
         equals=$they.gold
      [/variable]
      [then]
         [message]
            message=This should be fair!
         [/message]
      [/then]
   [/elseif]
   [else]
      [message]
         message=This will not be easy!
      [/message]
   [/else]
[/if]

[switch]

The [switch] tag is a special case because it does not use Condition Tags to control whether actions are performed. Instead, it executes different sets of actions based on the value of a variable

  • variable: The name of the variable to check.
  • [case]: Case tag which forms a block containing:
    • value: The value to test the variable's value against. This can be a comma separated list of values.
    • Action WML: Action WML to execute if the variable matches the value. (The rest of the [case] block after the value attribute.)
  • [else]: Else tag which forms a block of Action WML to execute if no [case] block contains a value matching the value of the variable.

Example usage:

[switch]
   variable=foo
   [case]
      value="A"
      # ... WML if foo=A ...
   [/case]
   [case]
      value="B"
      # ... WML if foo=B ...
   [/case]
   [else]
      # ... WML if not foo=A nor foo=B ...
   [/else]
[/switch]

[while]

Like the [if] tag, executes actions only if conditions described in the contained conditions are met. Additionally, the [while] tag continues to execute the actions until the contained conditions are no longer met. Executes a maximum of 65536 iterations per invocation.

  • Condition Tags: Conditions which must be met for the actions in the [do] tag to be executed.
  • [do]: contains actions that should be executed repeatedly until some condition is false. Multiple [do] tags can be used, and they will be executed in sequence on each iteration. However, there is usually no reason to do this.

The [while] tag is useful for iterating over an array. An array is a list of values. The numberth value in the array array is stored in the WML variable array[number]. Note that if number is the value of the variable variable, the expression $array[$variable] will return the numberth value in array.

'FOREACH' Macro

This macro simplifies the use of a [while] tag to create a for-each iteration format. This is useful, for example, when you want to iterate over each row in a table. To use it, use the FOREACH and NEXT macros. Note: This macro is deprecated; you should just use the [foreach] WML tag instead.

'REPEAT' Macro

This macro simplifies the use of a [while] tag to execute the same actions repeatedly for a specified number of times. To use it, use the REPEAT macro.

[for]

(Version 1.13.2 and later only)

Loops over an integer range. Note that, if iterating over an array to delete several elements, it is best to use reverse=yes to avoid accidentally skipping some elements.

  • variable: The name of the variable containing the current index. Defaults to i. If there is already a variable with this name, it will be automatically saved before the start of the loop, and reset to its previous value when the loop exits. If there wasn't a variable with that name before the loop, it will be automatically deleted, there is no need to do a [clear_variable] afterwards
  • start: The index of the first element to loop over, and sets the starting value of variable. Defaults to 0.
  • end: The index of the final element to loop over, and sets the maximum allowed value of variable. Defaults to start.
  • step: The value added to the current value of variable after each iteration of the loop. Defaults to 1 if start < end, or -1 if start > end.
    • For example, if start=1 and step=2, then the value of variable for each iteration will be: 1, 3, 5, ...
  • array: Specify an array to iterate over. This is a shortcut for setting start=0 and end=$($array_name.length-1)
    • If array is set, then start, end, and step are ignored.
  • reverse: If set to yes, and array was specified, then this is a shortcut for setting start=$($array_name.length-1) and end=0.
  • [do]: The actions to execute on each iteration. As with [while], it is possible to use multiple [do] tags, but there is usually no reason to.

[foreach]

(Version 1.13.2 and later only)

Loops over an array variable. This is not used to implement the {FOREACH} macro because [foreach] doesn't support adding or removing elements while looping (and will usually raise an error), use [for] instead.

  • array: The array variable to loop over.
  • variable: The name of a variable which refers to the current item. Defaults to this_item. Any changes made to this variable will persist in the array after the loop has completed.
  • index_var: The name of a variable which refers to the index of the current item. Defaults to i. Note that this is just for information purposes and should not be used to access the array from within the loop (any such changes made will not persist).
  • readonly: If set to yes, this prevents the array from being modified in any way during the loop. (It defaults to no.) That means that changes made through the variable will not persist. Changes made through the index_var will also not persist (as normal). In effect, the array is reverted to its original state once the loop exits.
  • [do]: The actions to execute on each iteration. As with [while], it is possible to use multiple [do] tags, but there is usually no reason to.

The [foreach] tag simulates local-scoping of its index variables. If there was already a WML variable with the same name (by default i and this_item respectively), it will be automatically saved before the start of the [do], and reset to its previous value when the loop exits. If there wasn't a variable with that name before the loop, there is no need to do a [clear_variable] afterwards.

It's possible to nest [foreach] loops, however 1.16 does not support using the same variable= name for both loops (issue 6305, fixed in (Version 1.17.13 and later only)).

[repeat]

(Version 1.13.2 and later only)

Repeats some actions a fixed number of times. This is a completely stateless loop - there's no way to know which iteration of the loop you're on. (If you need this, use [for] instead.)

  • times: The number of times to repeat the actions.
  • [do]: The actions to repeat. As with [while], it is possible to use multiple [do] tags, but there is usually no reason to.

[command]

This tag is more of an Unconditional Action: when it is encountered, the actions in its content are simply executed once. In practice, this tag serves little purpose. However, it may be used to arrange actions together in logical groups, for example, with actions that are stored in an array and later inserted. (It is also used inside of [set_menu_item] and [option] of InterfaceActionsWML.)

Condition Tags

These tags describe conditions which must be met before an action can take place. Some or all of them are used in the various Conditional Actions.

[true]

Represents a condition that always yields true. Takes no arguments.

[false]

Represents a condition that always yields false. Takes no arguments.

[have_unit]

A unit with greater than zero hit points matching this filter exists.

  • StandardUnitFilter *: Selection criteria. Do not use a [filter] tag.
  • count: (Optional) If used, a number of units equal to the value must match the filter. Accepts a number, range, or comma separated range. If not used, the default value is "1-99999".
  • search_recall_list: (Optional) If 'yes', search through recall list too. (Default is 'no')

[have_location]

A location matching this filter exists.

  • StandardLocationFilter: Selection criteria.
  • count: (Optional) If used, a number of locations equal to the value must match the filter. Accepts a number, range, or comma separated range. If not used, the default value is "1-99999".

[has_achievement]

(Version 1.17.13 and later only)

The specified achievement has been completed.

  • content_for: The [achievements_group] that this achievement is part of.
  • id: The id of the achievement.

NOTE: This is not safe to use in online multiplayer since different players can have different achievements completed. As such it will always be treated as if the achievement is not completed.

[has_sub_achievement]

(Version 1.17.17 and later only)

The specified achievement has been completed.

  • content_for: The [achievements_group] that this achievement is part of.
  • id: The id of the achievement.
  • sub_id: The id of the sub-achievement.

NOTE: This is not safe to use in online multiplayer since different players can have different sub-achievements completed. As such it will always be treated as if the sub-achievement is not completed.

[variable]

Test the value of a WML variable against another value.

  • name: The name of the variable to test.
  • <comparison>: One of the following keys must be used to compare the value of the named variable, represented as $name below, against another value:
    • contains: $name contains this string value.
    • equals: $name is equal (string wise) to this value.
    • not_equals: $name is not equal (string wise) to this value.
    • numerical_equals: $name is equal (numerically) to this value.
    • numerical_not_equals: $name is not equal (numerically) to this value.
    • greater_than: $name is numerically greater than this value.
    • greater_than_equal_to: $name is numerically greater than or equal to this value.
    • less_than: $name is numerically less than this value.
    • less_than_equal_to: $name is numerically less than or equal to this value.
    • boolean_equals: $name has an equivalent boolean value.
    • boolean_not_equals: $name does not have an equivalent boolean value.
    • formula: (Version 1.15.0 and later only) $name satisfies the given WFL formula.

Boolean Values

When values are evaluated as boolean values they are checked to see if they are false or true.

  • These values are evaluated as true: "yes" and "true"
  • These values are evaluated as false: "no", "false" and ""(uninitialized)
    • However, in contexts where true is defined as the default value, an uninitialized value would be considered true.

Warning: Do not use "off", "on", integers, floating-point numbers or anything else than the above as booleans.

Formulas

When using a formula, the variable's value can be referenced as value in the formula. This is a WFL representation of a config object that supports the following fields:

  • __all_children: A list of key-value pairs, where the key is the tag name and the value is another config object representing the tag content.
  • __children: A map from tag name to a list of all children with that tag name.
  • __attributes: A map from attribute to value. Only useful if you specifically require a map for some reason.
  • Any attribute name: The value of that attribute
  • Any tag name: A list of all children with that tag name.
  • Note that if there is a tag and an attribute with the same name, accessing it by name will return the attribute. You would need to use __children to access the tag.

For example, suppose you had a variable with the following WML content:

[my_variable]
    stuff=777
    something=a value
    [something]
        value=42
    [/something]
    [another_tag]
        value=21
    [/another_tag]
    [subarray]
        value=8
    [/subarray]
    [subarray]
        value=91
    [/subarray]
    [another_tag]
        value=12
    [/another_tag]
[/my_variable]

Then the formula could access the following variables on the value object:

  • __all_children: A list of ordered key-value pairs roughly equivalent to ['something' -> ['value' -> 42], 'another_tag' -> ['value' -> 21], 'subarray' -> ['value' -> 8], 'subarray' -> ['value' -> 91], 'another_tag' -> ['value' -> 12]]
  • __children: A map roughly equivalent to ['something' -> [['value' -> 42]], 'another_tag' -> [['value' -> 21], ['value' -> 12]], 'subarray' -> [['value' -> 8], ['value' -> 91]]]
  • __attributes: A map equivalent to ['stuff' -> 777, 'something' -> 'a value']
  • stuff: The number 777
  • something: The string 'a value'
  • another_tag: A list roughly equivalent to [['value' -> 21], ['value' -> 12]]
  • subarray: A list roughly equivalent to [['value' -> 8], ['value' -> 91]]

(Version 1.17.11 and later only) When using a formula, you can now specify an additional key:

  • as_type: Specifies the type of the value object in the formula. The default is wml, which uses the structure as described above. The other supported options are:
    • unit: Interprets the variable's value as a stored unit, allowing you to write the formula the same way you would in a StandardUnitFilter.
    • weapon: Interprets the variable's value as an attack type, allowing you to write the formula the same way you would in a StandardWeaponFilter.

[found_item]

(Version 1.13.2 and later only) Test if an item (i.e., a modification given by [object]) has been found yet. Note: This will only detect objects added via ActionWML in an event in the same scenario. It will not detect objects added in [modifications] when a unit is created, nor objects added via [modify_unit] or the Lua wesnoth.add_modification function, nor objects added in a previous scenario in a campaign.

  • id: The ID of the item to test. It must exactly match an [object] that has been taken for the test to pass.

[proceed_to_next_scenario]

(Version 1.13.10 and later only) In SP, true if the scenario has been won.

[lua]

(Version 1.13.11 and later only) Evaluate a lua expression, which must return a boolean value. Useful for writing one-off conditions that are difficult to express with other tags, but for much-used conditions it's better to define a custom condition tag using wesnoth.wml_conditionals.

  • code: The Lua expression.
  • name: A name used to identify the tag in error messages.
  • [args]: Arbitrary data passed to the expression, accessible via ... in the Lua code.

For example

[event]
	name=new turn
	first_time_only=no
	[filter_condition]
		[lua]
			code = << return (wesnoth.get_variable("turn_number") % 2 == 0) >>
		[/lua]
	[/filter_condition]
	[message]
		speaker=narrator
		message= "Hello world $turn_number|"
	[/message]
[/event]

Meta-Condition Tags

These tags aren't really conditions, themselves. Instead they are wrapped around condition tags to group them into multiple conditions that must all be met, lists of conditions that only one must be met, or conditions that must not be met. These are handled in top-to-bottom order in any combination you can think of. One important thing to remember is if you are using [or] tags, the first conditional statement should not have an [or] tag wrapped around it.

[and]
A condition which must evaluate to true in addition to any other conditions that precede it. This is useful as a bracket for complex conditions, but not strictly necessary.
  • Condition Tags: If these evaluate to true, the [and] tag evaluates to true.
[or]
A condition which, when false, has no effect, but when true, allows previously failed conditions to be ignored.
  • Condition Tags: If these evaluate to true, the [or] tag evaluates to true.
[not]
Similar to [and], but its contents must be false. Thus it reverses the evaluation of its contents. Since a normal condition tag without contents is always considered true, an empty [not] is always considered false.
  • Condition Tags: If these evaluate to true, the [not] tag evaluates to false. If these evaluate to false, the [not] tag evaluates to true.


When multiple meta-conditions are encountered one after another in a containing tag, the evaluation order is as follows:

  1. the immediate contents of the containing tag are evaluated first to determine if there is a successful match known as a "true" condition
  2. this true or false result is combined with the top meta-condition to produce another true or false result
  3. this result is combined with the next meta-condition, and so on. However, if the engine recognizes that no remaining meta-conditions might reverse the result, it will cleverly skip them.
  4. if the final result is a successful match, then the action will take place.

See Also

This page was last edited on 22 February 2024, at 03:38.