WMLsyntax ch

From The Battle for Wesnoth Wiki
Revision as of 11:57, 10 November 2013 by Yiyuezhuo (talk | contribs)

[edit]WML Tags

A:

abilities, about, add_ai_behavior, advance, 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, attack_anim, attacks, avoid;

B:

base_unit, berserk, binary_path, break, brush;

C:

campaign, cancel_action, candidate_action, capture_village, case, chance_to_hit, change_theme, chat, choose, clear_global_variable, clear_menu_item, clear_variable, color_adjust, color_range, command (action, replay), continue, 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, era, event, 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_vision, filter_weapon, filter_wml, find_path, fire_event, firststrike, floating_text, for, foreach, frame;

G:

game_config, get_global_variable, goal, gold, gold_carryover;

H:

harm_unit, has_ally, has_attack, has_unit, 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), illuminates, image, 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, portrait, post_movement_anim, pre_movement_anim, primary_attack, primary_unit, print, 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_unit_overlay, repeat, replace_map, replace_schedule, replay, replay_start, reset_fog, resistance (ability, unit), resistance_defaults, resource, return, role, rule;

S:

save, scenario, scroll, scroll_to, scroll_to_unit, secondary_attack, secondary_unit, section, select_unit, sequence, set_extra_recruit, set_global_variable, set_menu_item, set_recruit, set_specials, set_variable, set_variables, sheath_weapon_anim, show_if (message, set_menu_item), show_objectives, side, skirmisher, 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_type, store_unit_type_ids, store_villages, story, swarm, switch, sync_variable;

T:

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

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;

韦诺标记语言 (WML)被用于编码几乎所有在韦诺里的事物,包括剧本,单位,存档文件以及用户交互接口,WML文件时简单,易读的文本文件,经常以.cfg后缀标出,与ini与XML文件非常类似。 关于如何使这些文件写的更易读,见 ConventionsWML.

标签和属性结构

WML有一个包含两个成员的语法结构: 标签 and 属性. 其中属性又由(keys)与(value)组成。作为例子:

 [tag]
     key=value
 [/tag]

标签用于区分信息,直到一个数据被包含在属性里。键标出保存的数据的数据类型而值真正保存它们。当一个WML文件执行,标签识别成一些信息单元,如一个执行行动或一整个战役。这给了一个在一个标签内的属性一个上下文(context)。像每个在一个标签内的key=value行,其值被算进那个标签内。 标签也可以出现在另一个标签里,里面的标签被认为是包围它的标签的子标签,像下面的例子一样.

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

每个标签介绍了一些不同的东西关于这个游戏;不同的标签以不同的方式发挥作用,但那些标签必须在上下文中有意义。这是一些 "top-level tags" ,这是一些不在任何其他标签内就可使用的标签,以及这些标签允许使用的子标签(以及键)。不能被理解的标签和键,如错别字,有些时候会产生错误信息,但是多数时候它们被无视掉。

键不能与变量混淆! 一个常见错误在初学者那里就是使用一个没有上下文意义的名字。相反,应使用在WML标准里能被找到的,具有上下文意义的,处于某个标签下的键名。所有这些标签下的键名字可以在这个文档AlphabeticalWML 中查到,或者WML Tags 导航框。

此外,对于标签和键的名遵循一个特殊形式。它们必须由字母数字与下划线组成,特别是不能有什么+ -之类的运算符(它们有特殊意义,见下)。不过,对于值来说它们可以包含任何它们需要的符号。


标签修正语法

插入一个加号(+)在一个标签前面名的标签形式允许追加到一个同名的(除去+后)较早的标签。这允许属性的增加或覆盖。

 [tag]
     key=value
 [/tag]
 [+tag]
     key=value
 [/tag]
  • 所有在+tag(追加的标签代称)里的键必须设置一个给定的值。如果这个键不存在于想要追加的标签,则它们会被添加到要追加的那个标签里。其他情况下它们的值会替换老值在所追加的标签。
  • 任何在+tag里出现的子标签会被追加到对应标签子标签中。澄清一点:所追加标签的子标签不会因此被改变,这是一个追加(append)而不是一个合并(merge)
  • 还可以在一个标签外部修正这个标签的子标签,只要在修正子标签被修正父标签包围即可。这加强了修正的能力。

多行赋值语法

在一行内多次赋值是可行的。通过用等号分隔的几个键与几个值的形式。像这样:

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

这等价于

 [tag]
     key1=value1
     key2=value2
     key3=value3
 [/tag]
  • 允许两边项数不对称。当键更多时,从左数起没有对应值得键被赋空值。当值更多时,最后一个可对应的值以及后面所有的值作为一个表赋给最后一个键。

特殊属性值

一个属性值除了被赋予纯文本,也可以赋予其他形式,这些形式有不同的意义。

  • 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 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.
  • 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.
  • 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.
  • 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 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 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 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 (+) within a formula (without quotes, the plus sign represents string concatenation). Formula expressions are only supported where variable substitution is supported.

Variables

Variables in WML are used to store data for later retrieval. Each variable is identified by its name, which may contain only alphanumerics and underscores. Once created, a variable persists until the end of a campaign unless explicitly cleared.

The three basic manipulations of WML variables are assigning a value, querying the value, and clearing the variable.

  • Assigning to a variable: stores a value in the variable. This is done with tags like [set_variable] or with macros like {VARIABLE}.
  • Querying a variable: returns the last value stored in the variable (or the empty string, if no value was). This is done by prefixing the variable name with a dollar sign, as in $variable, and sometimes ending the variable name with a pipe character, as in $variable|.
  • Clearing a variable: makes the WML engine forget about that variable. This is useful for reducing overhead, since all used variables are stored in saved games. This is done with [clear_variable] or the {CLEAR_VARIABLE} macro.

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 (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 foo is the name of an array, foo[0] is the full name of its first container variable, foo[1] the full name of its second, and so on. foo.length is the special variable that always stores the number of containers in the array foo. Hence, if the value stored in foo.length is 18, the last container in the array would be foo[17]. 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 foo[3] as if it were a scalar one is illegal; instead, you would use foo[3].value 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 bar stored in a container foo you would write foo.bar. 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 $, the WML engine with interpret what is between the rightmost $ and the next | as a full variable name to be queried, and replace $variable| with the result of this query.

In certain situations, the | 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 $ will not have special significance. The following places use the literal mode:

  • value of literal= inside [set_variable]
  • contents of [literal] inside [set_variables]
  • the special [variables] tag, used to give initial values to many variables upon scenario start

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, attack_end, attacker_hits, attacker_misses, defender_hits, defender_misses, 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, attack_end, attacker_hits, attacker_misses, defender_hits, defender_misses, 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 [store_unit] command have a unit.variables sub-container where custom variables related to that unit may be saved. (Remember to [unstore_unit] for the changes to be kept.) One benefit of this approach is that the unit may then be 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,

[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

[variables]
    our_side=1
    their_side=2
[/variables]

where side 1 has 75 gold, and side 2 50 gold. Then,

[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

[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.

Comments

Comments are indicated by starting a line with a pound sign (#). Unless the line forms a valid preprocessor directive, all text after the pound sign will be ignored by the WML engine.

See Also