Difference between revisions of "SyntaxWML"

From The Battle for Wesnoth Wiki
(Limitations on variable substitution & tweaking sectioning levels)
(Tag and Attribute Structures: Note case sensitivity)
 
(61 intermediate revisions by 16 users not shown)
Line 1: Line 1:
 +
{{Translations}}
 
{{WML Tags}}
 
{{WML Tags}}
  
 
The '''Wesnoth Markup Language''' ('''WML''') is used to code almost everything in Wesnoth, including scenarios, units, savefiles, and the user interface layout. WML files are simple, human-readable text files, usually with the .cfg extension, with similarities to INI files and XML.
 
The '''Wesnoth Markup Language''' ('''WML''') is used to code almost everything in Wesnoth, including scenarios, units, savefiles, and the user interface layout. WML files are simple, human-readable text files, usually with the .cfg extension, with similarities to INI files and XML.
 
+
For guidelines on keeping these files easily human-readable, see [[ConventionsWML#Indentation|ConventionsWML]].
== Syntax Basics ==
 
 
 
WML is a line-based language, meaning that line breaks are significant. The opening and closing lines of a tag (defined later) cannot include other text. When setting an attribute (also defined later), all text up to the first equals sign (=) is considered the key, while all text following that equals sign until the end of the line is considered the value. A line break must occur before starting another <code>key=value</code> line; otherwise the intended "<code>key=value</code>" will be treated as textual data and considered part of the preceding attribute's value.
 
The type of line break used within a WML file should be consistent to avoid confusing the game. (This is typically only an issue when a file is edited from different operating systems; Mac, Linux, and Windows each have their own types of line breaks.)
 
 
 
Consecutive whitespace characters in WML are usually equivalent to a single space, and in many cases whitespace itself is optional. (However, good indentation is crucial for readable files; see [[ConventionsWML#Indentation|ConventionsWML]] for guidelines.) Furthermore, there are some cases in which spaces are more than optional; sometimes they are stripped (sometimes resulting in malfunctioning WML). At the same time, there are some cases in which whitespace that looks irrelevant to many human readers is in fact significant and not stripped (sometimes resulting in malfunctioning WML). If in doubt, copy the spacing from working WML.
 
For text that will not be displayed to a player, it is sometimes useful to use an underscore (_) instead of a space so that issues with whitespace can be sidestepped.
 
 
 
Comments are indicated by starting a line with a pound sign (<code>#</code>). Unless the line forms a valid [[PreprocessorRef#Preprocessor_directives|preprocessor directive]], all text after the pound sign will be ignored by the WML engine.
 
  
 
== Tag and Attribute Structures ==
 
== Tag and Attribute Structures ==
  
 
WML has a syntax containing two basic elements: ''tags'' and ''attributes''. Furthermore, ''attributes'' consist of ''keys'' and ''values''. For example:
 
WML has a syntax containing two basic elements: ''tags'' and ''attributes''. Furthermore, ''attributes'' consist of ''keys'' and ''values''. For example:
  [tag]
+
<syntaxhighlight lang="wml">
      key=value
+
[tag]
  [/tag]
+
    key=value
 +
[/tag]
 +
</syntaxhighlight>
  
 
''Tags'' are used to partition information, while the data is contained in the ''attributes''. ''Keys'' identify the type of data to be stored and ''values'' are the actual data stored. When WML is processed, the tag identifies some unit of information, such as an action to perform or even an entire campaign. This gives a context for the attributes within the tag. For each <code>key=value</code> line within a tag, the attribute identified by <code>key</code> has its data set to <code>value</code>.
 
''Tags'' are used to partition information, while the data is contained in the ''attributes''. ''Keys'' identify the type of data to be stored and ''values'' are the actual data stored. When WML is processed, the tag identifies some unit of information, such as an action to perform or even an entire campaign. This gives a context for the attributes within the tag. For each <code>key=value</code> line within a tag, the attribute identified by <code>key</code> has its data set to <code>value</code>.
 
Also allowed inside a tag is another tag. The inner tag is considered the child of the outer tag, as in the following example.
 
Also allowed inside a tag is another tag. The inner tag is considered the child of the outer tag, as in the following example.
  [parent_tag]
+
<syntaxhighlight lang="wml">
      key1=value1
+
[parent_tag]
      [child_tag]
+
    key1=value1
          key2=value2
+
    [child_tag]
      [/child_tag]
+
        key2=value2
  [/parent_tag]
+
    [/child_tag]
 +
[/parent_tag]
 +
</syntaxhighlight>
  
Every tag describes something different about the game; different tags work differently, with the allowed tags defined by context. There are several "[[ReferenceWML#WML_toplevel_tags|top-level tags]]" that are allowed when not inside any other tag, and each tag defines which child tags it recognizes. An unrecognized tag often causes the game to abort processing the WML, but there are some situations (particularly [[FilterWML]]) in which unrecognized tags are quietly ignored. For a list of all tags with links to their documentation, see [[AlphabeticalWML]] or the navigation box that appears on all pages documenting tags.
+
Every tag describes something different about the game; different tags work differently, with the allowed tags defined by context. There are several "[[ReferenceWML#WML_toplevel_tags|top-level tags]]" that are allowed when not inside any other tag, and each tag defines which child tags (and which keys) it recognizes. Unrecognized tags and keys, such as the result of typos, sometimes produce error messages, but at other times they are ignored. The [[SchemaWML|WML schema]] defines what is allowed and where. Although it's not designed to be read by humans, you can [[ValidationFAQ|use it to automatically detect]] if you've done something wrong even in contexts where unrecognized keys and tags would be ignored, though it still won't work in contexts where you're allowed to define the contents however you like.
  
Each tag defines which attributes it accepts, hence which keys are valid within that tag. Setting the values of those keys will configure the behavior of that tag. Unrecognized keys are usually quietly ignored. (In particular, keys are not variables.)
+
''Keys should not be confused with variables!'' A common mistake among beginners is to make up undocumented key names. Instead, consult the WML Reference to find allowed key names for each tag. For a list of all tags with links to their documentation, see the "WML Tags" navigation box.
 +
 
 +
Also, tag and key names follow a special format. They will contain only alphanumeric characters and underscores; in particular, they cannot contain <code>+</code>, <code>-</code>, or whitespace. The values, however, may contain such characters when needed. A key or tag name beginning with a digit or even consisting of entirely digits is permitted. Tag and key names are case sensitive.
  
Tag and key names may contain only alphanumeric characters and underscores; in particular, neither <code>+</code>, <code>-</code>, nor whitespace is allowed.
 
Values, on the other hand, are not so restricted.
 
  
 
=== Tag Amendment Syntax ===
 
=== Tag Amendment Syntax ===
 +
 
Inserting a plus sign (<code>+</code>) before a tag name allows one to append to an earlier tag (the most recent with the same name) rather than starting a new tag. This allows attributes to be added or replaced.
 
Inserting a plus sign (<code>+</code>) before a tag name allows one to append to an earlier tag (the most recent with the same name) rather than starting a new tag. This allows attributes to be added or replaced.
  [tag]
+
<syntaxhighlight lang="wml">
      key=value
+
[tag]
  [/tag]
+
    key=value
  [+tag]
+
[/tag]
      key=value
+
[+tag]
  [/tag]
+
    key=value
 +
[/tag]
 +
</syntaxhighlight>
  
 
* All keys in the ''+tag'' will be set to the given values. If the keys did not exist in the most recent [tag] then they are added to that [tag]; otherwise their values will replace the old values in the most recent [tag].
 
* All keys in the ''+tag'' will be set to the given values. If the keys did not exist in the most recent [tag] then they are added to that [tag]; otherwise their values will replace the old values in the most recent [tag].
Line 49: Line 48:
 
* Any child tags of the ''+tag'' will be appended to the children of the most recent [tag]. To be clear: none of those original child tags will be altered by this operation, since this is an "append" and not a "merge."
 
* Any child tags of the ''+tag'' will be appended to the children of the most recent [tag]. To be clear: none of those original child tags will be altered by this operation, since this is an "append" and not a "merge."
  
* Currently, you are not allowed to make tag amendments to a child tag after the parent tag has already closed. Using [+tag] syntax multiple times in a row will not allow you to amend the more inward scopes. However, this limitation may be removed in future versions of Wesnoth.
+
* It is even possible to make tag amendments to a child tag after the parent tag has already closed. Using [+tag] syntax multiple times in a row (first for the parent, then for the child) will allow you to amend the more inward scopes.
  
 
=== Multiple Assignment Syntax ===
 
=== Multiple Assignment Syntax ===
 +
 
It is possible to set multiple attributes on a single line. This is done by listing the associated keys, followed by an equal sign, followed by the desired values.
 
It is possible to set multiple attributes on a single line. This is done by listing the associated keys, followed by an equal sign, followed by the desired values.
  [tag]
+
<syntaxhighlight lang="wml">
      key1,key2,key3=value1,value2,value3
+
[tag]
  [/tag]
+
    key1,key2,key3=value1,value2,value3
 +
[/tag]
 +
</syntaxhighlight>
 
would be the same as:
 
would be the same as:
  [tag]
+
<syntaxhighlight lang="wml">
      key1=value1
+
[tag]
      key2=value2
+
    key1=value1
      key3=value3
+
    key2=value2
  [/tag]
+
    key3=value3
 +
[/tag]
 +
</syntaxhighlight>
 
* If there are extra keys, they will be set to an empty value. If there are extra values the last key will be set to the comma-separated list of all remaining values.
 
* If there are extra keys, they will be set to an empty value. If there are extra values the last key will be set to the comma-separated list of all remaining values.
 +
* It is recommended not to use this syntax with keys which normally interpret commas specially (such as x and y in a [[StandardLocationFilter]]), to avoid confusion on which key receives which value. However, using <code>x,y=12,10</code> for single coordinates is widely used and is an exception to the recommendation.
  
 
=== Special Attribute Values ===
 
=== Special Attribute Values ===
 +
 
Although an attribute's value can be just text corresponding to the function of its key, a value can also be encoded in many other ways, each with a specific purpose.
 
Although an attribute's value can be just text corresponding to the function of its key, a value can also be encoded in many other ways, each with a specific purpose.
* '''key = "value"''': a ''quoted value'' is a value surrounded by quotes. This is often unnecessary as single-line values are typically interpreted as intended. However, quotes are required in order to specify a multiple-line values (a line break inside quotes does not end the value). Quotes may also be required to cancel the special meaning of other characters, and they prevent spaces from being stripped. It is never wrong to use quotes with correct WML.
+
* {{Anchor|quoted values|2='''key = "value"'''}}: a ''quoted value'' is a value surrounded by quotes. This is often unnecessary as single-line values are typically interpreted as intended. However, quotes are required in order to specify multiple-line values (a line break without quotes would otherwise end the value). Quotes may also be required to cancel the special meaning of other characters, and they prevent spaces from being stripped &ndash; without quotes, all leading and trailing spaces would be removed, and internal runs of spaces would be replaced by a single space. It is never wrong to use quotes with correct WML.
* '''key = _"value"''': a ''[[translatable|translatable value]]'' is a value that is subject to translations, and should be used for all text intended to be shown to a player (most notably seen in [story], [message], and the name= key in unit definitions). A translatable value is surrounded by quotes and preceded by an underscore (_). In terms of WML syntax, it behaves very much like a quoted value, other than being unsuitable for [[ConditionalActionsWML#Condition_Tags|comparisons to other values]]. Translatable values are intended for display on the screen, while quoted values are better suited for internal data.
+
* {{Anchor|translatable strings|2='''key = _"value"'''}}: a ''[[translatable]] value'' is a value that is subject to translations, and should be used for all text intended to be shown to a player (most notably seen in [story], [message], and the name= key in unit definitions). A translatable value is surrounded by quotes and preceded by an underscore (_). In terms of WML syntax, it behaves very much like a quoted value, other than being unsuitable for [[ConditionalActionsWML#Condition_Tags|comparisons to other values]]. Translatable values are intended for display on the screen, not for internal data. See [[TranslationsWML]] and [[GettextForWesnothDevelopers]] for more information.
* '''key = "value1" + "value2"''': ''string concatenation'' is performed with the plus sign (<code>+</code>). If a plus sign appears outside quotes in a value, it means that the string/value on its right will be appended to the string/value on its left.  To have an actual plus sign in a value, the string containing the <code>+</code> character must be surrounded by quotes (a quoted value or a translatable value). Quotes are not strictly necessary around the pre-concatenated values, but they are advisable so that it is easy to tell where the values begin and end and to spot some kinds of mistakes.
+
* {{Anchor|value concatenation|2='''key = "value1" + "value2"'''}}: ''string concatenation'' is performed with the plus sign (<code>+</code>). If a plus sign appears outside quotes in a value, it means that the string/value on its right will be appended to the string/value on its left.  To have an actual plus sign in a value, the string containing the <code>+</code> character must be surrounded by quotes (a quoted value or a translatable value). Quotes are not strictly necessary around the pre-concatenated values, but they are advisable so that it is easy to tell where the values begin and end and to spot some kinds of mistakes. If two non-quoted values are concatenated, they will have a space inserted between them, but if either value is quoted, no space will be inserted.
* '''key = "quoted ""double quoted value"" value"''': ''doubled quotes'' can be used to create quote marks within a quoted or translatable value. The doubled quote mark in the value produces one quote mark in the stored data and does not terminate the quoted value. (These do not necessarily need to be used in pairs.)
+
* {{Anchor|escaping quotes|2='''key = "quoted ""double quoted value"" value"'''}}: ''doubled quotes'' can be used to create quote marks within a quoted or translatable value. The doubled quote mark in the value produces one quote mark in the stored data and does not terminate the quoted value. (These do not necessarily need to be used in pairs.)
* '''key = $variable''': a ''variable substitution'' sets the key to the value of the indicated WML variable. This is indicated by the dollar sign (<code>$</code>) and is really just  a special case of general variable substitution, as variables can be substituted within other values. See [[#Variable_Substitution|below]] for more information on values based on WML variables. (Note that some keys require their data to be a variable name, not the variable's value; in that case there would be no dollar sign.) ''Variable substitution is supported in only a few contexts, such as in the <nowiki>[</nowiki>[[IntroWML|story]]<nowiki>]</nowiki> tag and in [[EventWML]].
+
* {{Anchor|variable substitution basics|2='''key = $variable'''}}: a ''variable substitution'' sets the key to the value of the indicated WML variable. This is indicated by the dollar sign (<code>$</code>) and is really just  a special case of general variable substitution, as variables can be substituted within other values. See [[VariablesWML]] for more information on values based on WML variables. (Note that some keys require their data to be a variable name, not the variable's value; in that case there would be no dollar sign.) ''Variable substitution is supported in only a few contexts, such as in [[IntroWML]] and [[EventWML]].''
* '''key = "$(formula-expression)"''': a ''formula expression'' sets the key to the value of the processed formula. This is indicated by a dollar sign (<code>$</code>) followed by a parenthesized expression. See [[FormulaAI]] for more information on formula basics, data types, and built-in functions. Quotes around the formula are not strictly necessary in all cases, but they are advisable, particularly since quotes are the only way to use a plus sign (<code>+</code>) within a formula (without quotes, the plus sign represents string concatenation). ''Formula expressions are only supported where variable substitution is.''
+
* {{Anchor|formula substitution|2='''key = "$(formula-expression)"'''}}: a ''formula expression'' sets the key to the value of the processed formula. This is indicated by a dollar sign (<code>$</code>) followed by a parenthesized expression. See [[Wesnoth Formula Language]] for more information on formula basics, data types, and built-in functions. Quotes around the formula are not strictly necessary in all cases, but they are advisable, particularly since quotes are the only way to use a plus sign (<code>+</code>) within a formula (without quotes, the plus sign represents string concatenation). ''Formula expressions are only supported where variable substitution is supported.''
 
+
* {{Anchor|macro-protected string|2='''key = <<value>>'''}}: similar to a quoted value but stronger: the value is hidden from the [[PreprocessorRef|preprocessor]], which will see all text therein as literal. Useful with [[LuaWML]] or whenever a literal curly brace ("{", a US-ASCII 0x7B) is needed in any text string. This can also be combined with the translatable mark, in case curly braces are needed in translatable text.
== Variables ==
 
 
 
A WML variable can be manipulated in three ways:
 
* Assigning a value to a variable stores that value in the variable. This is done with [set_variable] or the {VARIABLE} macro.
 
* Querying a variable returns the last value stored in it (or the empty string, if no value was). This is done by calling $variable.
 
* Clearing a variable makes the WML engine forget about that variable. This is useful since the WML engine must save all used variables when a game is saved. This is done with [clear_variable] or the {CLEAR_VARIABLE} macro.
 
 
 
Each variable is given a name. A given variable name may contain only alphanumerics and underscores. A variable in these operations is identified by its full name. For more information on macros, please refer to [[PreprocessorRef]]
 
 
 
=== Kinds of Variables ===
 
==== Scalar ====
 
A scalar variable can store a single string or number.
 
 
 
  [set_variable]
 
      name=my_variable
 
      value="sample value"
 
  [/set_variable]
 
 
 
The full name of a scalar variable is its given name, in this case ''my_variable''. Note that the value of the variable can be translatable or even a formula expression ([http://wiki.wesnoth.org/SyntaxWML#Special_Attribute_Values Special Attribute Values]).
 
 
 
==== Array ====
 
An array variable is a numbered sequence of container variables. There are some specific tags that assign array information, for example [store_unit] and [store_locations]. One could create an array using [set_variable] like this:
 
  [set_variable]
 
      name=my_awesome_array[0].x
 
      value=10
 
  [/set_variable]
 
  [set_variable]
 
      name=my_awesome_array[1].x
 
      value=12
 
  [/set_variable]
 
  [set_variable]
 
      name=my_awesome_array[2].x
 
      value=14
 
  [/set_variable]
 
 
 
However, when working with arrays, it is usually easier to make use of [set_variables]. This would be written as follows:
 
  [set_variables]
 
      name=my_awesome_array
 
      [value]
 
          x=10
 
      [/value]
 
      [value]
 
          x=12
 
      [/value]
 
      [value]
 
          x=14
 
      [/value]
 
  [/set_variables]
 
 
 
If <tt>foo</tt> is the name of an array, <tt>foo[0]</tt> is the full name of its first container variable, <tt>foo[1]</tt> the full name of its second, and so on. <tt>foo.length</tt> is the special variable that always stores the number of containers in the array <tt>foo</tt>. Hence, if the value stored in <tt>foo.length</tt> is 18, the last container in the array would be <tt>foo[17]</tt>. If you try to query an array as if it were a container, then it will simply use the first index[0]. Thus $foo.bar would be the same as $foo[0].bar
 
 
 
''Note'': Do not attempt to store a scalar value to the explicit index of an array, which is a container of scalar variables. Hence referring to a variable named <tt>foo[3]</tt> as if it were a scalar one is illegal; instead, you would use <tt>foo[3].value</tt> to store a scalar value. (While it may appear to work to an extent if you ignore this rule, it may also cause undefined behavior. For example, loading a text save of a game that contains such variables will fail with a WML error.)
 
 
 
==== Container ====
 
A container variable can store any number of scalar and/or array variables. There are tags to assign specific information, for instance [store_side]. To refer to a variable <tt>bar</tt> stored in a container <tt>foo</tt> you would write <tt>foo.bar</tt>. An explicit index inside an array is also considered a container.
 
 
 
=== Conditionals ===
 
Variables and be compared with and used in a conditional block by [variable] within an [if] or [while] tag. For more information, please refer to [[ConditionalActionsWML]].
 
 
 
=== Variable Substitution ===
 
Whenever using a $ in front of a variable name, the content which has previously been put into this variable name is used instead of the name of the variable. For example:
 
  [event]
 
      name=turn 1
 
      [set_variable]
 
          name=my_variable
 
          value= _ "Konrad"
 
      [/set_variable]
 
      [message]
 
          speaker=Delfador
 
          message= _ "Hello, $my_variable|... How are you?"
 
      [/message]
 
  [/event]
 
 
 
The WML code above will cause Delfador to say "Hello, Konrad... How are you?" on turn 1.
 
 
 
When writing scenario events ([[EventWML]]), a scalar variable can generally be substituted into the right-hand of any '''key=value''' assignment. If the provided value contains a <tt>$</tt>, the WML engine with interpret what is between the rightmost <tt>$</tt> and the next <tt>|</tt> as a full variable name to be queried, and replace <tt>$''variable''|</tt> with the result of this query.
 
 
 
In certain situations, the <tt>|</tt> that marks the end of the variable name to be queried can be omitted. The exact rule is: if there is no |, variable names span letters, digits, underlines, balanced square brackets and some periods. Doubled periods and some periods that would result in an illegal variable name will not be included. If the variable name ends up being empty (e.g. when using $|), then it will be replaced by just $, giving you an easy way to include a dollar sign in an interpolated string.
 
 
 
==== Literal Mode ====
 
 
 
There are a few places where the substitution mode is literal. In these places, attribute value are used exactly as provided, nothing is substituted, and the <tt>$</tt> will not have special significance. The following places use the literal mode:
 
* value of '''literal=''' inside [set_variable]
 
* contents of '''[literal]''' inside [set_variables]
 
 
 
=== Automatically Stored Variables ===
 
* '''side_number''': the number of the current player's side (may be empty during start or prestart events)
 
* '''turn_number''': the number of the current turn (may be empty during start or prestart events)
 
* '''x1''': this is the x-coordinate of the location where the most recent event was triggered
 
* '''y1''': this is the y-coordinate of the location where the most recent event was triggered
 
* '''x2''': this is the x-coordinate of the location that assisted in triggering the most recent event
 
* '''y2''': this is the y-coordinate of the location that assisted in triggering the most recent event
 
* '''unit''': inside an event, this is the unit at $x1,$y1
 
* '''second_unit''': inside an event, this is the unit at $x2,$y2
 
* '''this_unit''': inside a standard unit filter, this is the unit currently being considered for a possible match
 
* '''damage_inflicted''': inside attacker_hits and defender_hits events, this is the amount of damage that was inflicted
 
* '''weapon''': inside attack, attacker_hits, defender_hits, die and last_breath events, this is some information about the weapon that is/was being used by the unit at $x1,$y1. It contains the attributes from [attack], see [[UnitTypeWML]].
 
* '''second_weapon''': inside attack, attacker_hits, defender_hits, die and last_breath events, this is some information about the weapon that is/was being used by the unit at $x2,$y2. It contains the attributes from [attack], see [[UnitTypeWML]].
 
 
 
Note: Automatically stored container and array variables are only stored once that one of their attributes is accessed for the first time. This means that one can sometimes get wrong results, for instance by killing the unit at $x1,$y1 as first action in a moveto event and then accessing $unit.something. This can be worked around by previously making a dummy access, such as adding 0 to hitpoints.
 
 
 
=== The [variables] tag ===
 
 
 
The [variables] tag is used in saved games to describe the current value of each variable, and in scenario files for assigning initial values to variables at scenario start.
 
 
 
A scalar variable is assigned using an attribute, where the attribute's key is the variable's given name, and the attribute's value is the value to be stored in the variable.
 
 
 
A container variable with given name ''foo'' is assigned using a [foo] tag that contains the definitions for the contained variables.
 
 
 
An array variable with given name ''foo'' is assigned using several [foo] tags, where the first tag describes foo[0], the second foo[1], ...
 
 
 
=== Storing variables inside units ===
 
 
 
Sometimes it is useful to store a custom WML variable inside a unit. Units stored with the [[InternalActionsWML#.5Bstore_unit.5D|[store_unit]]] command have a '''unit.variables''' sub-container where custom variables related to that unit may be saved. (Remember to [[DirectActionsWML#.5Bunstore_unit.5D|[unstore_unit]]] for the changes to be kept.) One benefit of this approach is that the unit may then be [[FilterWML|filtered]] based on the value, for example:
 
[filter]
 
  [filter_wml]
 
    [variables]
 
      my_variable="test"
 
    [/variables]
 
  [/filter_wml]
 
[/filter]
 
 
 
=== Variable Usage Examples ===
 
Consider a saved game with the following [variables] tag (or a freshly started scenario with that tag)
 
[variables]
 
    attitude_of_elves=hate
 
    attitude_of_dwarves=love
 
    attitude_of_humans=like
 
    current_opponent=elves
 
[/variables]
 
  
Then,
+
== Comments ==
[message]
 
    message="Oh, I see $current_opponent|! They surely $attitude_of_$current_opponent|| us!"
 
[/message]
 
displays the message
 
Oh, I see elves! They surely hate us!
 
  
Consider another game with variables
+
Comments are indicated by a pound sign (<code>#</code>) unless in double quotes. Unless the line forms a valid [[PreprocessorRef#Preprocessor_directives|preprocessor directive]], all text after the pound sign will be ignored by the WML engine. Note that if the beginning of the line is a valid preprocessor directive, which is then followed by ''another'' pound sign, the second pound sign will still be interpreted as a comment character. For example, this works:
[variables]
+
<syntaxhighlight lang="wml">
    our_side=1
+
#ifdef FOO
    their_side=2
+
#endif # FOO
[/variables]
+
</syntaxhighlight>
where side 1 has 75 gold, and side 2 50 gold. Then,
+
Whether or not doing so is a good idea is a stylistic choice.
[store_side]
 
    side=$our_side
 
    variable=we
 
[/store_side]
 
[store_side]
 
    side=$their_side
 
    variable=they
 
[/store_side]
 
[message]
 
    message=We have $we.gold gold, they have $they.gold gold.
 
[/message]
 
[if]
 
    [variable]
 
        name=we.gold
 
        greater_than=$they.gold
 
    [/variable]
 
    [then]
 
        [message]
 
            message=This should be easy!
 
        [/message]
 
    [/then]
 
    [else]
 
        [message]
 
            message=This will not be easy!
 
        [/message]
 
    [/else]
 
[/if]
 
[clear_variable]
 
    name=we
 
[/clear_variable]
 
[clear_variable]
 
    name=they
 
[/clear_variable]
 
displays the messages
 
We have 75 gold, they have 50 gold.
 
This should be easy!
 
If side 2 had 100 gold instead, the same code would display the messages
 
We have 75 gold, they have 100 gold.
 
This will not be easy!
 
  
The code
+
It is a very good coding convention to always add a space immediately following a pound sign for every comment. Not only does it avoid accidentally calling a preprocessor directive (for example, a commented line that begins with the word “define”) but it also makes comments stand further apart from the code.
[store_unit]
 
    [filter]
 
        canrecruit=yes
 
        side=1
 
    [/filter]
 
    variable=leader
 
[/store_unit]
 
[message]
 
    message=Our leader's first attack does $leader[0].attack[0].damage damage per hit.
 
[/message]
 
[clear_variable]
 
    name=leader
 
[/clear_variable]
 
always displays a true sentence.
 
  
You may find more complicated examples of variable use in the [[UsefulWMLFragments]] section.
+
Specially-formatted comments are frequently used to give commands to the Wesnoth [[MaintenanceTools|maintenance tools]] to suppress false positives and enhance their coverage, as well as for adding explanatory comments for [[GettextForWesnothDevelopers#Marking_up_strings_in_WML|translatable strings]].
  
 
== See Also ==
 
== See Also ==

Latest revision as of 03:36, 23 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, credits_group, criteria;

D:

damage, 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, found_item, for, foreach, 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, 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, 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;

The Wesnoth Markup Language (WML) is used to code almost everything in Wesnoth, including scenarios, units, savefiles, and the user interface layout. WML files are simple, human-readable text files, usually with the .cfg extension, with similarities to INI files and XML. For guidelines on keeping these files easily human-readable, see ConventionsWML.

Tag and Attribute Structures

WML has a syntax containing two basic elements: tags and attributes. Furthermore, attributes consist of keys and values. For example:

[tag]
    key=value
[/tag]

Tags are used to partition information, while the data is contained in the attributes. Keys identify the type of data to be stored and values are the actual data stored. When WML is processed, the tag identifies some unit of information, such as an action to perform or even an entire campaign. This gives a context for the attributes within the tag. For each key=value line within a tag, the attribute identified by key has its data set to value. Also allowed inside a tag is another tag. The inner tag is considered the child of the outer tag, as in the following example.

[parent_tag]
    key1=value1
    [child_tag]
        key2=value2
    [/child_tag]
[/parent_tag]

Every tag describes something different about the game; different tags work differently, with the allowed tags defined by context. There are several "top-level tags" that are allowed when not inside any other tag, and each tag defines which child tags (and which keys) it recognizes. Unrecognized tags and keys, such as the result of typos, sometimes produce error messages, but at other times they are ignored. The WML schema defines what is allowed and where. Although it's not designed to be read by humans, you can use it to automatically detect if you've done something wrong even in contexts where unrecognized keys and tags would be ignored, though it still won't work in contexts where you're allowed to define the contents however you like.

Keys should not be confused with variables! A common mistake among beginners is to make up undocumented key names. Instead, consult the WML Reference to find allowed key names for each tag. For a list of all tags with links to their documentation, see the "WML Tags" navigation box.

Also, tag and key names follow a special format. They will contain only alphanumeric characters and underscores; in particular, they cannot contain +, -, or whitespace. The values, however, may contain such characters when needed. A key or tag name beginning with a digit or even consisting of entirely digits is permitted. Tag and key names are case sensitive.


Tag Amendment Syntax

Inserting a plus sign (+) before a tag name allows one to append to an earlier tag (the most recent with the same name) rather than starting a new tag. This allows attributes to be added or replaced.

[tag]
    key=value
[/tag]
[+tag]
    key=value
[/tag]
  • All keys in the +tag will be set to the given values. If the keys did not exist in the most recent [tag] then they are added to that [tag]; otherwise their values will replace the old values in the most recent [tag].
  • Any child tags of the +tag will be appended to the children of the most recent [tag]. To be clear: none of those original child tags will be altered by this operation, since this is an "append" and not a "merge."
  • It is even possible to make tag amendments to a child tag after the parent tag has already closed. Using [+tag] syntax multiple times in a row (first for the parent, then for the child) will allow you to amend the more inward scopes.

Multiple Assignment Syntax

It is possible to set multiple attributes on a single line. This is done by listing the associated keys, followed by an equal sign, followed by the desired values.

[tag]
    key1,key2,key3=value1,value2,value3
[/tag]

would be the same as:

[tag]
    key1=value1
    key2=value2
    key3=value3
[/tag]
  • If there are extra keys, they will be set to an empty value. If there are extra values the last key will be set to the comma-separated list of all remaining values.
  • It is recommended not to use this syntax with keys which normally interpret commas specially (such as x and y in a StandardLocationFilter), to avoid confusion on which key receives which value. However, using x,y=12,10 for single coordinates is widely used and is an exception to the recommendation.

Special Attribute Values

Although an attribute's value can be just text corresponding to the function of its key, a value can also be encoded in many other ways, each with a specific purpose.

  • key = "value": a quoted value is a value surrounded by quotes. This is often unnecessary as single-line values are typically interpreted as intended. However, quotes are required in order to specify multiple-line values (a line break without quotes would otherwise end the value). Quotes may also be required to cancel the special meaning of other characters, and they prevent spaces from being stripped – without quotes, all leading and trailing spaces would be removed, and internal runs of spaces would be replaced by a single space. It is never wrong to use quotes with correct WML.
  • key = _"value": a translatable value is a value that is subject to translations, and should be used for all text intended to be shown to a player (most notably seen in [story], [message], and the name= key in unit definitions). A translatable value is surrounded by quotes and preceded by an underscore (_). In terms of WML syntax, it behaves very much like a quoted value, other than being unsuitable for comparisons to other values. Translatable values are intended for display on the screen, not for internal data. See TranslationsWML and GettextForWesnothDevelopers for more information.
  • key = "value1" + "value2": string concatenation is performed with the plus sign (+). If a plus sign appears outside quotes in a value, it means that the string/value on its right will be appended to the string/value on its left. To have an actual plus sign in a value, the string containing the + character must be surrounded by quotes (a quoted value or a translatable value). Quotes are not strictly necessary around the pre-concatenated values, but they are advisable so that it is easy to tell where the values begin and end and to spot some kinds of mistakes. If two non-quoted values are concatenated, they will have a space inserted between them, but if either value is quoted, no space will be inserted.
  • key = "quoted ""double quoted value"" value": doubled quotes can be used to create quote marks within a quoted or translatable value. The doubled quote mark in the value produces one quote mark in the stored data and does not terminate the quoted value. (These do not necessarily need to be used in pairs.)
  • key = $variable: a variable substitution sets the key to the value of the indicated WML variable. This is indicated by the dollar sign ($) and is really just a special case of general variable substitution, as variables can be substituted within other values. See VariablesWML for more information on values based on WML variables. (Note that some keys require their data to be a variable name, not the variable's value; in that case there would be no dollar sign.) Variable substitution is supported in only a few contexts, such as in IntroWML and EventWML.
  • key = "$(formula-expression)": a formula expression sets the key to the value of the processed formula. This is indicated by a dollar sign ($) followed by a parenthesized expression. See Wesnoth Formula Language for more information on formula basics, data types, and built-in functions. Quotes around the formula are not strictly necessary in all cases, but they are advisable, particularly since quotes are the only way to use a plus sign (+) within a formula (without quotes, the plus sign represents string concatenation). Formula expressions are only supported where variable substitution is supported.
  • key = <<value>>: similar to a quoted value but stronger: the value is hidden from the preprocessor, which will see all text therein as literal. Useful with LuaWML or whenever a literal curly brace ("{", a US-ASCII 0x7B) is needed in any text string. This can also be combined with the translatable mark, in case curly braces are needed in translatable text.

Comments

Comments are indicated by a pound sign (#) unless in double quotes. Unless the line forms a valid preprocessor directive, all text after the pound sign will be ignored by the WML engine. Note that if the beginning of the line is a valid preprocessor directive, which is then followed by another pound sign, the second pound sign will still be interpreted as a comment character. For example, this works:

#ifdef FOO
#endif # FOO

Whether or not doing so is a good idea is a stylistic choice.

It is a very good coding convention to always add a space immediately following a pound sign for every comment. Not only does it avoid accidentally calling a preprocessor directive (for example, a commented line that begins with the word “define”) but it also makes comments stand further apart from the code.

Specially-formatted comments are frequently used to give commands to the Wesnoth maintenance tools to suppress false positives and enhance their coverage, as well as for adding explanatory comments for translatable strings.

See Also

This page was last edited on 23 February 2024, at 03:36.