命令条件语¶
什么是命令条件语?¶
命令条件语是插入在宏命令中,使宏根据条件执行不同功能的语句。举个例子,下面这个宏的作用是,如果是友方目标就施放恢复,如果是敌方目标就上痛:
/cast [help] 恢复; [harm] 暗言术:痛
当这个宏执行时,首先检查[help]条件,判断当前目标是否是一个可以接受治疗/增益法术的目标。如果[help]条件成立,那么就施放恢复并执行下一条命令,否则(即没有目标,或目标不接受有益技能)继续执行下一个子句,也就是分号后[harm]那里,再判断[harm]条件。[harm]条件和[help]条件相反,判断目标是否接受敌对法术。同上,如果条件成立就释放“暗言术:痛”并执行下一条命令。如果条件不成立,由于后面没有其他子句,这条宏命令就算执行完了,但是什么动作都没有做。 注:如果没有写[harm]条件,实际运行效果是差不多的。不过,如果你没有目标或者当前目标不接受任何法术,那么屏幕上将会出现错误信息,或者对于某些技能,鼠标将会变成选择施放目标的状态。
可以使用条件语的命令¶
只有那些“安全化”命令可以接受命令条件语。其实正是经过安全化的命令才需要条件语。常规命令,比如说聊天、表情之类的,可以通过脚本来实现命令条件语的功能。而且暴雪不想限制大家在聊天时使用分号(;)。如果/s命令可以使用命令条件语的话,那么下面这个命令就会只说hello:
/say Hello; I’m a n00b
以下是当前客户端中安全化命令的列表:
show[1]
showtooltip[1]
/assist
/cancelaura
/cancelform
/cast
/castrandom
/castswquence
/changeactionbar
/clearfocus
/cleartarget
/click
/dismount
/equip[2]
/equipslot[2]
/focus
/petagressive
/petattack
/petautocastoff
/petautocaston
/petdefensive
/petfollow
/petpassive
/petstay
/startattack
/stopattack
/stopcasting
/stopmacro
/swapactionbar
/target
/targetenemy
/targetfriend
/targetlasttarget
/targetparty
/targetraid
/use
/userandom
[#1]:#show和#showtooltip不是真正意义上的安全化命令,但是它和/use以及/cast的内部机制相仿。 [#2]:/equip和/equipslot逻辑上也不算是安全化命令,因为它们的功能是可以通过插件和脚本实现的。 当然,如果你希望在常规命令中使用命令条件语,就需要安装专门的插件。MacroTalk,这是我的一个作品,通过在非安全化命令前添加/opt,然后在/opt中处理各类条件来实现对不同命令的调用(当然只能是非安全化命令)。最新版的SuperMacro中应该也有类似的功能。
[target=]条件语¶
该条件语使得宏命令除了可以对条件进行判断外,还可以设置动作的目标。例如,下面这个宏运行时,无论当前目标是谁,玩家只会给自己绑绷带:
/use [target=player] 厚灵纹绷带
Target条件语在指定动作目标的同时,也指定了进行条件判断的目标。下面这个垃圾宏是一个纯教学例子,看我的说明:
/cast [help] [target=targettarget, help] [target=player] 快速治疗
这个宏运行的时候,首先会检查[help]条件。如果条件为真,那么就开始吟唱快速治疗。否则就跳至第二个条件,[target=targettarget, help]。此时,判断目标和技能目标都被设定为你当前目标的目标,然后进行help条件判断。如果条件成立就对你当前目标的目标施放快速治疗,否则再跳至第三个条件。而第三个条件总是成立的,所做的只是把你自己当作施法目标。
语法¶
命令条件语是按什么规则生效的?恐怕要回答这个问题很容易引起混乱。所以,趁还没有正式开始讲,我先用一些现实生活的例子做类比。看不懂不要紧,这只是些概念,技术性的内容后面都还会再提到的。
条件语语法简介¶
所有的宏命令的基本工作方式是相同的:一个命令,后面带上一个或多个参数(取决于命令的要求,有些甚至不需要任何参数)。看下面这些例子:
/cast 猛击
\___/ \___/
| |
| 参数
|
命令
/petattack
\_______/ \/
| |
| 参数(为空)
|
命令
/castsequence reset=target 献祭, 腐蚀术, 痛苦诅咒, 生命虹吸
\_________/ \_______________________________________/
| |
命令 参数
而命令条件语可以通过对一组条件进行的判断来选择命令的实际参数。首先,可以用分号分隔出若干个“若干组条件+参数”这样的子句,逻辑上,分号就相当于高级语言中的else或是elseif。条件的组数不定,也可以没有,同一组条件用一个方括号括在一起。而每组条件中有可以包含多个条件。就像这样:
/命令 [一组条件] [另一组条件] 参数1; [又一组条件] 参数2; ...
前面的例子已经说明了,宏命令的解释过程是从左至右的。当一组条件被判定成立时,命令就会采用其对应的条件。如果某一个子句中不包含条件,那么就被无条件判定为成立。像/cast XXX这种简单的宏命令就可以理解为一个只有一个子句的宏,而这个子句又不包含条件。而如果一个宏的任何一组条件都不为真,那么它就完全不会执行。
条件语法¶
每组条件都是由逗号分隔的一些条件语组成的,各条件不分前后次序。逻辑上,[target=]总是先发生作用,然后其他的条件才进行判定。逗号在这里可以理解为“并且”,也就是说各条件简是逻辑“与”的关系。比如[help, nodead, target=focus]的含义就是:我的焦点是友善的,并且是只活的。 注意:条件是对大小写敏感的,如果你把[help]写成了[Help],宏运行时会报错。 条件中有组合式的使用方式,比如nodead,同样对于help,你可以用nohelp表示相反的条件。但是nohelp不等于harm:首先,help和harm都要求目标存在才有可能成立;其次,有些目标,比如中立阵营NPC、非战斗宠物或者护送任务NPC等,既不算help,也不算harm。 还有些条件可以指定一些特定的参数。比如[stance],姿态,单独使用时表示“在任一姿态中”(显然这对战士来说是废话一句)。如果给它加上参数,就可以指定在某个姿态下,格式是在条件语后写上冒号(:),然后后面写上参数,每个参数间用斜线(/)分隔。综上所述,一个条件语的完整格式如下(<>表示其中的部分是可选的):
[<no>condition<:parameter</parameter</parameter<…>>>>]
下面举个例子,如果在战斗或防御姿态施放盾击,否则转入防御姿态:
/cast [stance:1/2] 盾击; 防御姿态
这个宏用伪代码写的话就是:
IF 当前在姿态1或姿态2
THEN 用盾击
ELSE 切换防御姿态
注意:“no”前缀是对整个条件和所有参数的修饰,即把原来的真变为假,假变为真。比如[nostance:1/2]表示“不在姿态1也不在姿态2中”。
完整的EBNF语法¶
对EBNF规范很熟悉的人,以上内容可以概括为:
command = "/", command-verb, [ {command-object, ";" } command-object] ]
command-verb = ? any secure command word ?
command-object = { condition } parameters
parameters = ? anything which may be passed to the command word ?
condition = "[" condition-phrase { "," condition-phrase } "]"
condition-phrase = [ "no" ], option-word, [ ":" option-argument { "/" option-argument } ]
option-argument = ? any one-word option, such as 'shift, 'ctrl', 'target', '1', '2' ?
参数为空¶
有些命令是可以没有参数的,这里就存在着一个陷阱。比如:
/petattack [target=focus, harm];
很多初学者一看,认为这个宏的含义应该就是判断焦点是否为敌对,如果是,就把宠物送上去咬。而实际上呢?让我们分析一下:
/petattack [target=focus, harm] ;
\________/ \______________/ V V V
| | | | |
命令 条件语1 | | 参数2 (为空)
| |
| 条件语2(为空)
|
参数1 (为空)
现在看出来了吧?由于那个分号的存在,这个语句实际上包含两个子句,而一个条件语为空的子句是被当作条件成立处理的,因此即使前面的条件语1不成立,也会执行一个/petattack。
条件为空¶
有时我们需要在特定条件下对特定目标施放技能,并在条件不成立的情况下按常规施放。这中效果可以通过使用一组空条件来获得。下面例子中的宏在执行时会对你鼠标指向的友方单位施放圣光闪现。如果鼠标没有指向任何单位或者指向的目标不是友善的,那么就会按常规对当前目标施放,或者根据设置(如自动自我施法、自我施法功能键)对自己施放:
/cast [target=mouseover, help] [ ] 圣光闪现
[target=]条件语与命令参数¶
很多命令的参数是可以直接指定目标的。比如/target party1就可以把小队中第一个队友作为你的目标。而用/target [target=party1]的话,虽然看起来别扭,但是效果也是一样的。但是宏的设计者不希望我们根据一个单位的状态而对另一个单位执行动作,因此大多数情况下[target=]条件和命令参数只能有一个发生作用。例如:
/target [target=focus, dead] party1
客户端会把party1直接忽略掉——因为你已经指定了[target=focus]。不过这种情况也有例外,就是个别命令拥有一个“特殊单位”(其实也就是该命令会影响的单位标志符)。见下表:
命令 特殊单位
/target target
/focus focus
/startattack target
/petattack pettarget
当在[target=]中使用的是该命令的“特殊单位”时,命令执行目标不会被设置为该单位,而命令参数中指定的目标也不会被忽略。例如:
/focus [target=focus, dead] [target=focus, noharm] target
由于focus是/focus命令的特殊单位,所以/focus的目标就不会被[target=focus]设置成焦点,而是target,即当前目标。如果没有指定target,/focus就相当于没有参数,同样是把当前目标设为焦点。
命令条件语¶
下面给出一张条件总表,每一个条件在后面我都会再给出更详细的介绍。
总表¶
WOW2.0在对宏命令系统的更新中,宗旨就是把玩家从按“一键万能宏”按到手抽筋的状态中“解脱”出来。不过有一些宏的用法是被官方认可了的,它们获得了“玻璃渣祝福”的效果——可以通过使用条件语来重现。 下面列出宏命令系统中支持的所有条件语。如果你需要的判断条件没有在此列出,那么就不可能通过该条件来执行安全化命令的动作。这是中央的死龟腚,谁都没办法,不过以后也有可能会再增加一些。
help 目标可以接受增益法术 harm 目标可以受到攻击 exists 目标存在 dead 目标已经挂了 stance:0/1/2../n 玩家在某姿态下 stealth 玩家在潜行状态下 modifier:shift/ctrl/alt 某功能键被按下 button:1/…/5/<虚拟按键号> 宏通过某键点击执行 equipped:<装备类型> 玩家装备了某类型物品,参见《装备类型》 channeling:<法术名称> 玩家正在引导某法术 actionbar:1/…./6 当前技能栏为某动作栏 pet:<宠物名称或类型> 玩家当前宠物为某宠物 combat 玩家正在战斗状态 mounted 玩家在骑乘状态 swimming 玩家在游泳 flying 玩家在飞行状态 flyable 玩家正处在一个允许飞行的地界 indoors 玩家在室内 outdoors 玩家在户外 party 目标在玩家的小队中 raid 目标在玩家的小队或团队中 group:party/raid 玩家在某集体中(小队/团队)
敌/友(help / harm)¶
没什么好说的,保留空地一块,等待补充。
存在(exists)¶
如果目标存在条件为真。比如[exists],如果你没有目标,该条件就不成立。而对于[target=focus, exists],如果你设置了焦点目标,条件就成立。不过很多情况下该条件用不到,因为[help],[harm],[dead],[party]和[raid]条件成立的情况下,[exists]条件是必定成立的。
死亡(dead)¶
如果判断对象已经挂了,条件就成立。
姿态(stance:0/1/2/…/n)¶
姿态是指对技能能否施放有影响的状态,比如战士的姿态,小德、萨满、暗牧的形态,盗贼的潜行状态。而骑士的光环、猎人的守护都算是姿态。单独用[stance]是指在任意一种姿态下,就相当于[stance:1/2/…/n]这样把所有姿态列出来,对战士来说就是永远成立的。而[stance:0]就相当于[nostance]表示不在任何形态下。而[stance:0/3]就表示在形态3下或者不在任何形态下。 姿态的编号和面板上的顺序是对应的。下面给出各职业的姿态表:
编号 小德 战士 暗牧 盗贼 萨满
1 熊形态 战斗姿态 暗影形态 潜行 幽灵狼
2 海豹形态 防御姿态
3 豹形态
4 旅行形态
5 枭兽/树形态
6 飞行形态
注意:上面给出的是全表。如果少了某个姿态,其下方的形态就依次上移。我承认,我这话是针对小德说的…… 下面给出例子:
/cancelform [nostance:0/1/3]
/cast [stance:1/3] 精灵之火(野性);[nostance] 精灵之火
如果在熊/猫形态,施放精灵之火(野性);在人形态,施放精灵之火;在其他形态就先退出,然后施放精灵之火(WOW2.3以后可以这样,2.3之前该宏只能退出形态)。
潜行(stealth)¶
对于盗贼来说由于 [stance] 的存在反而显得多余。这个是给暗夜、法师、猫德用的,我的意思是它可以用来判断影遁、隐形和猫的潜行。
功能键状态(modifier:shift/ctrl/alt)¶
它是节省技能栏的好帮手,可以让一个宏对不同功能键做不同动作,比如:
/cast [modifier, help] [modifier, target=targettarget, help] 快速治疗; [help] [target=targettarget] 强效治疗术
该宏会依次判断你的目标和目标的目标是否友善,条件成立的话,如果按下了某功能键,施放快速治疗,否则施放强效治疗术。 当然也可以指定特定的功能键。[modifier:shift/ctrl]表示Shift或者Ctrl被按下;如果想表示两个键同时按下则可以这样实现:[modifier:shift, modifier:ctrl]。 但是要注意这样一种情况,比如你的宏是通过A键执行的,然后根据Shift来做判断。但是你的Shift+A被设置了另外一个动作,那么你按下Shift+A的时候,执行的就是其对应的动作,而不是你的宏。另外,modifier可以被简写做mod以节省空间。
功能键变量¶
虽然说mod指定的只能是shift、ctrl或alt,但是还可以通过一些系统变量来间接指定。比如SELFCAST这个系统变量,是指“自我施法功能键”,默认值为alt,可以通过某些插件修改,表示按下该键后执行的动作都是针对玩家自身的。下面看这个例子:
/cast [modifier:SELFCAST, target=player] [target=mouseover] [ ] 强效治疗术
这样的话,不管你系统设置的自我施法键是什么,宏命令都会正常执行。下面给出其他的一些系统变量,括号内为默认值,后面为中文含义:
AUTOLOOTTOGGLE(shift) 自动拾取键
STICKYCAMERRA(ctrl) 镜头跟随
SPLITSTACK(shift) 物品堆叠分离
PICKUPACTION(shift) 拖动技能栏按钮
COMPAREITEMS(shift) 物品比较
OPENALLBAGS(shift) 打开所有背包
QUESTWATCHTOGGLE(shift) 任务追踪
装备(equipped:<物品类型>)¶
[equipped] 条件可以判断指定类型的物品是否被装备。物品类型号可以是装备栏名称,物品类别或者物品子类别。比如我根据盾牌装备状态判断该用盾击还是拳击:
#show [equipped:Shields] 盾击; 拳击
/cast [equipped:Shields,stance:1/2] 盾击; [equipped:Shields] 防御姿态; [stance:3] 拳击; 狂暴姿态
利用[equipped]这里的#show可以根据装备显示不同的图标。下面的伪代码用来解释上面/cast命令的执行过程:
if 装备了盾牌 and 在防御姿态 then
/cast 盾击
else if 装备了盾牌 then
/cast 防御姿态
else if 在狂暴姿态 then
/cast 拳击
else /cast 狂暴姿态
下面再给出一个变态的压制宏作例子:
/equip [noequipped:Two-Handed Axes] 水晶熔铸战斧
/cast [nostance:1] 战斗姿态; [equipped:Two-Handed Axes] 压制
引导中(channeling:<技能名称>)¶
在引导法术的状态下,如果施放另外一个法术将会打断施法。这个条件语就是用来防止这一情况的。当然,它还有些其他的用途,比如只打断特定的引导技。只用 [channeling] 的话表示正在引导任意技能,或者后面可以指定任意个引导技能的名称表示正在引导其中一个。 注意:引导和吟唱是两码事, [channeling] 条件只对引导技能,如奥书飞弹、吸取生命、精神鞭笞等有用。([nochanneling] 同理)
技能条(actionbar:1/…/6)¶
系统默认的界面中有一个主技能条,可以翻页。而用这个条件就可以根据当前技能页作出不同反应。比如猎人可以拿来把守护做成姿态:
/swapactionbar 1 2
/cast [actionbar:1] 雄鹰守护; 灵猴守护
这样就可以切换1号和2号两个技能页,换到1页时施放雄鹰守护,2页时则施放灵猴守护。
宠物(pet:<宠物名称或类型>)¶
对任何有宠职业来说这个条件都很有用,它可以根据你宠物状态来执行动作,可以根据宠物名字,也可以是类型(比如Voidwalker,Boar,Imp,Wolf等),如果只用[pet]的话表示带着任意宠物。比如法师可以根据是否有水宝宝施放不同的霜星:
/cast [pet] 冰冻术;冰霜新星
战斗(combat)编辑
如果在战斗状态则条件成立。
行动方式、室内外状态(mounted, swimming, flying, indoors & outdoors)¶
这些都无庸赘述,要说的就是它们都是对玩家自身状态的判断,而不是目标。
允许飞行 (flyable)¶
用于判断是否处在可以使用飞行坐骑的地区。
小队/团队队友(party/raid)¶
判断目标是否是自己的小队或团队中的队友。
在小队/团队中(group:party/raid)¶
注意和前面的区别。这个用于判断玩家自己是否处在小队或团队中,并且团队包括小队。这对加状态很有用,比如:
/cast [group, nomodifier] 奥术光辉; [help] [target=player] 奥术智慧
如果在队伍中,施放奥数光辉;如果按下功能键或者不在队伍中则施放奥术智慧。
命令条件语的应用¶
在第一部分中提到的很多命令,如果不配合条件语的使用,是没有什么价值的。而上述内容也只给出了一小部分的应用示例。作为本部分的压轴内容,下面两段将会把你带入一个更高的境界。
设置焦点(focus)¶
focus是一个单位标识符(参见《单位标识符》),就像target、player、raidpet1target一样。你可以将它设定为某一个单位,玩家或者NPC。比较简单的设置方法是通过按键设置。在按键设置中有两个选项:“焦点目标”和“目标焦点”。我不知道这是哪个脑残翻译的,其实际含义分别是“以目标为焦点”和“以焦点为目标”。当你设置了焦点以后,就可以用focus这个标识符了,也可以通过“目标焦点”绑定的按键把你设的focus作为你的当前目标。话说按键绑定也太小儿科了,下面来看看什么是职业玩家的focus用法。 作为一个有控制技能的专业DPS,我们最常用的就是控场宏。我们可以预先把你的“被监护人”设为你的焦点,然后用这种宏来调教他——而此过程中并不用切换目标:
/cast [target=focus] 变形术
而作为一个灰常牛逼灰常娴熟的治疗,你可以把焦点设为你的主坦。另外还可以通过一些头像增强插件,比如FocusFrame来观察你焦点的状态。 不过职业玩家一般不用按键绑定设置焦点,而是用/focus和/clearfocus宏命令来设置或清除焦点。/focus直接就可以达到按键绑定的效果了,而通过参数指定/focus的目标更是按键绑定所没有的功能:
/focus party3target
上面的只不过是教学示例,实际上职业玩家是这样用的:
/focus [target=focus, noharm] [target=focus, dead] [modifier]
/stopmacro [target=focus, noexists]
/cast [target=focus] 变形术
第一行先判断以下三个条件,如果满足任意一个,就把你的当前目标设为焦点(不要忘记,focus是/focus命令的特殊单位,参见[target=]条件语与命令参数):
你的当前焦点不是敌对目标(如果焦点不存在该条件也成立)
你的焦点已经死了
某个功能键被按下了
第二行判断你的焦点是否存在,如果不存在就终止宏的运行。这样控场是不是很方便?我们注意到这里用了/stopmacro命令,而不是在/cast命令中对焦点是否存在进行判断。这样的好处是我们可以在宏的最后加上更多的内容,比如一个小队喊话。 下面这个宏也很有用,可以把你的目标和焦点互换:
/cleartarget [target=target, dead]
/clearfocus [target=focus, dead]
/target focus
/cleartarget [target=focus, noexists]
/targetlasttarget
/focus target
/targetlasttarget
前两行的作用是把死亡的目标和焦点清除掉。第四行的作用是防止你没有当前焦点,导致当前目标不变,以至于在第五行选择了你以前的一个目标。
用/click进行分支判定¶
假如你想让一个按键根据不同的功能键施放不同的技能,并且根据左键右键选择不同的施放目标,那么我可以给你这样的一个例子:
/cast [modifier:shift, button:1, target=party1] [modifier:shift, button:2, target=player] 强效治疗术; [modifier:ctrl, button:1, target=party1] [modifier:ctrl, button:2, target=player] 快速治疗; [nomodifier, button:1, target=party1] [nomodifier, button:2, target=player] 恢复
哦… 对不起,不大好看… 而且貌似超过255个字符限制了。重新写一下:
/cast [modifier:shift, button:1, target=party1] [modifier:shift, target=player] 强效治疗术
/cast [modifier:ctrl, button:1, target=party1] [modifier:ctrl, target=player] 快速治疗
/cast [button:1, target=party1] [target=player] 恢复
不过如果我们写一个宏根据不同按键点击分别选择两个不同的宏,而把功能键状态的判断放到这两个宏中的话,条理就会更清晰了: 主宏:
/click [button:1] MultiBarLeftButton2; MultiBarLeftButton3
辅助宏1:
/cast [mod:shift, target=party1] 强效治疗术; [mod:ctrl, target=party1] 快速治疗; [target=party1] 恢复
辅助宏2:
/cast [mod:shift, target=player] 强效治疗术; [mod:ctrl, target=palyer] 快速治疗; [target=player] 恢复