Syntaxwml/zh-Hans
韦诺标记语言 (WML)被用于编码几乎所有在韦诺里的事物,包括剧本,单位,存档文件以及用户交互接口,WML文件时简单,易读的文本文件,经常以.cfg后缀标出,与ini与XML文件非常类似。 关于如何使这些文件写的更易读,见 ConventionsWML.
Contents
标签和属性结构
WML有一个包含两个成员的语法结构: 标签 与 属性. 其中属性又由键(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标准里能被找到的,具有上下文意义的,处于某个标签下的键名。或者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": 引用形式:引用形式无条件的将双引号包围的内容当做一个文本值。这提供了可写多行的值和转义能力(双引号自己的转义使用连双双引号,"" 见下)。不过在多数时候并不用写出这一形式,如果没有特殊情况,一段文本自动当做加上了双引号组。
- key = _"value": translatable value 可翻译形式:使用一个下划线(_)与一个引用形式组合的形式。这一形式的文本可以被翻译comparisons to other values. ,自然它应该只用于会对外显示的文本而不是内部数据。除此以外它与引用形式工作方式一样。
- key = "value1" + "value2": 字符串连接:这种形式下两个字符串将从左往右连接作为一个新字符串。显然,由于这种形式的存在,要想在文本里表示加号必须使用引用形式。
- key = "quoted ""double quoted value"" value": 字符串转义:由于双引号表示引用,要想在文本里表示字符串必须使用两个双引号连在一起的形式。注意这并不需要成对使用。
- key = $variable: 变量代入形式:键将被赋给所标示的WML变量所含有的值。变量通过美元符号($)标示,这种标示法只是一般的变量代入法的特殊情况。看之后的内容获得更多关于WML的信息。(注意:一些键需要的是变量的名字而不是变量的值,这时候不加$)。变量代入有一些支持文档,如IntroWML 与 EventWML.
- key = "$(formula-expression)": 格式化表达式:格式化表达式是引用形式的特殊情况,这时有如上形式的表达式$(formula-expression)不会作为文本本身,而是代入对应变量所记录的字符串描述的表达式返回的字符串以生成新字符串。这有时可以理解为"string1"+$string-variable+"string2"的一种简写。更多关于formula的信息见FormulaAI.
变量
变量是WML用来暂时保存值延后再用的.每个变量被识别通过它的名字,这个名字只能包含字母数字和下画面。变量一建立就一直存在直到战役结束或被明确指出清空。
以下是三种简单的WML变量的操作方式,赋值,获取值与清空变量。
- 变量赋值: 保存一个值到一个变量当中去的操作。这通过像 [set_variable]或宏 macros 像这样 {VARIABLE}.
- 变量取值:返回最后被保存在变量的值(或空字符串值,如果这个变量还没创建)。需要使用美元号加变量名为标示出是哪个变量,如$variable,有时变量名后面会加竖线|,如$variable|.
- 清空一个变量:让WML系统忘记一个变量。这在保存游戏时减少存档大小方面有用。 [clear_variable] 以及 {CLEAR_VARIABLE} macro.
变量类型
标量
一个标量变量可以存储一行文本或数字。
[set_variable] name=my_variable value="sample value" [/set_variable]
标量变量的全名就是给它的名字,如my_variable。注意变量的值可以是可翻译形式或是一个格式化表达式,见特殊属性值节。(Special Attribute Values).
数组
一个数组变量是一个由容器变量组成的序列。存在一些特殊的标签指派数组的信息。如[store_unit]和[store_location].创建一个数组使用[set_variable]像这样:
[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]
不过一般可以使用一种更简单的写法创建的一个数组如使用[set_variables]。这将可以写成这种形式:
[set_variables] name=my_awesome_array [value] x=10 [/value] [value] x=12 [/value] [value] x=14 [/value] [/set_variables]
如果foo是数组的名字,那么foo[0]就是第一个容易变量的全名,foo[1]是第二个,以此类推、foo.length是一个特殊变量,它储存数组中的容器数目。比如若foo.length为18,则这个数组的最后一个容器就是foo[17].如果你想取一整个数组作为值,那么只要使用第一个索引[0]。一般的,$foo.bar 等价于$foo[0].bar.
注意:不要尝试像保存一个标量值一样保存数组容器变量值。如foo[3]并不是一个标量,不能直接赋值。而应使用foo[3].value形式。(虽然某些情况下可以使用那种形式,如果你无视这条规则,它将在更多时候出现不确定的行为。如载入一个文档存档文件时出现WML错误)
容器
一个容器变量可以保存任何数量的标量或数组变量。存在一些标签指派特殊信息,如[store_side]。若一个变量bar被保存到一个容器foo,你可以用foo.bar调用。一个数组加一个索引构成的项也被认为是一个容器变量而不是标量。
条件分支
变量可以被用在所谓的分支块内,如让[variable]在[if]或[while]标签里。更多信息请参考,ConditionalActionsWML.
变量代入
当使用一个有一个$号在变量名前的形式,那么这个形式将被"代入",即将这个形式换成之前保存在变量名所代表的的变量里的内容。如:
[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]
上面的WML代码导致德叔说:"你好,科纳德,最近过的怎么样",在第一回合。
当写一个剧本事件(EventWML), 一个出现在赋值表达式(key=value形式)右边的变量可能被代入。如果值的任何部分前面有$,WML解释器会将其视为一个代入的申请,并分析出变量全名(通过空格或|),找到变量的值,然后置换掉发出询问的形式。
在不引起歧义的情况下,|号可以省略。确切的规则是:如果没有|,被识别的变量名会跨过字母,数字,下划线,方括号和一些句号。不过连续两个句号等非法形式不包括在内。如果变量名为空就结束(例: 当使用 $| 时),那么$相当于被转义,表达$字符本身的意思。给了一个机会简单的在字符串中表示$。
原义模式
存在一些场合你可以让代入不发生让文本像原先写的那样显示出来。如$在这里就可以直接写而不用$|形式。下面场合使用了原义模式:
- literal属性值= 在[set_variable]内部
- [set_variables]里[literal]里的内容
- 特殊[variables]标签,初始化时。
自动内建变量
- side_number:玩家当前在控制的方面的序号(在初始化时可能为空)。
- turn_number:当前回合数(可能为空在初始化时)
- x1:这个是最近触发事件的位置的x坐标
- y1:这个是最近触发事件的位置的x坐标
- x2:这个是最近协助事件触发的位置的x坐标
- y2:x2:这个是最近协助事件触发的位置的y坐标
- unit:在事件内部,在x1,y1的单位
- second_unit:在事件内部,在x2,y2的单位
- this_unit:在一个标准单位筛选器内部,当前那个符合筛选规则的单位。
- damage_inflicted: 在attacker_hits 与defender_hits 事件内部, 造成的损伤的数量。
- weapon: 在attack, attack_end, attacker_hits, attacker_misses, defender_hits, defender_misses, die 以及 last_breath 事件内部, 这是一些关于在x1,y1的单位使用的装备的信息,它的属性来自[attack]表现,见 UnitTypeWML.
- second_weapon: 在attack, attack_end, attacker_hits, attacker_misses, defender_hits, defender_misses, die 以及 last_breath 事件内部, 这是一些关于在x2,y2的单位使用的装备的信息,它的属性来自 [attack]表现,见 UnitTypeWML.
注意:自动内建变量容器和数组变量只被保存一次到它们的属性之一被第一次访问时。这意味着有时会获得错误的结果,例如杀死一个单位在$x1,$y1作为一个moveto的第一个动作,然后取出$unit.something的值。这将造成一次虚假的取值,如增加0到HP上。
[variables]标签
[variables]标签用来保存游戏,其描述当前变量的每个值。并且在剧本文件用于赋初值给变量在剧本初始化时。
一个标量变量可被赋值使用一个属性,这个属性的键是变量的名,这个属性的值时变量保存的值。
一个名为foo的容器变量被赋值使用一个[foo]标签,它包含其定义的变量。
一个名为foo的数组使用一系列[foo]标签,第一个叫foo[0],第二个叫foo[1]。。。
单位内部变量
有时在一个单位里保存一个自定义的WML变量是有用的。使用[store_unit]命令,可以为单位附加一个unit.variables自定义子容器变量,这个变量可以被保存。(记住 [unstore_unit] 可以使变化被保存.) 使用这种方式的一个好处是可以使用基于值的筛选器 filtered .例如:
[filter] [filter_wml] [variables] my_variable="test" [/variables] [/filter_wml] [/filter]
变量用法示例
考虑一个使用[variables]标签存档的游戏(或初始化剧本时使用这个标签)。
[variables] attitude_of_elves=hate attitude_of_dwarves=love attitude_of_humans=like current_opponent=elves [/variables]
然后
[message] message="Oh, I see $current_opponent|! They surely $attitude_of_$current_opponent|| us!" [/message]
打印出信息
Oh, I see elves! They surely hate us!
考虑其他游戏变量
[variables] our_side=1 their_side=2 [/variables]
side 1 有75金币,side 2有50金币。然后
[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]
打印出这个信息:
We have 75 gold, they have 50 gold. This should be easy!
如果side 2有100金币,类似的代码将打印出
We have 75 gold, they have 100 gold. This will not be easy!
代码
[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]
将打印出一句正确的描述
你能找到更多复杂的变量例子使用方式在UsefulWMLFragments 章.
注释
注释用一个井号(#)开头。除非这行是一个预处理指令preprocessor directive, 所有这样的注释会被WML解释器无视。