|
想要查看内容赶紧注册登陆吧!
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
第十二章 宏 (Macros)
可用命令 (Available Command)
安全和普通斜杠命令 (Secure and Normal Slash Commands)
Target选项 (The Target Option)
安全指令列表 (List of Secure Commands)
施法序列 (Cast Sequences)
物品栏ID (Item Slot IDs)
条件 (Conditions)
可用的条件 (Available Conditions)
组合条件 (Combining Conditions)
逻辑与AND (The Logical AND)
逻辑非NOT (The Logical NOT)
逻辑或OR (The Logical OR)简单的控制构造 (Simple Control Structures)
宏的反馈 (Macro Feedback)
突破255个字符的限制 (Circumventing the 255-Character Limit)
在宏中使用Lua (Using Lua in Macros)
发送聊天消息 (Sending Chat Message)
计时宏 (Timers in Macros)
抑制错误消息 (Suppressing Errors)
优化选项 (Tuning Options)
绕过[flyable]bug (Circumventing the [flyable] Bug)
总结 (Summary) 第十二章 宏
(Macros)
对于任何学习Lua以便充分体验WoW的人来说,可以肯定的是,在你们的动作条(action bar)中已经有了一些宏(macros)。例如当你要执行复杂的任务,仅需一个按钮,即可根据条件将不同的法术施放到不同的目标身上,它们会非常有用。不同的条件也可能非常的复杂,例如,你可以检测你当前的目标是敌对的(hostile)还是友方的(friendly),是存活的(alive)还是死亡的(dead)。
如果你的动作条中有宏,你是自己创建的还是从其他地方复制粘贴的?如果是你自己创建的,你知道你在做什么吗?许多玩家认为宏只是一个由简单的斜杠命令列表组成的,但是它们非常强大。某些斜杠命令可以包含强大的条件,并由多种可以使用的选项。
宏总是逐行执行的,这意味着你必须在你想使用的斜杠命令之后插入新行。例如,一个宏发送两条消息到聊天框是这样的: - /say Hello...
- /say ...World!
复制代码你可以将游戏中所有可用的斜杠命令添加到宏中,从游戏中提供的斜杠命令如/say,或小的Lua脚本如/script <Lua code>,到插件创建的斜杠命令中复杂的Lua函数。唯一的限制是每个宏的字符数被限制为255。但我们会找到规避这一限制的方法。
本章是关于创建宏的,因此我们将探索宏是如何工作的,以及如何创建功能及其强大的宏。我们将从宏的可用命令概述开始。 可 用 命 令
(Available Command)
你可以找到基本的斜杠命令,如“/cast <spell>”、“/use <item>”(内部实际上是相同的命令),或“/castsequence <spell1>, <spell2>, ...”,但是还有更多命令,例如,你知道命令“/petautocasttoggle <pet spell>”吗?
○ 安全和普通斜杠命令(Secure and Normal Slash Commands)
我们将用于宏的大多数重要斜杠命令都被描述为安全斜杠命令,因为它们通常只是执行单个的受保护的函数。所有这些斜杠命令都存储在一个表中,只能从文件FrameXML\ChatFrame.lua中访问,保存局部变量的表的名称为SecureCmdList。回想一下,普通的斜杠命令(比如由插件创建的斜杠命令)存储在全局可访问的表SlashCmdList中。
在我们看来,这些普通命令相当乏味,因为它们所能做的一切也可用由Lua脚本完成。你还知道了游戏提供的所有重要的普通斜杠命令,因为你每天都在使用它们。例如,/raid <text>向团队发送一条消息,这是你在聊天框中一直想要输入的内容。还有命令/random去分配战利品。其他常用的普通斜杠命令是表情(emotes),例如,/facepalm <some guy who just wiped the raid>(某人刚刚离开了团队)有时会非常有用。
然而,本章不涉及这些提供的普通命令。你已经知道了最重要的那些,因为你每天都在使用它们。所有其他不太常用的普通斜杠命令被用于管理公会或团队。而且,这些斜杠命令通常非常简单,它们通常只接收一个参数,比如文本或目标。我们希望编写你可以在boss战或竞技场中使用的强大的宏。
注意:如果你需要更多关于游戏提供的普通斜杠命令的信息,暴雪在其网站上有一个列表:http://www.worldofwarcraft.com/info/basics/slashcommands.html。
现在让我们关注安全命令,乍一看它们要复杂得多。增加复杂性(adding complexity)是指你可以添加到斜杠命令中的条件和选项。在执行命令之前会检查条件,如果条件不满足,斜杠命令将被忽略。稍后你将看到关于条件的更多信息。
我们将首先研究哪些斜杠命令可以使用,以及它们提供的选项。有一个选项比较特殊,因为它对所有斜杠命令都可用,并且在内部实际上是一个条件——target选项。
○ Target选项(The Target Option)
让我们使用一个大家都知道的斜杠命令作为例子:/cast。这似乎是一个简单的命令,它对你当前的目标施法。但是你也可用使用/cast [target=focus] <spell>对你的焦点目标施法。在例子中这个选项的值是focus,但是它可以是任何有效的单位ID或附近的玩家或NPC的名字。
target是一个可用于所有安全命令的选项。这个选项显然不是对所有命令都有意义,但它在每个安全命令的语法上都是有效的,而不是对每个命令都有效。 注意:只有安全命令支持target选项,普通的斜杠命令不需要。但是许多普通的斜杠命令,比如表情(emotes),将动作的目标作为一个参数。 这个选项用来引出我们第一个有用的宏,对目标的目标施放一个法术。例如,治疗可以用它来治疗Boss,于是就会自动治疗它的当前目标: - /cast [target=targettarget] <healing spell>
复制代码另一个对猎人或术士有用的宏是,将一个法术对准宠物的目标。这可以通过下面的斜杠命令完成: - /cast [target=pettarget] <spell>
复制代码安全指令列表(List of Secure Commands)
表12-1列出了所有可用的关于施放法术或使用装备物品的安全命令。稍后将详细解释一些一些更高级的斜杠命令,例如/castsequence 小贴士:所有安全斜杠命令都是用Lua编写的。你可以在文件FrameXML\ChatFrame.Lua中找到他们(在文件中搜索SecureCmdList)。阅读斜杠命令后面的代码可用帮助你理解它。
表12-1 可用的法术和物品的安全斜杠命令 | | | 你的角色开始攻击<目标>或者你当前的目标(如果它被省略了)。也可以使用target选项替代。
| | | | | | | /castrandom <spell1>,<spell2>,...
| 从被逗号分隔列的列表中随机选择一种法术或物品并使用它。
| /castsequence <spell1>,<spell2>,...
| 当它第一次被执行时将施放<spell1>,第二次点击时将执行<spell2>,以此类推。它的参数也可以是物品。这个命令带有功能更加强大的额外重置选项(reset option),这将在本章后面详细解释。
| | | | | | | | 从你的库存中装备物品<itemName>,别名:/eq
| | 在<slot>中装备<物品>,稍后将解释槽ID(slot ID)。
| | | /swpactionbar <page1> <page2>
| 动作条<page1>和<page2>之间的切换。如果你当前既不是<page1>,也不是<page2>,则将选择<page1> |
这几个主要处理法术和物品的命令是宏中最重要。注意,由于全局冷却时间(global cooldown)限制,每个宏只能施放一个法术。但是有一些法术不会激活全局冷却,比如萨满和德鲁伊的自然之速(Nature’s Swiftness)。如果自然之速准备好了,以下的宏将会立即施放治疗波(Healing Wave)。如果你的自然之速正在冷却,则它将施放普通的治疗波。 - /cast Nature’s Swiftness
- /cast Healing Wave
复制代码你也可以对德鲁伊使用这个宏,用德鲁伊的治疗之触(Healing Touch)替代治疗波。其他不能触发全局冷却时间的法术包括牧师(神圣)的心灵专注(Inner Focus)和法师(奥术)的心灵镇定(Presence of Mind)。你可以使用这两种法术构建类似的宏。
但是除了施法之外,还有更多的斜杠命令。表12-2列出了处理target和focus target的所有安全命令,这些命令也可以派上用场。
表12-2 你的(焦点)目标可用的安全斜杠命令 | | | 目标的<name>。这也会把附近以<name>作为名称的玩家或NPC当作目标。你可以使用/targetexact <name>来避免这种行为。也可以使用target选项替代参数。别名:/tar
| | 以确切的名称作为目标。你可以使用target选项替代参数。
| | | | | | | | | | | | | | | | | | | | 协助<target>,也可以使用target选项替代参数。别名:/a <target>
| | 把<target>设为焦点,你也可以使用target选项。
| | |
表12-3列出了对猎人和术士来说特别重要的斜杠命令,因为他们可以命令你的宠物。
表12-3 宠物的可用安全斜杠命令 | | | 使你的宠物开始攻击<目标>。也可以使用target选项。
| | | | | | | | | | | | | /petautocasttoggles <spell>
| |
表12-4列出了所有处理副本角色的命令,如主坦克和主辅助的分配(assignments)。你可能想知道为什么要保护下面的函数,因为他们似乎不处理可以自动执行游戏的功能。原因是,如果他们没有被保护,你可以写一个插件,总是将你团队中生命值最低的玩家设置为主坦克。一个单位框体插件可以使用一个安全的组页眉(secure group header)来显示你所有的主坦克。这将总是显示最低生命值的玩家,而安全/受污染代码系统(secure/tainted code system)的目的是防止这样的插件。
表12-4 副本角色可用的安全斜杠命令 | | | | | 将目标设定为新的主坦克。也可以使用target选项。别名:/mt
| | | | | | | | 移除<target>的主协助状态。别名/maoff |
这是四种主要的斜杠命令。但是还有一些其他的命令可以使用。表12-5列出了所有剩余的安全命令。
表12-5 其他可用的安全斜杠命令 | | | 请求与<target>进行决斗。这里不可以使用target选项。
| | | | | /click <secure frame> <mouseButton>
| 在全局变量<secure frame>与<mouseButton>中执行存储的安全框体的OnClick处理程序。这是一个非常强大的命令,因为它允许我们点击任意的安全按钮模板,稍后你将看到如何使用它。 |
在本节的表中有两个命令我们没有完全解释:/castsequence和/equipslot。现在让我们仔细看看。
○ 施法序列(Cast Sequences)
施法序列命令一个额外选项:reset选项,它定义了何时重置为施法序列中第一个法术的标准。该选项不是必须的,默认情况下,施法序列在到达列表中最后一个法术时重新启动。你可能希望reset选项和target选项一样,以方括号的方式添加到命令参数的开头,但事实并非如此。重置选项必须放在可选条件(即target选项)和法术列表之间。下面的例子会说明这一点: - /castsequence [target=focus] reset=30 <spell1>,<spell2>,...
复制代码每次宏被执行的时候都会启动一个30秒的计时器,当计时器到期时就会重置为第一个法术。这意味着如果30秒内没有施法序列,它将重置。但reset接收的不仅仅是数字,它也可以是定义重置操作的触发器和字符串。你可以使用以下触发器。 1、当你改变你的目标时,目标重置序列。
2、当你离开战斗,战斗触发。
3、当你在执行宏时,按住键盘修饰键ctrl、alt和shift重置序列。 斜杠命令处理程序后面的代码只是在这个选项上使用string.find,如果它找到匹配的触发器,就会重置序列,因此你可以设置多个触发器,当其中一个触发器发生时重置。例如,reset=ctrltarget30,当你按下Ctrl再点击该宏时、当你更改你的目标时,或当你30秒没有使用宏时,将重置它。
○ 物品栏ID(Item Slot IDs)
安全命令/equipslot <slot> <item>带有一个物品(item)将要被装备到的物品栏ID(item slot ID)。命令/use <item>和/cast <item>也接收这样的ID代替物品名称。
有两种类型的清单ID(inventory IDs):字符串(比如你头部的头部装备栏(HeadSlot))和数字(比如你的头部是1)。宏只能使用数字标识符,而插件也可以(而且应该)在API函数中使用字符串标识符: - id, texture = GetInventorySlotInfo(slotName)
复制代码图12-1 显示了所有装备栏的槽位标识符(slot identifiers)
这些数字对我们很重要,因为我们不能字宏命令中使用字符串。我们现在可以编写简单且强大的物品使用宏。想象你装备了两个“在Y秒内产生X额外伤害”的花哨饰品。他们通常共享一个短暂的冷却时间,因此你不能同时激活他们。有一个宏可以激活当前没有冷却时间的饰品是非常有用的。
这里用/use(或/cast)命令会非常简单,我们可以尝试在同一个宏中激活这两个饰品。 如果其中一个处于冷却状态,它将被跳过,并显示通常的“该物品尚未准备好”消息。稍后你将看到如何屏蔽(suppress)此错误消息。
到目前为止,我们尝试的宏非常简单,你可能已经知道了如何使用大多数命令。让我们创建一些更高级的带有条件的宏。 条 件
(Conditions)
条件以方括号的形式添加到宏中,就像target选项一样(从语法上讲,它实际上也是一个条件)。一个简单条件的好例子是exists,如果命令的目标存在,则赋值(evaluates)为true,如果目标不存在则赋值为false。如果你有一个目标并且不做其他事情,下面的斜杠命令对你的目标施放<spell>。 你还可以使用target选项来修改命令的目标。exists条件也指向被目标选项指向的单位。如果你有目标,以下命令对你的目标施放<spell>。 - /cast [target=focus, exists] <spell>
复制代码 在一个命令中,多个条件总是用逗号分隔。我们现在可以向这个宏添加其他条件,但是首先让我们对现有的条件进行概述。 小贴士:使用红色问好作为宏的图标,因为它会根据条件自动选择适当的图标。 可用的条件(Available Conditions)
表12-6列出了所有可用的条件,并进行了简短的描述。一些更复杂的条件,如装备,将在本节后面详细解释。
| | | | | 如果宏被鼠标按钮x点击则为true,就像安全模板属性按钮后缀一样。x也可用是任何作为按钮传递给/click命令的字符串。
| | 如果你当前正在引导<spell>则为true。该法术是可选的,如果你当前正在使用任何法术,只要是引导而不是法术,则赋值为true。
| | | | | | 如果你一个<tiemType>类型的物品被装备,则为true。这个参数稍微复杂一些,稍后会详细解释。别名:worn:<itemType>
| | | | 如果你在外域(Outlands)或诺森德(Northrend)并且可以飞行(mount),则为真。警告:这个条件像在冬拥湖(Wintergrasp)或达拉然(Dalaran)这样的区域中赋值为true(这是一个使这个条件几乎完全没用的bug)
| | | | 有效的群组类型(group type)是队伍和团队,如果你在这样的群组中,则赋值为true。
| | | | | | | | 如果宏被带有修饰符的按键点击,则为ture。有效的<modifier>值为ctrl、alt和shift。
| | | | | | | | 如果你当前的宠物是<name>则为true。该参数是可选的,也可以只使用pet来检查任何宠物。
| | 如果你目前以ID为x的姿态(stance)或变形形态,则为真。姿态ID将在稍后详细说明。ID是可选的,你可以只使用stance来检查任何姿态或变形形态是否处于激活状态。别名:form:x
| | | | |
这些条件可以用于除了决斗命令/duel和/forfeit之外的所有安全命令。
这个列表中较为复杂的条件之一是equipped,它接受物品的类型而不是名称。每个物品都有一个类型和一个子类型,例如,可以使用他们对拍卖行重点物品进行分类。在这个宏条件中可以使用他们的标识符是拍卖行所显示的物品类型的本地化字符串。例如你可以使用条件equipped:Clot来检查你当前是否穿着布甲装备。在这里使用装备类型没有太大意义,有趣的选择是使用武器类型。例如,盗贼可以使用以下宏,在一个简单的宏中结合背刺(Backstab)(需要一把匕首)和影袭(Sinister Strike),具体取决于当前装备的武器。 - /cast [equipped:Daggers] Backstab
- /stopmacro [equipped:Daggers]
- /cast Sinister Strike
复制代码 如果你正在使用匕首,这将施放背刺并取消该宏。否则它施展邪恶打击。在下一节中,你将看到使用一个cast命令编写这样一个宏的方法。 - 注意:物品类别总是复数,所以使用[equipped:Dagger]不起作用。
复制代码 另外两个重要的分类是单手武器(One-Hand)和双手武器(Two-Hand),如果你使用单手武器或双手武器,则它们会被赋值为真。
表中完全没有解释的另一个条件是stance:x。姿态是战士的不同姿态、还有德鲁伊变形形态、牧师的暗影形态和救赎之魂、盗贼潜行、萨满的幽灵狼和术士的恶魔形态。姿态ID 1指的是你在变形/姿态条中可见的第一个姿态或变形,2指的是第二个,以此类推。例如姿态1:指战士的战斗姿态或德鲁伊的熊姿态。
姿态ID可以指向不同的形态或姿态,取决于德鲁伊的天赋(talent)和专精(specialization,spec)。对德鲁伊来说,stance:5指的是平衡专精下的枭兽(Moonkin)形态,和恢复专精下的生命树(Tree of Life)形态。牧师稍微复杂一点,如暗影形态可用的话,stance:1表示暗影形态,如果救赎之魂可用但暗影形态不可用,则表示救赎之魂。如果两种天赋都点了,救赎之魂是stance:2。 注意:圣骑士的光环和猎人的守护灵不是姿态,即使它们出现在变形/姿态栏上。这意味着你不能使用姿态条件来检查哪一个光环或守护灵当前处于激活状态。 我们已经讨论了所有可用使用的条件。让我们结合它们来构建复杂的表达式。 组合条件(Combining Conditions)
检查两个条件最简单的方法实际上并不是结合两个不同的条件。所有条件以condition:argument的形式用斜杠分隔开来,这些参数将用逻辑或OR组合在一起。如果你按下Shift或Alt键,下面的命令可用施放<spell>: - /cast [mod:shift/alt] <spell>
复制代码但是我们也可用在一个命令中组合两个不同的条件。最简单的组合是连词(用逻辑和AND连接条件)。
· 逻辑与AND(The Logical AND)
你已经在上一节中已经看到了一个示例,因为target选项在语法上是一个条件: - /cast [target=focus,exists] <spell>
复制代码我们可用添加另一个用逗号分隔的条件来检查它们。以下示例在你的目标存在且死亡时对其施展复活: - /cast [exists,dead] Resurrection
复制代码设置条件以检查目标是否存在或是否死亡也非常的有用。我们需要逻辑非NOT来完成这件事。 逻辑非NOT(The Logical NOT)
条件的否定也可用轻松完成。只需向条件添加前缀no来否定它(应用逻辑NOT)。因此,没有死亡意味着你的目标是或者的。如果你的目标存在并且还活着,以下的宏可用对他施放<spell>: - /cast [exists,nodead] <spell>
复制代码逻辑NOT被局限于一个单一的条件,不能再宏条件中添加括号。让我们试着否定上一个例子中的条件。想象你把这个否定的表达式写成Lua表达式,就像这样: - not (exists and not dead)
复制代码在宏中不可能使用像[no(exists,nodead)]这样的条件。我们需要将这个表达式转换成可用在宏中表示的等价表达式。我们可用通过分析条件的含义在这样一个简单的例子中做到这一点。这意味着我们的目标要么不存在,要么已经死亡了。在Lua语法中可用将其写成(不存在)或死亡。稍后你将看到如何使用逻辑或宏。
这两种形式之间的转换并不总是那么明显,特别是当你有更复杂的表达式时。但是布尔代数中有一个简单的法则可用用来做这个变换。德摩根定律是这样的: - not (A and B) = (not A) or (not B)
复制代码如果我们把这个应用到我们的表达式not (exists and not dead),我们会得到(not exists)或(not not dead)。显然,not not dead的意思和dead是一样的,所以我们得到(not exists)或dead。
本法则也适用于用or替代and。 - not (A or B) = (not A) and (not B)
复制代码但我们仍不能在宏中使用表达式,因为我们还没有讨论逻辑,让我们看看它是如何工作的。
· 逻辑或OR(The Logical OR)
若要用逻辑OR组合两个条件,请在方括号中添加另一个表达式块。最后一节中的示例如下所示。 - /cast [noexists][dead] <spell>
复制代码如果你的目标不存在或已经死亡,此技能将会使用<spell>。OR操作符在某种程度上也受到了限制。假如你有一个(A or B) and (C or D)形式的表达式,你可能认为可用把宏条件写成[A][B],[C][D],但这是不对的。你还必须将表达式转换成析取范式(disjunctive normal form),将表达式分解为多个子表达式,这些子表达式可用像正常条件一样简单,并与逻辑OR组合在一起。
对于这种表达式的变换还有一个有用的定律——分配律 - A and (B or C) = (A and B) or (A and C)
- A or (B and C) = (A or B) and (A or C)
复制代码让我们试着将这个定律应用于表达式(A or B)and(C or D),将其转换为适合于宏的形式。 - (A or B) and (C or D)
- = ((A or B) and C) or ((A or B) and D)
- = ((A and C) or (B and C)) or ((A and D) or (B and D))
- = (A and C) or (B and C) or (A and D) or (B and D)
复制代码表达式的这种形式与原始形式具有相同的含义,可用用作如下所示的宏条件: - /cast [target=player][target=focus] <spell>
复制代码第一个代码块总是为true,因为它不包含条件,所以第二个块永远不会执行,它的target选项没有影响。但我们依然可以向代码块添加条件,以根据这些条件设置target选项。我们可用使用这个技术来扩展本章的第一个宏,这个宏可用对你目标的目标施放治疗法术。 - /cast [target=targettarget] <healing spell>
复制代码你可以用这个宏以一个怪物为目标,并且治疗该当前拉住怪物的坦克玩家,但当我们的目标是一个友方玩家时,它是没有用的。下面的宏会检查我们当前的目标是否是友方,如果是,会对他施放治疗;否则它对目标的目标施放治疗。 - /cast [target=target,help] [target=targettarget] <healing spell>
复制代码注意:第一个target选项实际上不是必须的,因为target默认设置为target。
我们可以进一步扩展宏,首先检查鼠标悬停单位ID。这个单位ID与安全单位模板(secure unit templates)一起工作,它允许你用鼠标悬停在你的副本框体来治疗玩家。接下来的检查可以是目标,然后是目标的目标。这些单位ID上可能会出现help fails的情况,但在这种情况下,我们能然可以对自己施放这个魔法。以下是懒惰治疗者的终极宏,它执行前面提到的所有检查,并选择一个可以治愈的目标: - /cast [target=mouseover,hepl][target=target, help][target=targettarget,help] [target=player] <healing sepll>
复制代码注意,第二个代码块中需要target=target,因为第一个块将目标设置更改为mouseover(鼠标悬停)。仅仅使用[help]作为第二个是没有意义的,因为它检查鼠标悬停目标是否是友方,事实并非如此。我们知道,因为如果它是友方的话,就永远不会到达第二个块。 注意:不需要添加检查目标是否还活着,因为条件帮助的作用不仅仅在于检查目标是否友好。它会检查目标是否是有益法术的有效目标,而死亡的目标不是这类法术的有效目标(复活术除外,复活术不能与help检查同时使用。) 我们现在可以用条件构建复杂的表达式,但是整个命令的形式仍然非常简单:使用if <expression>,之后do一些操作,最后end构造。有一个elseif或else块将是一个很好的补充。 简单的控制构造(Simple Control Structures)
宏中唯一可用的控制结构是if-else-elseif块。在宏中没有循环这样的东西。
宏中else或selseif块以分号开始。然后是要使用的条件和宏参数。我之前展示了一个宏,如果你装备了一把匕首,它就会使用背刺,否则就会使用影袭。 - /cast [equipped:Daggers] Backstab
- /stopmacro [equipped:Daggers]
- /cast Sinister Strike
复制代码这个宏使用stopmacro命令,正如我所说的,我们将尝试它的另一个版本,它只包含一行代码。我们只需要添加一个分号,后面跟着else块的内容,这里只有使用Sinister Strike(影袭)作为参数施放。 - /cast [equipped:Daggers] Backstab; Sinister Strike
复制代码 elseif-block在分号后面使用额外条件,就像下面的宏,如果你有敌方目标,它会施放伤害法术,如果你的目标是友方目标,它会施放治疗法术: - /cast [harm] <damage spell>;[help] <healing spell>
复制代码控制结构的另一个有趣的用法是使用btn或mod条件来根据所使用的鼠标按钮或键盘修饰符执行不同的操作。盗贼可用使用下面的宏,先用鼠标左键点击,然后再用鼠标右键点击,对两种武器都施加毒药。 - /cast Wound Poison VII
- /cast [button:1]; [button:2] 17
复制代码第一个命令使用毒药,然后要求你选择一个目标。如果你左键点击宏,第二个命令就会在你的主手上使用放置的技能,如果你右击宏,第二个命令就会在右手上使用放置的法术。
另一个非常强大的宏是为了试图打断一个法术的战士准备的。战士可以在战斗中打断法术并且还拥有带盾牌猛击(Shield Bash)(需要盾牌)的防御姿态。拳击(Pummel)可以用于狂暴姿态,这个法术不需要特定的武器类型。以下宏在你处于狂暴姿态时施放拳击,否则它会检查你是否装备了盾牌,然后施放盾牌猛击。如果这个检查也失败了,也就是说你处于战斗姿态或防御姿态,并且没有装备盾牌,它就会释放狂暴姿态,所以你可以第二次执行这个宏。 - /cast [stance:3] Pummel; [equipped:Shields] Shield Bash; Berserker Stance
复制代码注意不可能一下就施放狂暴姿态和拳击,因为狂暴姿态会触发全局冷却时间。
你可能已经注意到的一件事是,如果你选择红色问好作为宏图标,它们会自动显示正确的法术。但是我们也可以控制显示哪些法术和鼠标提示。 宏的反馈(Macro Feedback)
当你在当前环境下执行宏时,它总是使用法术的图标和冷却时间。但这并不足够,并且可以在宏的开始使用命令#show或#showtooltip来控制这种行为。这两个命令还需要宏的问号图标。
这两个命令都很简单。它们带有一个单独的参数,然后显示在该宏的动作条中。下面的宏在动作条中显示为攻击,其行为就像在动作条中有普通攻击,而不是宏一样。但是当你单击它时,它会施放Flash Heal - #show Attack
- /cast Flash Heal
复制代码命令#showtooltip遵循完全相同的语法。唯一的不同是,将鼠标放在宏上时,还会获得该法术的鼠标提示,它还设置图标。#show命令仅设置图标,鼠标提示宏的名称。
也可以从安全命令中使用已知的条件,并且分号用于简单的if-then-else结构。下面的宏创建了一个按钮,如果你有匕首,则显示背刺,否则显示影袭。 - #showtooltip [equipped:Daggers] Backstab; Sinister Strike
复制代码但是以前使用相同条件的宏已经具有此功能(鼠标提示除外,该提示仅显示了宏的名称)。宏的图标已经正确,并且你几乎不需要操作按钮的鼠标提示。因此你可能向知道这些命令的真正用途是什么。答案是,你不能始终在宏中使用带有条件的简单斜杠命命令。例如,当实际工作由Lua代码完成时,你将需要此功能,因为/script命令没有被解析确定要显示的图标。在本章的最后,当我们创建一个挂载宏时,你将看到一个这样的例子。
你还需要使用#showtooltip,如果你的宏有一个stopmacro命令,你想要显示一个不同的图标,如果命令的条件是满足的,因为当确定图标/鼠标提示显示时,游戏不检查停止条件。但是,你很少需要根据stopmacro条件显示不同的图标,因为你通常可以通过使用控制结构来避免使用stopmacro。
showtooltip的另一个可能用途是当你的宏调用其他宏或执行安全按钮的单击操作时。例如,假设在第一个动作中有两个宏,两个动作槽,ActionButton1和ActionButton2。你现在想创建一个宏,如果你有一个敌对的目标,它会执行宏1,否则会执行宏2。 - #showtooltip [harm] <damage spell>; <heal spell>
- /click [harm] ActionButton1; ActionButton2
复制代码如果我们不在这里使用#showtooltip,按钮根本不会显示图标,因为在确定要显示图标时,WoW不会解析/click所引用的按钮。但是,我们为什么要编写这样一个简单调用另一个宏呢?因为其他宏的长度也可以达到255个字符,这意味着我们已经成功地绕过了宏只有255个字符的限制。但还有其他方法可以做到这一点,而不必将宏分割成许多小的部分。让我们看看如何结合/click和安全动作按钮模板来创建非常长的宏。 突 破 255 个 字 符 的 限 制
(Circumventing the 255-Character Limit) 一个宏很少需要超过255个字符,但有一种情况是,你想要完成“杀死所有稀有怪物”的成就。它是一个真正有用的宏,试图以所有稀有怪物为目标,和当你以它为目标时显示一条消息。之后你可以在西游怪物的刷新点到处飞,并一直点击宏。
我们需要使用Lua代码创建一个安全动作按钮,并将其类型设置为macro,将其属性macrotext设置为如下内容。 - /targetexact Loque’nahak
- /targetexact High Thane Jorfus
- ...etc with all 23 Northrend rare spawns
- /stopmacro [noexists]
- /script ChatFrame1:AddMessage(“Found a rare spawn: ”..UnitName(“target”))
- https://nga.178.com/read.php?&tid=24367379
复制代码 这显然不是一个普通的宏,所以让我们为它构建一个安全操作按钮。创建在宏中使用的按钮的最佳位置是在单独的插件中。我有一个名为RandomCrap的小插件,它由一个XML和一个Lua文件组成,其中包含我经常使用的一些函数和模板。但如果你只是想测试它,你也可以在一个插件如(TinyPad)中输入以下代码。
创建这样一个宏最简单的方法是使用23个/targetexact命令编写这样一个字符串。注意,用方括号分隔字符串允许在字符串中使用新行,因此可以在代码中逐字地编写长宏。但是,更聪明的做法是创建一个包含所有boss名称的表,并从这个字符串自动宏文本。它更短,更灵活,如果你想允许部分匹配,你可以很容易地将target命令从targetexact更改为/target:
Code lua: - local rarespawns = {“Loque’nahak”, “Hildana Deathstealer”, “Fumblub Gearwind”, “Perobas the Bloodthirster”, “King Ping”, “Crazed Indu’le Survivor”, “Grocklar”, “Syreian the Bonecarver”, “Griegen”, “Aotona”, “Vyragosa”, “Putridus the Ancient”, “High Thane Jorfus”, “Old Crystalbark”, “Icehorn”, “Vigdis the War Maiden”, “Tukemuth”, “Scarlet Highlord Daion”, “Seething Hate”, “Zul’drak Sentinael”, “Terror Spinner”, “King Krush”, “Dirkee”}
- local targets = “”
- for i, v in ipairs(rarespawns) do
- targets = targets..”/targetexact ”..v..”\n”
- end
- local frame = CreateFrame(“Button”, “RareSpawns”, nil, “SecureActionButtonTemplate”)
- frame:SetAttribute(“type”, “macro”)
- frame:SetAttribute(“macrotext”, target..[[
- /stopmacro [noexists]
- /script ChatFrame1:AddMessage(“Found a rare spawn: ”..UnitName(“target”))]])
复制代码该代码首先生成宏文本的/targetexact部分,然后创建一个安全操作按钮,并将其类型设置为macro。然后将属性macrotext设置为前面生成的字符串,然后是停止条件和显示消息的代码。
这项技术适用于所有需要255个字符以上的宏,但它也有一个小缺点:你必须使用#show(或#showtooltip)命令来在动作条中获得图标和工具提示。我们现在可以构建一个宏,它可以单击带有长宏属性的不可见的安全操作按钮。这个宏非常简单,因为/click命令需要一个包含按钮的全局变量。 在 宏 中 使 用 Lua
(Using Lua in Macros)
还有最后一个主题,它实际上与传统的宏没有什么关系——在宏中使用Lua。这非常简单,只需要使用斜杠命令/script。但是在宏中由上面Lua可用呢?请记住,不能从Lua中施展法术或使用物品,因为这些函数受保护,因此只能从安全代码中调用。来自宏的代码永远不安全。
○ 发送聊天消息(Sending Chat Message)
在上一节中,你在宏中看到了一个简单的Lua聊天消息例子。我们调用ChatFrame1:Addmessage(msg)来在聊天框中显示一个通知。另一个类似的用途是发送聊天消息,但这不一定需要Lua代码。简单的聊天消息可用发送与常见的斜杠命令,如/say和/raid。甚至可用通过在消息中使用%t将目标包含在聊天消息中,它将被替换成为当前目标的名称。这不是一个特定于宏的函数,你可用在你的聊天信息中使用%t来指向你在《魔兽世界》中的目标。以下的宏对德鲁伊很有用,它施放复生,并发送复活玩家的名字到团队聊天中。 - /cast Rebirth
- /raid Battle res on %t!
复制代码这个宏根本不使用任何Lua。但是这个宏的另一个有用功能是向复活玩家发送一个私聊,这样它就可用准备回到战斗中。你可能会认为这里有可能使用/w %t Battle res incoming。但它只适用于聊天信息,而不是私聊的目标。这意味着我们需要Lua代码啊向当前目标发送一个私聊。 - /cast Rebirth
- /raid Battle res on %t!
- /script SendChatMessage(“Battle res incoming!”, “WHISPER”, nil, UnitName(“target”))
复制代码在宏中使用Lua的一个明显缺陷是很快就会达到255个字符的限制。解决方案是将实际的Lua代码外包到一个小插件中,然后提供一个简单的斜杠命令或从宏调用Lua函数。下面的代码创建了斜杠命令/wtarget <msg>,它将发送消息<msg>到你的当前目标:
Code lua: - SLASH_WHISPERTARGET1 = “/wtarget”
- SLASH_WHISPERTARGET2 = “/wtar” -- alias /wtar <msg>
- SlashCmdList[“WHISPERTARGET”] = function(mag)
- if UnitName(“target”) then
- SendChatMessage(msg, “WHISPER”, nil, UnitName(“target”))
- end
- end
复制代码- /wtar Battle res incoming!
复制代码除了更简短和更容易使用之外,当你没有目标时,它不会产生错误消息。
另外一个有用的功能是安排在特定时间之后发送消息。着允许你创建倒计时宏,这是非常有用的,所以让我们看看如何完成它。
○ 计时宏(Timers in Macros)
实现这个最简单的方法是从你的宏中使用SimpleTimingLib。但是创建一个以秒为单位的斜杠命令比在某段时间之后执行的斜杠命令更容易。下面的代码创建了一个斜杠命令,该命令在给定时间后执行另一个斜杠命令。它需要安装SimpleTimingLib库,要么作为独立运行的版本,要么嵌入到插件中。 - local function runCmd(cmd)
- local old = ChatFrameEditBox:GetText()
- ChatFrameEditBox:SetText(cmd)
- ChatEdit_SendText(ChatFrameEditBox)
- ChatFrameEditBox:SetText(old)
- end
- SLASH IN1 = “/in”
- SlashCmdList[“IN”] = function(msg)
- local time, cmd = msg:match(“(%d+)(.+)”)
- if cmd:sub(1,1) ~= “/” then
- cmd = “/”..cmd
- end
- SimpleTimingLib_Schedule(time, runCmd, cmd)
- end
- https://nga.178.com/read.php?&tid=24367379
复制代码函数runCmd通过使用一个技巧来执行实际的命令——它修改默认聊天框中包含的文本,并调用函数ChatEdit_SendText(editBox),该函数在文件FrameXML\ChatFrame.lua中定义。它还可以在这里解析命令并找到与之关联的斜杠命令处理程序或表情,但这将是一项相当大的工作(需要大约30行代码)。如果你想找到斜杠命令在默认UI中式如何处理的,可以在文件frameXML\ChatFrame.lua中读取函数ChatEdit_ParseText(editBox, send)。
我们现在可以在宏中使用/in命令,例如这样: - /raid Pull in 3 seconds!
- /in 1 /raid Pull in 2 seconds!
- /in 2 /raid Pull in 1 second!
- /in 3 /raid Pull now!
复制代码还可以省略要调用的命令中的前斜杠,因为/in处理程序会在命令不是以斜杠开头的情况下添加一个斜杠。语法/in 3 raid Pull now!也会执行。 - 注意:/in命令无法执行任何安全命令,因为执行路径被提供斜杠命令的插件污染了。
复制代码Deadly Boss Mods(DBM)附带的另一个计时器斜杠命令式所谓的披萨计时器(pizza timer),可以通过斜杠命令/dbm timer xx:yy <text>来开始。它显示了一个带有名字<text>的DBT计时器。你可以在一个宏中使用它来跟踪某个技能或法术的冷却时间。但是还有另一个更强大的斜杠命令:/dbm broadcast timer xx:yy <text>,它广播一个dbm计时器给你的队伍或团队群组。此命令需要团队助手(raid assistant)或团长(leader)状态。
团长可以使用如下的宏来为团队宣布一个短暂的休息时间。 - /rw Have a short break! (5 min)
- /dbm broadcast timer 5:00 Break
复制代码抑制错误消息(Suppressing Errors)
为什么会有人想要禁止错误消息呢?答案是有一些宏总是生成错误消息,即使它们被成功执行。这方面的一个例子是我们前面使用的饰品宏。 这个宏试图同时使用两个饰品,这总是会生成一个错误消息。如果第一个/use命令成功,第二个/use命令会因为全局冷却而失败。去掉红色的“物品还没有准备好”消息的一个简单方法是清除显示该消息的框体。这个框体存储在全局变量UIErrorsFrame中,它的类型是MessageFrame。这种消息框体的工作原理类似于聊天框体(滚动消息框体),但没有滚动功能。你可以使用方法frame:AddMessage(msg)向这样的框架添加消息,最重要的是使用methodframe: clear()消除消息。此框体类型(以及所有其他框体类型)的完整参考可在附录A中获得。
下面的宏在尝试执行两个/use命令后清除UIErrorsFrame。 - /use 13
- /use 14
- /script UIErrorsFrame:Clear()
复制代码当然,也可以将此代码放在一个插件中。但是这里的Lua代码相对较短,因此不值得这样做。
○ 优化选项(Tuning Options)
一些常用的宏不同于其他宏,因为它们基本上只是执行一次Lua脚本。这些“宏”简单地设置了一个所谓的cvar(控制台变量(console variable),一个存储游戏设置的变量,比如你的视频选项),这也可以通过编辑文件World of Warcraft\WTF\config.wtf来完成。这样的选项可以通过调用SetCVar(“option”, “value”)来设置,并使用GetCVar(“option”)来获取。
下面是一个常见的宏示例,它允许你通过设置选项进一步缩小camerDistanceMaxFactor到2.5。在界面选项菜单的距离滑块(The distance slider)最多到2.0。 - /script SetCVar(“camerDistanceMaxFactor”, ”2.5”)
复制代码注意这个选项的指保存在config.wtf中,这意味着执行了这个“宏”一次,并且你可能根本不会将这个简单的Lua脚本存储在一个宏中。
还有许多其他可用选项,可以将他们设置为比选项菜单所允许的更高的值。控制“地面场景(Ground Clutter)”密度和据伦理的视频选项就是一个很好的例子。下面的宏将这两个选项设置为视频效果菜单中滑块之外的值。 - /script SetCvar(“groundEffectDensity”, “256”)
- /script SetCVar(“groundEffectDist”, “140”)
复制代码这增加了杂草和其他植被的数量和可见范围。然而,如果你没有一个高端的配置,这可能会大大降低你的FPS。请注意,配置菜单中的选项被限制为较低的值是有原因的。
○ 绕过[flyable]bug(Circumventing the [flyable] Bug)
另一个非常有用的宏是在允许飞行坐骑或普通坐骑的区域使用飞行坐骑。如果条件flyable正常工作,这看起来是一个非常简单的宏。你可以简单地使用以下宏来做到这一点: - /cast [flyabel] <flying mount>
- /cast [noflyable] <normal mount>
复制代码但是飞行不能正常工作。如果你在外域或诺森德允许飞行的区域,则此条件的值为true。在《巫妖王之怒》之前,在外域任何地方,普通坐骑允许的地方飞行坐骑也是被允许的。这在巫妖王之怒中不在正确,因为你不能在达拉然(除了克拉瑟斯的着陆点)或冬拥湖,但是那里仍然是true。这意味着宏在这些区域中失效。
但是使用坐骑不是一个受保护的动作,即使它可以通过安全命令/cast完成。在3.0补丁中引入的函数CallCompanion(type, id)可以用来召唤非战斗宠物或坐骑。类型可以是“CRITTER”来召唤非战斗宠物,也可以是“MOUNT”来使用普通坐骑。坐骑的ID可以从默认的宠物和坐骑菜单获得,第一个坐骑(或宠物)的ID为1,第二个为2,以此类推。
下面的代码创建一个斜杠命令/mount,它使用基于当前所在区域的可用坐骑列表中随机飞行坐骑或普通坐骑。
Code lua: - local groundMounts = {1, 16, 26}
- local flyingMounts = {5, 10, 22}
- SLASH_MOUNT1 = “/mount”
- SlashCmdList[“MOUNT”] = function(msg)
- local zone = GetRealZoneText()
- local subzone = GetSubZoneText()
- if IsMounted() then
- Dismount()
- elseif IsFlyableArea() and zone ~= “WWintergrasp”
- and (zone ~= “Dalaran” or subzon == ”Krasus’ Landing”) then
- CallCompanion(“MOUNT”, flyingMounts[math.random(#flyingMounts)])
- else
- CallCompanion(“MOUNT”, groundMounts[math.random(#flyingMounts)])
- end
- end
- https://nga.178.com/read.php?&tid=24367379
复制代码注意,这里有必要检查我们是否以及上了坐骑了,如果上了,就解除,因为CallCompanion (type, id)不像/cast命令那样,它不会解除坐骑。之后,斜杠命令使用一个良好的条件来检查是否真的允许在该区域飞行,如果是这种情况,则使用来自flyingmounth表的随机坐骑。否则,它使用表groundMounts中的随机坐骑。如果你想使用基于此脚本的宏,就必须用你喜爱的坐骑的ID来填充这些表。
使用提供这个斜杠命令的插件的一个宏可能是这样的: - #showtooltip [flyable] <flying mount>; <normal mount>
- /mount
复制代码#showtooltip只是为了得到宏的图标和鼠标提示,这个图标在达拉然和冬拥湖中是错误的并不重要 ● 总 结
(Summary)
本章节演示了一种与《魔兽世界》API交互的不同方式:通过斜杠命令,乍一看似乎相当简单。但是这些安全的斜杠命令可以与复杂的条件结合使用,这使得它们非常强大。我们查看了所有可用的安全斜杠命令,它们可以执行通常只能从安全代码(即从默认UI)或使用安全模板执行的操作。
我们讨论了如何使用逻辑运算符组合多个条件来构建复杂的表达式。然后我们了解了如何在斜杠命令中的简单 if-then-else-end 块中使用这些表达式。
本章的下一个主题是在宏中使用Lua,我们尝试了许多可用在宏中使用的有用的Lua脚本。你还了解了如何将宏与安全模板结合使用以规避255个字符的限制,如果你希望使用长宏,这一解决方案可能非常重要。
安全斜杠命令和安全模板是执行某些动作的唯一方式,比如施法。在本章中,你看到了如何结合这两种技术来创建及其强大的宏,以帮助你进行副本或PVP对抗。
如果你正在寻找宏,请一定去WoWWiki页面http://ww.wowiki.com/Useful_macros逛逛。这个页面有一个相当强大的宏编译,可以用于各种目的,你说不定会在那里找到你要找的东西。你可能已经找到了这个宏列表并从那里复制了一些宏。但是你现在知道了这些宏是如何工作的,并且可用根据自己的需要定制它们。理解一段代码并能够对其进行定制总是比只是复制和粘贴要好。
|
|