绕开上帝
日历
网志分类
· 所有网志 (3)
· 魔兽世界 (3)
· 经典文章 (0)
· 小记杂笔 (0)
· 心情生活 (0)
· 实用技术 (0)
站内搜索
友情链接
· 我的歪酷 非非共享界

订阅 RSS

0005496

歪酷博客

当你将神遗忘后....
« 上一篇: WOW界面DIY实用教程(dart使用指南)—dab,duf,moveanything高级应用 下一篇: 两个比较酷的D系列界面UI,都是War3 Undead! »
Azrael @ 2006-08-14 01:34

Chapter One

玩了WOW有一段时间了,除了游戏本身所提供的基本功能之外,其它WOW的功能我都尽量的尝试
.在这里我提供一下我个人的心得.

相信很多的玩家都知道,WOW有所谓的合法外挂(COSMOS),但是WOW又非常的严格的抓所谓的非
法外挂,那么合法的外挂与非法的外挂差别在哪?

其实所谓的合法外挂,只是在于一些有心的玩家利用了WOW所提供的功能,以及指令,另外在WOW
的游戏核心上,另外写了一些辅助性质的SCRIPT来帮助游戏接口的简易操作.至于非法外挂,
就是利用任合游戏本身所没提供的功能来增加自身的利益(包括了所谓第三者程序third party
program).

既然WOW本身有提供这样的功能,身为玩家的我们为什么不尽量的利用这些好处呢?有鉴于台
湾玩家在获得这些信息上的困难(因为有关于这方面的讨论,大部分都是英文),我在这里提出
讨论,或许能带给台湾的玩家另外一种的游戏体验.

暴风雪在WOW的官方网站上有很明确的提到,UI的修改是玩家对于游戏整体体验中的一部分.
但是什么是UI?UI修改又是什么?

UI是USER INTERFACE(使用者接口),在WOW中,所有的UI都是模块化的,每一个按钮,每一个窗
口都是属于某一个模块的定义.玩家在玩游戏的时候,并不是直接的对于游戏核心下达游戏指
令,而是先在UI上面的动作,然后在藉由UI的模块上下达游戏核心指令.例如我们按下游戏中
攻击的按钮,WOW会先检查这个按钮的定义是什么,然后才执行这个定义下的指令.

那么修改UI的好处又是什么呢?这样说好了.WOW本身所提供的UI,其背后的定义都是最基本的
,最简化的.比如说快捷键按钮的设计,以及每个指令动作.在按钮以及窗口的设计上,使以简
单容易上手为主要目的.但是对于进阶玩家而言,又会觉得WOW所提供的快捷键按钮不够用,所
以自己在UI上面加以修改,这样就不但可以自行决定快捷键按钮的数目,也可以把这些按钮摆
在自己最喜欢的地方.

另外关于指令动作上(键盘与老鼠在UI上面的指令),WOW基本的UI设定都是一个指令一个动作
.我们按一个按钮,WOW做一个动作.但是我们可以自行设定UI,达到玩家的下达一个指令,WOW
同时做很多动作.

比如说,WOW给玩家在攻击上的选择是,按TAB会帮玩家找出画面上距离最近的敌人(原始设定
是20码的距离范围内),然后玩家必须按攻击的按钮或是T,在这样的情况下才会攻击.玩家下
达了两个指令,做了两个动作.但是在UI的修改上,我们不但可以修改画面上距离最近的敌人
的距离范围(适合远距离攻击的玩家),我们还可以设定按下TAB按键,不但会自动定位距离最
近的敌人,还会自动开始攻击.

在这个讨论串当中,我主要是针对指令UI上的设定提出讨论,因为关于画面上的设定已经有很
多现成的选择(COSMOS).因此我将针对CLASS上面辅助型的UI设定.在藉由讨论上,让台湾的玩
家们也有机会自行设计出最方便,最有效率的攻击,法术施展,以及宠物控制.

当然我绝对欢迎玩家针对任何的UI设定提出讨论,但是我不见得有能力回答.毕竟我个人比较
不喜欢去研究画面的排列,所以这方面花的功夫也比较少.




Chapter Two

上一篇文章介绍了UI修改的最基本观念,在这篇文章中我将提供UI修改上的最基本的动作,工
具以及数据来源.
在我们要对UI做任何的修改或是制作模块之前,我们必须先了结WOW的UI基本结构.在WOW的数
据夹里面,我们可以找的一个DATA的子目录.在这个子目录里面,包括了所有WOW会用到的档案
,包括了模块,图形,字型等等.这些都压缩在所谓的MPQ档案里面.拿我个人的档案来做例子,
我的MPQ檔在C:Program FilesWorld of WarcraftData下面.而所有UI可以用到的档案都压缩
在interface.mpq档里.

要检查MPQ档案里面有些什么,我个人建议WinMPQ这个程序.为了避免大家担心我放病毒,在这
里我建议大家自行上GOOGLE查哪里可以下载WinMPQ.

因为游戏的UI的基本设定都在interface.mpq,所以我不建议大家直接对于interface.mpq里
面的档案直接修改.大家可以把所需要的档案解压出来.只要做完修改后不存回interface.mpq
里面,在这样的情况下,都不会影响到基本设定.

那么大家会问修改完之后的档案该存在哪呢?首先到WOW的目录里面,然后开一个先的子目录
叫做interface.以我个人的例子是C:Program FilesWorld of Warcraftinterface.然后大家
可以把修改好或是制作好的档案存在这个数据夹下面.当WOW加载游戏数据的时候,WOW会自动
到这个数据夹里面检查哪些模块蛟撦d入.

虽然UI修改可以用到WOW现有的档案,但是为了方便教学,我在这里提出的例子将不会用到WOW
现有的档案.事实上,除了要做游戏画面上的设定,大部分的情况下,我们不见得要用到WOW现
有的UI档案,只要我们制作模块用的都是WOW所提供的核心指令就可以了.

在制作模块之前,我先介绍一下每一个模块所需要的最基本的档案.每个模块都需要一个介绍
档,toc檔.定义档,xml,以及核心檔,lua檔.这三种档案都可以用笔记本或是任何的文书处理
程序来做修改.

为了方便介绍,我举出一个简单的例子来解释这三个档案.现在让我们设计个 Hi 模块.这个
模块当你执行的时候,他会在你的游戏画面上出现一个 Hi 的信息.

因为我们这个模块叫做Hi,所以我们需要三个档案

hi.toc
hi.xml
hi.lua
(模块的名称最好与档案的名称相对应)

现在让我介绍一下hi.toc的格式:

## Interface: 4150
## Title: Hi
## Notes: just want to say hi
## OptionalDeps:
## Dependencies:
hi.xml

在## Interface:后面的数字代表了目前WOW的版本.制作模块的作者有义务维持模块支持最
新版的WOW,所以每当WOW做出更新的时候,模块的制作人得检查模块是否还能工作,当确定还
能工作的时候,就可以更新射个数字.更新这个数字有两个意义:第一,WOW会检查每个模块的
这个数字,如果与WOW版本相辅合,那么就会加载,不然就会档掉.第二,玩家可以确定这个模块
的版本是可以使用的版本.

我在这里不建议除了模块的制作人修改这个数字.因为有时候模块的设计可能很复杂,在不是
制作人的情况下,很可能不知道到底没有更新的模块是否还跟最新版的WOW兼容.如果玩家自
行更改这个数字让它跟WOW的版本数字一样的话,WOW就会自动加载这个模块.如果模块不兼容
的情况下,很可能会造成游戏上的困扰.

写到这里,玩家可能会问要去哪里找WOW最新的版本数字.当执行WOW游戏的时候,在登入的画
面上的最左下方,可以找到这个信息.以目前我写这个教学的时间而言,WOW最新版所提供的信
息是Version 1.2.1 (4150).大家要用的是4150这个数字,而不是1.2.1这个数字.

在## Title:后面,模块制作人打的字符就是这个模块的名称.

在## Notes:后面,模块制作人打的字符就是这个模块的简介

## OptionalDeps:后面, 模块制作人标示出这个模块是否有其它的额外的模块可以支持这个
模块.当这个地方有标示其它的模块的时候,并不代表玩家们也必须要有这个额外模块,只是
有了这个额外的模块,可以让这个么模块的功能更加完整.

## Dependencies:后面, 模块制作人得标示出这个模块必须要使用的的档案(包括了必须使
用到其它模块的档案,请注意,上面选择性模块的档案并不需要在这里标示).

因为这个教学模块并不需要用到其它的模块,所以只需要标示出模块定义文件 hi.xml.

hi.xml的介绍:

基本上XML可以当做网页设计档案(HTML)来看,可是严格的来说,XML是拿来作为定义上或是数
据传输上所使用的.如果玩家对于XML的语法以及如何用有兴趣,可以到
http://www.w3.org/
XML/查询更详细的数据

现在我只介绍XML在WOW模块设计上该如何用.


<Ui xmlns="
http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema
-instance" xsi:schemaLocation="
http://www.blizzard.com/wow/ui/">
<script file="hi.lua"/>

<Frame name="hi_core">
<scripts>
<OnLoad>
this:RegisterEvent("VARIABLES_LOADED");
</OnLoad>
<OnEvent>
if (event == "VARIABLES_LOADED") then
hi_initialize();
end
</OnEvent>
</Scripts>
</Frame>
</Ui>



大家可以忽略前面几行<Ui xmlns ......... />.基本上每一个WOW模块XML文件都必须要有
这几行.

重要的是 <script file="hi.lua"/> 在这里大家得定义出模块的核心档案是什么.以我们目
前的例子,核心档案是hi.lua.

在 <Frame name="hi_core"> 这里定义出模块在游戏画面中要使用的的子画面的名称.这个
名称必须是独一无二的,避免与其它的模块画面冲突到.

在上面的例子中我们可以看到<OnLoad>和<OnEvent>的标示,基本上<OnLoad>的意思是当WOW
在加载游戏接口的时候,因该要做出什么动作.以我们的例子,我们要在WOW游戏里注册一个变
量叫做"VARIABLES_LOADED".
<OnEvent>的意思是,如果发生了什么事件,那么该做出什么动作来反应.以我们的例子,如果
注册"VARIABLES_LOADED"成功的话,我们就执行hi_initialize(). 当然,如果没有注册成功
,也就不会有事件发生,这代表了我们的模块没有加载到游戏里面,所以我们也就没有后续动
作.

hi.lua的介绍:
lua 是一个script语言.WOW所有的UI模块都是建立在这个语言之上.对于lua想要更深入的了
解,请到官方网站:
http://www.lua.org/manual/5.0/ 在这里可以查到所有关于lua的语法以
及使用方式.

现在让我介绍我们目前的例子:


function hi_initialize()
SlashCmdList["HIHI"] = hi_command;
SLASH_HIHI1 = "/hihi";
SLASH_HIHI2 = "/您好";
end

function hi_command(msg)
message(msg);
end




大家可以看到我们写两个小function 一个叫hi_initialize 一个叫 hi_command. 在hi.xml
里面,如果模块顺利在入的话hi_initialize是第一个被呼叫的.在这里我们自行设定了一些
"/"指令.我想大家因该对于游戏里面的一些"/"指令并不陌生.

同样的我们也可以帮我们的模块设定这些"/"指令.
SlashCmdList["HIHI"] = hi_command; 代表的意思是如果我们么组的"/"指令被呼叫的话,
我们因该执行hi_command这一个function.
SLASH_HIHI1 = "/hihi";
SLASH_HIHI2 = "/您好";
这里是帮我们的"/"指令定出名称,目前我还不确定我们是否可以自行自做出中文指令,但是
我想只要可以在WOW输入中文,上面的设计就因该没问题.(所以还请可以在WOW输入中文的玩
家测试一下.
这里要稍微注意的一点是SlashCmdList["HIHI"]里面的HIHI必须要和SLASH_HIHI1和SLASH_HIHI2
的HIHI依样.如果我们把HIHI改成NIHAO 那么就会变成SlashCmdList["NIHAO"], SLASH_NIHAO1
, 以及SLASH_NIHAO2. 至于HIHI 或是 NIHAO 后面的 1 和 2 只是变量,代表了同样的指令
,有哪些变种的指令.

当我们打入了"/hihi"或是"/您好" 就会执行下面的function
function hi_command(msg)
message(msg);
end
基本上只是在游戏画面上出现一个窗口,然后窗口上面显示我们在指令后面打入的讯息.

例如我们输入"/hihi 测试"

那么出现的窗口就会显示 "测试" 在那上面.

好了,我们写好这三个档案了.现在我们要告诉WOW加载我们的HI模块.
首先,到"C:Program FilesWorld of Warcraftinterface"这个子目录里面.如果还没有这个
子目录的话,自行开一个新的.然后在这个目录里面开一个新的目录叫做"AddOns"所有玩家设
计的模块都因该摆在这个目录里面.然后在"AddOns"这个目录里面在开一个目录叫做"HI".最
后把我们做好的三个档案存到这个目录里面.
"C:Program FilesWorld of WarcraftinterfaceAddOnsHI"

现在我们可以测试这个模块了喔.

稍微介绍一下WOW简易管理模块的方式.如果当玩家有安装自行设计的模块的话(比如说COSMOS
),在进入角色选单的时候,我们可以看到画面的左下方有一个Addons的按钮.大家可以在者里
自行选择所希望开启的模块.在模块名子前面打勾,表示选择角色之后,游戏就会开始加载模
块.没打勾就代表不会加载. 请注意,WOW有模块加载的上限.所果所有加载的模块用到的资源
超过32MB,游戏会自动关闭.这时候就需要去管理接口关掉一些模块喔.

下一篇文章,我将教大家如何在lua档案里面用WOW的核心指令,以及如何只使用3个档案,就可
以写出很有帮助的SCRIPT.




Chapter Three

在来一系列的文章,我要教猎人的玩家如何利用模块设计,有效率的执行远距离,近距离,以及
宠物攻击. 顺便介绍一些WOW的核心指令.
我想玩过网络游戏的玩家,多多少少都因该听过外挂.什么是外挂?其实就是能自动的帮助玩
家执行一些指令.基本上很类似MACRO(没听过MACRO的人,因该有听过EZSCRIPT吧)

WOW本身就有提供MACRO这样的功能.只要我们在游戏中输入"MACRO"之后,我们就可以开始设
计我们自己的辅助指令.但是WOW的MACRO有很多限制.第一,WOW的MACRO是半自动的,意思就是
说,你一定要按下某一个键盘按键,或是老鼠按键,才能执行你所设定的MACRO.第二,游戏中的
MACRO有字数上的限制.最多只能输入255个英文字符.第三,WOW的MACRO无法设定时间上面的
间隔.在MACRO里面的所有的指令会被一次执行.第四,如果你所执行的很多指令中有很多都有
指令冷却时间(例如魔法的COOLDOWM),那么MACRO只会执行第一个可以执行的指令.

同样的,当我们设计模块的时候,我们也同样受限于这样的限制,但是却没有255个英文字符的
限定,在这样的情况下,我们可以自做更复杂的指令方式.

今天我要教大家的模块是猎人辅助模块.

WOW的猎人是属于远距离攻击的单位,最需要控制的是如何有要的利用各式的ASPECT以及宠物
攻击.当近距离攻击的时候,猎人需要用到ASPECT OF MONKEY,当远距离攻击的时候,需要用到
ASPECT OF HAWK. 但是我想很多人因该都会遇到,同时指示宠物攻击,玩家攻击,以及转换ASPECT
的时候,会手忙脚乱.现在我们的目标是如何设计一个模块可以让我们在操作上更顺畅.

猎人辅助模块设计目标:
1:玩家主动攻击的时候,宠物也会主动攻击(WOW的基本模式是,玩家按攻击,然后还要按宠物
攻击).

2:玩家与宠物永远是攻击同一个目标,以最快最有效率的方式来减少战斗画面上的危机.避免
宠物与玩家通时攻击不同的敌人,造成最后的结果是玩家与宠物同时阵亡.

3:有效的辨识玩家的攻击方式,然后执行最有效率的ASPECT.例如玩家近距离攻击的时候不是
在ASPECT OF HAWK的状况下.

4:有效的用远距离攻击技能(包括了节省MANA,快速选择敌人目标等等)

好了,有了以上的目标,现在开始让我们来设计.首先,来制作模块所需要的最基本的三个档案
.因为我替我的模块设计的名称叫做HunterAssistant(猎人辅助),所以我的三个基本档案叫
做:
HunterAssistant.toc
HunterAssistant.xml
HunterAssistant.lua


HunterAssistant.toc:
## Interface: 4150
## Title: Hunter Assistant V0.1
## Notes: Macro scripts for assisting Hunter
## OptionalDeps:
## Dependencies:
HunterAssistant.xml

HunterAssistant.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Ui xmlns="
http://www.blizzard.com/wow/ui/"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.blizzard.com/wow/ui/">
<script file="HunterAssistant.lua"/>

<Frame name="HunterAssistantFrame">
<scripts>
<OnLoad>
this:RegisterEvent("VARIABLES_LOADED");
</OnLoad>
<OnEvent>
if (event == "VARIABLES_LOADED") then
HunterAssistant_init();
end
</OnEvent>
</Scripts>
</Frame>
</Ui>




我将不在第这两个档案多做解释.有疑问的,请参考上一篇文章.毕竟我只使用的最简单的设
计.
现在的重点LUA核心檔.我先把档案内容列出来,然后在以另外的文章详细的解释每个指令.

HunterAssistant.lua:


function HunterAssistant_init()
-- define slash command here
SlashCmdList["HA_HunterMarkI"] = HA_HunterMarkI;
SLASH_HA_HunterMarkI1 = "/HAHunterMarkI";
SLASH_HA_HunterMarkI2 = "/hahmi";

SlashCmdList["HA_HunterMarkII"] = HA_HunterMarkII;
SLASH_HA_HunterMarkII1 = "/HAHunterMarkII";
SLASH_HA_HunterMarkII2 = "/hahmii";

SlashCmdList["HA_AttackMelee"] = HA_AttackMelee;
SLASH_HA_AttackMelee1 = "/HAAttackMelee";
SLASH_HA_AttackMelee2 = "/haam";

SlashCmdList["HA_AttackRangeI"] = HA_AttackRangeI;
SLASH_HA_AttackRangeI1 = "/HAAttackRangeI";
SLASH_HA_AttackRangeI2 = "/haari";

SlashCmdList["HA_AttackRangeII"] = HA_AttackRangeII;
SLASH_HA_AttackRangeII1 = "/HAAttackRangeII";
SLASH_HA_AttackRangeII2 = "/haarii";

SlashCmdList["HA_StingSerpentI"] = HA_StingSerpentI;
SLASH_HA_StingSerpentI1 = "/HAStingSerpentI";
SLASH_HA_StingSerpentI2 = "/hasseri";

SlashCmdList["HA_StingSerpentII"] = HA_StingSerpentII;
SLASH_HA_StingSerpentII1 = "/HAStingSerpentII";
SLASH_HA_StingSerpentII2 = "/hasserii";

SlashCmdList["HA_StingSerpentIII"] = HA_StingSerpentIII;
SLASH_HA_StingSerpentII1 = "/HAStingSerpentIII";
SLASH_HA_StingSerpentII2 = "/hasseriii";

SlashCmdList["HunterTest"] = HunterTest_command;
SLASH_HunterTest1 = "/HunterTest";
SLASH_HunterTest2 = "/ht";
end





function HA_AttackMelee()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Attack");
x=1
found=false;
while (UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Monkey")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Monkey");
end;
end;
end




function HA_AttackRangeI()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Auto Shot");
x=1
found=false;
while (UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Raven")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Hawk(Rank 1)");
end;
end;
end




function HA_AttackRangeII()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Auto Shot");
x=1
found=false;
while (UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Raven")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Hawk(Rank 2)");
end;
end;
end




function HA_HunterMarkI()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Hunter's Mark(Rank 1)");
end;
end




function HA_HunterMarkII()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Hunter's Mark(Rank 2)");
end;
end




function HA_StingSerpentI()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
x=1
found=false;
while (UnitDebuff("target",x)) do
if(string.find(UnitDebuff("target",x), "Quickshot")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Serpent Sting(Rank 1)");
end;
end;
end




function HA_StingSerpentII()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
x=1
found=false;
while (UnitDebuff("target",x)) do
if(string.find(UnitDebuff("target",x), "Quickshot")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Serpent Sting(Rank 2)");
end;
end;
end




function HA_StingSerpentIII()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
x=1
found=false;
while (UnitDebuff("target",x)) do
if(string.find(UnitDebuff("target",x), "Quickshot")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Serpent Sting(Rank 3)");
end;
end;
end




function HunterTest_command()
x=1
found=false;
while(UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Raven")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Hawk(Rank 1)");
end;
if(found) then
CastSpellByName("Aspect of the Monkey");
end;
end


Chapter Four
首先我要说声抱歉,因为我没注意到基地的文章发表没有办法显示"TAB"的空格.这样在查看
程序代码,一定会造成困扰.如果大家在看程序代码会眼睛痛的时候,还请见谅.

现在,让我们研究一下HunterAssistant.lua第一段:

function HunterAssistant_init()
-- define slash command here
SlashCmdList["HA_HunterMarkI"] = HA_HunterMarkI;
SLASH_HA_HunterMarkI1 = "/HAHunterMarkI";
SLASH_HA_HunterMarkI2 = "/hahmi";

SlashCmdList["HA_HunterMarkII"] = HA_HunterMarkII;
SLASH_HA_HunterMarkII1 = "/HAHunterMarkII";
SLASH_HA_HunterMarkII2 = "/hahmii";

SlashCmdList["HA_AttackMelee"] = HA_AttackMelee;
SLASH_HA_AttackMelee1 = "/HAAttackMelee";
SLASH_HA_AttackMelee2 = "/haam";

SlashCmdList["HA_AttackRangeI"] = HA_AttackRangeI;
SLASH_HA_AttackRangeI1 = "/HAAttackRangeI";
SLASH_HA_AttackRangeI2 = "/haari";

SlashCmdList["HA_AttackRangeII"] = HA_AttackRangeII;
SLASH_HA_AttackRangeII1 = "/HAAttackRangeII";
SLASH_HA_AttackRangeII2 = "/haarii";

SlashCmdList["HA_StingSerpentI"] = HA_StingSerpentI;
SLASH_HA_StingSerpentI1 = "/HAStingSerpentI";
SLASH_HA_StingSerpentI2 = "/hasseri";

SlashCmdList["HA_StingSerpentII"] = HA_StingSerpentII;
SLASH_HA_StingSerpentII1 = "/HAStingSerpentII";
SLASH_HA_StingSerpentII2 = "/hasserii";

SlashCmdList["HA_StingSerpentIII"] = HA_StingSerpentIII;
SLASH_HA_StingSerpentII1 = "/HAStingSerpentIII";
SLASH_HA_StingSerpentII2 = "/hasseriii";

SlashCmdList["HunterTest"] = HunterTest_command;
SLASH_HunterTest1 = "/HunterTest";
SLASH_HunterTest2 = "/ht";
end




附注:HA_代表的意思是HunterAssistant的缩写.

其实这里没有什么特别的.这里只是帮模块设定一些简单的"/"指令.将来我们可以直接把这
些指令用到游戏的MACRO中. 请注意的一点是,每一个指令都有一个FUNCTION相对应.另外,我
每一个指令都一个全名指令,以及一个简写指令(方便使用).在指令命名设计上,我以看到指
令名称就大概能猜到使用的结果是什么.还有就是每个指令前面加上HA_这样能有效的避免跟
其它模块的指令冲突到.另外有几个指令后面有罗马数字,这些是代表了所使用到的猎人技能
是有等级高低的.比如说HA_HunterMarkI使用的是等级1的Hunter's Mark,HA_HunterMarkII
使用的是等级2的Hunter's Mark.

另外,我的指令排列是以英文顺序为主.这样方便我个人寻找BUG.

现在让我们继续往下看.


function HA_AttackMelee()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Attack");
x=1
found=false;
while (UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Monkey")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Monkey");
end;
end;
end



这一个function的主要目的是近距离攻击.首先第一行是AssistUnit("pet");这代表了什么
?其实这是WOW的核心指令之一.AssistUnit()的意思是帮助某一个单位的意思.这个指令可以
接受不同的变量,包括玩家单位,NPC友好单位,以及宠物单位.当执行了这个指令之后,你的敌
人对象就会变成你所帮助的那个单位的敌人是同一个.在这里"pet"的意思就是主角单位的宠
物.

我在这里会用AssistUnit("pet")开头的原因是,当你的宠物在攻击的时候敌人的时候,你跟
你的宠物所选择的敌人不见得是同一个,所以我们要确定主角跟宠物攻击的对象是同一个.

(注意:目前我这样的设计好像有点逻辑上的问题.思考逻辑到底是主角该帮主宠物还是宠物
帮助主角?游戏中的基本设定是主角受到攻击,宠物就会自动帮助第一个攻击主角的敌人,可
是如果好几个人攻击主角,宠物还是会先专心的把第一个敌人解决掉.所以我一开始会这样设
计,专心的先帮助宠物解决掉第一个敌人.可是当遇到我就是有特殊原因要先解决掉其它的敌
人的时候(例如某些特殊任务),我这样的设计反而造成困扰,因为只要我一攻击,我的对象就
就转换到宠物的敌人了.所以在未来的版本中,我可能会设定另一种攻击是,宠物永远帮助主
角攻击同一个敌人,使用的指令是 PetAssistUnit("Player"). "Player"就是代表主角的意
思.)

下一行, if(not UnitExists("target")) then
TargetNearestEnemy();
end;
这里的意思是检查执行帮忙的指令之后(AssistUnit())到底有没有敌人?如果主角的宠物没
有在战斗状态,那么我们敌人的状态就是没有选择.UnitExists("target")) 就是检查我们有
没有选择任何的目标.这个也是WOW的核心指令之一. 当然如果我们有选择目标,可是目标是
有好单位呢?不用担心,WOW的设计本来就是无法攻击友好单位的.那么TargetNearestEnemy(
)又是什么意思呢?就是自动选择距离最近的非有好单位当作目标选项.所以这一段的意思就
是,如果主角跟主角的宠物都没有目标的话,帮主角动挑一个最近的非有好单位当作目标.

在来

if(UnitExists("target")) then
PetAttack();
CastSpellByName("Attack");


这里代表的是,如果有目标的话,宠物攻击,然后主角攻击.PetAttack()是宠物攻击的指令,CastSpellByName
("Attack")的意思是主角施展技能,这个技能是攻击(Attack). 这些全都是WOW的核心指令喔
,酷吧.

继续

x=1
found=false;
while (UnitBuff("player",x)) do

found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Monkey");
end;
end;
end




这里我定义了一个变量X,以及一个变量FOUND(中文是找到的意思),这两个变量不是WOW的专
有变量,而是LUA的语法喔.为什么需要这两个变量?因为当我们在近距离攻击的时候,我必须
要确定主角是在于ASPECT OF MONKEY 之下,有了这些变量可以方便我来做检查.

while (UnitBuff("player",x))的意思就是如果在主角的身上可以找到Buff的话. UnitBuff
("player",1)会在寻找主角身上第一个buff的数据,然后传回讯息.如果没找到,就会传回一
个否定的讯息.UnitBuff("player",2)就是寻找第二个buff的数据.

if(string.find(UnitBuff("player",x), "Monkey"))
string.find是lua语言上的指令,不是WOW的核心指令.这个指令的目的是寻找一个讯息中的
字符串是否有特殊的字符.所以这一整段的意思是找寻主角身上的buff的信息是否有MONKEY
(猴子)的字符串.如果有的话,就把FOUND设定为TRUE.

if(not found) then
CastSpellByName("Aspect of the Monkey");
这一段就是如果从头到尾都没有找相关的buff的话,代表了主角没有施展"Aspect of the Monkey
",所以我们就执行施展技能的指令CastSpellByName("Aspect of the Monkey").

写到这里,让我顺便提出一些要点.不晓得大家有没有发现到,在这个function里面,从头到尾
只有一个指令需要冷却时间那就是CastSpellByName("Aspect of the Monkey").其它,比如
说攻击,全部都不需要冷却时间.这也就是为什么这么多指令都可以转变成一个单一指令.但
是因为CastSpellByName("Aspect of the Monkey")需要冷却时间,所以我把她摆在最后执行
,避免错误.另外一点就是,很多人在找寻主角身上的buff数据的时候,喜欢直接用UnitBuff(
"player",1)却没有想到其实主角身上可能有很多的buff呢.

所以我这样的设计一定可以确保如果主角已经施展了Aspect of the Monkey,就绝对不会重
复施展第二次(浪费mana喔).
至于这个function 里面的一些IF, WHILE, NOT等等的用以及正确的语法,就请大家到LUA的
官方网站去看.我就不多解释了.

在来是猎人的普通远距离攻击

function HA_AttackRangeI()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Auto Shot");
x=1
found=false;
while (UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Raven")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Hawk(Rank 1)");
end;
end;
end




这一段其实跟近距离的普通攻击是同样的逻辑,但是CastSpellByName("Auto Shot") 这个是
猎人专有的远距离自动攻击的指令.同样的这个指令可以跟其它需要冷却时间的指令同时使
用.另外CastSpellByName("Aspect of the Hawk(Rank 1)") 这是执行第一级的ASPECT OF
THE HAWK. 在我们模块function HA_AttackRangeII()里面就会执行第二级的ASPECT OF THE
HAWK, CastSpellByName("Aspect of the Hawk(Rank 2)")

function HA_HunterMarkI()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
CastSpellByName("Hunter's Mark(Rank 1)");
end;
end



这一段没有什么特别的,唯一的好处就是当主角开始使用MARK的技能的时候,就开始命令宠物
攻击.我们不需要按两个动作.另外,Hunter's Mark 也是有等级之分的,所以我写了其它相对
应的等级指令
注意:(这个FUNCTION我还没有完全的完成,因为我没有检查是否敌人已经被MARK过了,也就是
说这个指令允许重复MARK敌人,浪费MANA)

function HA_StingSerpentI()
AssistUnit("pet");
if(not UnitExists("target")) then
TargetNearestEnemy();
end;
if(UnitExists("target")) then
PetAttack();
x=1
found=false;
while (UnitDebuff("target",x)) do
if(string.find(UnitDebuff("target",x), "Quickshot")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Serpent Sting(Rank 1)");
end;
end;
end



这一个跟普通远距离攻击的指令很像,但是并不是使用普通的AUTO SHOT,而是使用了Serpent
Sting.另外这一个指令不会检查主角本身是否施展了ASPECT OF HAWK.因为Serpent Sting
跟aspect of the hawk都要冷却时间,两个写在一起,只会执行其中的一个,那么就一点意义
都没有了.既然这样,为什么要写这一个指令?其实这个指令会检查敌人身上是否已经被施展
了Serpent Sting,毕竟Serpent Sting没有加成效过,所以我们要避免重复施展Serpent Sting
.而WOW的基本Serpent Sting指令是不会做这样的检查的,所以我们还得一直盯着敌人的信息
看着,避免浪费MANA.可是设计了另外的这个指令,玩家根本不用担心浪费MANA,只要想到了就
执行一下,反证会自动检查,也不会中断AOTU SHOT的动作,更不会浪费MANA.另外,这个指令也
有设计其它不同等级的相对应指令.

最后

function HunterTest_command()
x=1
found=false;
while(UnitBuff("player",x)) do
if(string.find(UnitBuff("player",x), "Raven")) then
found=true;
end;
x=x+1;
end;
if(not found) then
CastSpellByName("Aspect of the Hawk(Rank 1)");
end;
if(found) then
CastSpellByName("Aspect of the Monkey");
end;
end



这个指令只是我设计好玩拿来测试用的,当执行这个指令的时候,主角会交互的使用ASPECT
OF MONKEY 或者 ASPECT OF HAWK.

模块的核心指令介绍到这里,下一篇文章将教玩家如何在游戏里用这些指令.

目前我们的模块有了最基本的三个档案了.现在让我们把这三个档案放入C:Program FilesWorld
of WarcraftInterfaceAddOnsHunterAssistant这个数据夹里面.然后执行游戏.

现在让我解释一下WOW上面所谓的斜线指令("/指令")该如何用.

大家因该都清楚如何的用感情指令,或是交谈指令.这些都是斜线指令.但是WOW还有一些斜线
指令是无法直接的输入, 比如说"/attack". 基本上这是WOW官方设计的攻击指令,其背后只
是很简单的呼叫了CastSpellByName("Attack"). 但是为什么我们无法直接使用这些指令呢
?因为暴风雪为了避免玩家利用其它的程序来设计非法的MACRO.

怎么说呢?因为WOW的MACRO没有时间间隔设计,避免玩家设计机器人,那么玩家设计机器人就
必须利用其它的程序.如果,设计机器人,机器人程序就可以直接的仿真键盘输入指令,而不会
影响到玩家对于鼠标的操做.所以WOW把很多的斜线指令的操作设定成只有在WOW的MACRO下才
能使用.你设计一个MACRO以及MACRO图像按钮,你要执行这个MACRO,你就必须对这个按钮按一
下,WOW才会执行这个动作.

当然,还是有其它的办法摆脱暴风雪这样的设计,但是我不会对类似这样的问题做出任和解说
.因为暴风雪尽力的维护游戏免于外挂的侵入,身为玩家的我也有义务要帮助暴风雪.

有这样的限制的斜线指令包括了所有的会使用到执行特殊技能的指令.所以当我们设计的模
块有用到执行特殊技能的时候,我们的斜线指令也只能在WOW下面的MACRO才能执行.(当然,我
们的猎人辅助模块还是用在MACRO下面比较好,毕竟在战斗的时候谁还有时间慢慢的的用键盘
输入指令,我们又不是机器人)

要使用WOW的MACRO很简单,只要在游戏中输入"/macro"或是按下Esc 然后选择macro的选项

在macor的画面,我们必须帮macro选择一个图像按钮,替macro命名,然后输入我们想要给macro
的指令.

现在让我列出猎人辅助模块的简易斜线指令:
Hunter's Mark 包括了不同的等级
/hahmi
/hahmii

Melee Attack(近距离攻击)
/haam"

Range Attack (远距离攻击)包括了不同的等级
/haari
/haarii

Serpent Sting(远距离特技)包括了不同的等级
/hasseri
/hasserii
/hasseriii

现在我们只要把macro的图像按钮选择好,然后给个名子,最后在底下输入指令的地方,挑一个
你想要执行的辅助指令输入就好了. 注意喔,一个macro只能使用模块的一个指令喔,因为就
算你输入了很多个,在执行macro的时候,游戏也只会执行情中的一个而已.(冷却时间的考虑
)

当你设定好了macro之后,WALA~~~,你就可以把这个图形按钮抓到快捷工具栏上面使用了~~~
就像是使用任何其它的基本图形按钮依样喔.好处是,你按一次按钮,却等于其它没有用辅助
模块人按好几次按钮依样喔.还会自动帮你做一些额外的检查呢.有效率了多吧.
下一次,我将教大家如何设计辅助模块可以帮大家在半自动的施展BUFF,对象也会半自动的选
择队友,宠物,或是自己.
附注1:因为我个人玩了10角色,包括了联盟的每一个CLASS,在未来的日子里,我将会不定期的
替自己写模块.如此同时,我也会拿上来与大家分享.但是我将不会再花这么多的时间详细解
释每一个指令.除非有网友提出问题,那时我会在尽力回答.

附注2:有关WOW的核心开放给玩家使用的指令,大家可以到这个网页找到.但是这里不是完整
的列表,说明也不是很清楚,不过大家将就的用噜.
http://www.wowwiki.com/World_of_Warcraft_API

附注3:最有效率的研究模块的方式,就是到官网的UI Customization的论坛参与讨论喔.也许
大家会找到一些意想不到,但是又很有帮助的模块喔.我个人就已经发现有人设计了一个挖矿
采要的模块,这个模块会把你最到过的挖矿以及采药的地点纪录下来,然后显示在地图上.怎
么样,很有用吧.





Chapter Five
或许我在模块解释以及使用教学方面,因该采用更简单的例子来让大家能更容易上手.所以我
决定不要直接的把我个人写好的模块拿上来,而是先的教大家如何使用WOW的MACRO,以及呼叫
一些WOW的指令.

首先让我重新的介绍一下WOW的MACOR
(基本资料来源 魔兽台湾:
http://www.wowtw.game.tw/)

在"魔兽台湾"的网页里,我们可以找到很清楚的MACOR中文定义以及解释:

宏[Macro]使你能够创建自己独创且非常酷的命令集,你可以通过点击一个按钮便完成一系
列的命令。宏拥有许多用法。

宏的创建

输入“/macro”或者点击谈话[talk]按钮并且选择宏[Macro]选项,将会弹出一个对话框,
里面记录着你现有的宏。在开始的时候里面应该没有任何宏。
点击对话框底部的”new”按钮,将会弹出另外一个对话框,其中要求你输入宏的名称并且
为这个宏选择一个图标。
给你的宏命名,选择一个容易记忆的名字。例如,输入“assist[协助]”。
选择一个图标。这里我们选择的是一把剑。
点击“Okay”按钮。你现在能够在你的宏对话框里看到这个宏的名称(assist),在名称的旁
边有你刚才选择的图标(剑)。
现在在assist[协助]图标上点鼠标左键加亮它。除了“new”按钮外,同时也有一个按钮用
来改变你的宏的名称和图标,以便你以后想改变它的名称或者选择一个不同的图标。
一旦你的“assist”图标是加亮状态,你就可以向下移动你的鼠标指针进入“enter macro
commands[输入宏命令]的区域。在这里你可以输入你想让这个宏按钮实现的命令。
输入“/assist Nebu[协助Nebu]”。
现在移动你的鼠标指针回到剑的图标(assist[协助]宏),在这个图标上压下鼠标的左键不松
开。
现在拖动图标到你的动作条的空槽里去。
当你要使用这个新的宏的时候,键入这个动作按钮对应的数字或者直接右键点击按钮本身。

现在你拥有了一个宏按钮,它将在其它玩家(Nebu)攻击的时候协助他。无论何时,当Nebu攻
击目标的时候,点击这个按钮后你的目标将会变为他正在攻击的目标。

以上是"魔兽台湾"给予MACRO的中文解释,以及一个很简单的例子.

现在让我们稍微加强一下上面的例子.

上面的例子里面,我们看到了MACRO的内容只有一行

/assist Nebu

现在我们来加强一下,让这个MACRO不但会协助,还会马上攻击.改过的MACRO会像底下这样.

/assist Nebu
/attack

好了,现在我们的MACRO有两行了.这个MACRO的目的是,协助Nebu(指定Nebu的敌人),然后攻击
.

那么现在让我们写一个很简单以及实用的MACRO.加设Nebu是一个牧师,我们要帮Nebu写一个
自动帮自己使用基本治疗的MACRO.

/target Nebu
/cast Lesser Heal(Rank 1)

以上的MACRO在执行的时候,每次都会选择Nebu作为治疗的对象.其中,/target Nebu 是选择
Nebu为对象,/cast Lesser Heal(Rank 1)是对于对象施展Lesser Heal第一级的法术.

我想以上的例子因该已经很清楚的解释了基本的MACRO该如何使用.可是在在"魔兽台湾"的网
页里也有提到:

宏的限制
宏是有长度限制的,如果你的信息太长了,就缩减一些!(显然)

这一点是没有错的,因为WOW的MACRO有255个英文字符的限制.我们该如何突破这个限制呢?

首先让我们先了解一下WOW的官方斜线指令.

上面那些MACRO里所用到的斜线指令,其实背后都有呼叫一些核心指令.例如:

/assist Nebu 呼叫了 AssistUnit("Nebu")
/attack 呼叫了 Attack("Target")
/target Nebu 呼叫了 TargetByName("Nebu")
/cast Lesser Heal(Rank 1) 呼叫了 CastSpellByName("Lesser Heal(Rank 1)")

这些核心指令除了可以使用官方的斜线指令来呼叫之外,我们还有其它几种方式来使用这些
核心指令.

第一种方式,直接在MACRO里使用这些核心指令.要直接使用这些核心指令,我们必须用到一个
斜线指令叫做/Script.

以下是把上面的MACRO例子改成使用核心指令的方式.
第一个MACRO 帮助Nebu攻击敌人
/Script AssistUnit("Nebu");
/Script Attack("Target");
第二个MACRO选择Nebu作为治疗的对象
/Script TargetByName("Nebu");
/Script CastSpellByName("Lesser Heal(Rank 1)");
要注意的一点是,当使用了/Script的时候,MACRO的每一行指令都要有";"作为结尾.

直接使用核心指令的好处是什么?因为WOW并没有帮每一个核心指令写对应的斜线指令,而很
多的核心指令的功能却是非常强大的.

核心指令除了能直接利用在MACRO之外,另一个用途就是可以使用在模块里面使用.关于使用
上的例子,大家可以参考我前几篇文章所提供的猎人辅助模块.在这里我们就可以利用模块所
提供的斜线指令来变相的突破了MACRO上面的字符限制了.

希望这一篇文章能更容易的让大家了解斜线指令,核心指令,MACRO,以及模块的用途.

>※littlethe(东周小星星)提到:
>我是个programmer,
>macro在程序中是指宏指令,
>若我没有弄错的话,
>这个macro是不是用于制定"连续动作"用的?
>
>按个键,
>人物就会做出连续预设动作,
>
>若是这样,
>那wow可还真特别,
>开放玩家编写macro,
>
>等我拿到wow时,
>要好好的来玩看看

恩~没有错喔

可是WOW本身的MACRO有很多的限制.可是如果玩家使用非游戏本身的MACRO来玩WOW,暴风雪就
可以砍此玩家的账号.

WOW本身的MACRO先天上就没有时间的设计.也就是说,MACRO里面所有的动作指令,通通当作及
时指令(当然,非常严格的来说还是会有先后顺序上的差别,可是时间上的差别只有不到0.1秒
.)这样的设计是避免玩家制作机器人.

另外,WOW很多的技能有冷却时间,如果把多个有冷却时间的技能写入MACRO,那么MACRO只会执
行第一个达到条件的技能,其它有冷却时间的技能都会被忽略.
>※littlethe(东周小星星)提到:
>虾米??
>那这样的话,
>那岂不就不能使用连续法术了?
>法术也有cast time不是么?
>还是wow的法术都是direct的?
>哇累...
>本来想说能不能来个先闪电再插补血丈后嗜血之类的
WOW的技能大约能分为三种,实时的,有冷却时间的,需要施展时间的.

实时的就是可以一直连续使用.

有冷却时间的就是在使用过后,有一个时间限制是不能使用同一招.另外,使用这种技能之后
,还会有大约不到一秒的时间无法使用任何其它的技能.

需要施展时间的,当使用的时候,在技能完全施展之前,无法使用任何其它的技能,除非先取消
掉.

所以只要是有被时间限制上的技能,在MACRO里,就只有一个可以被驱动,而且最好是摆在MACRO
的最后一行.如果摆在太前面,那么很可能就会使得后面的实时技能被挡掉.

>※willllee(balmung)提到:
>那可以用macro来配合其它程序吗?
使用任何不是魔兽纪元本身所提供的功能来执行游戏,都违反了魔兽纪元的使用条约.所以我
无法在这里回答您所提出的其它的相关问题.
但是有一点可以确定的是,魔兽纪元所提供的核心指令,已经可以做出广大的环境判断了.包
括判定血量多少,队友以及其宠物的状态,敌人的状态,等等.

目前官方论坛上已经有很多的模块能提供类似的功能.包括当自身血量低于某百分比,执行动
作的时候,会先帮自己补血(魔法或是对象,取决于是否在战斗中),以及根据队友的血量百分
比来决定宠物会先帮助哪个队友攻击.

如果有兴趣的网友,甚至可以写出根据敌人的状态做出不同的攻击或是反应的模块.

基本上,这些都可以只用到核心指令来达到的.





评论 / 个人网页 / 扔小纸条
* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 


 

分类小组论坛
杂谈 , 娱乐、八卦 , 文学、艺术 , 体育 , 旅游、同城 , 象牙塔 , 情感 , 时尚、生活 , 星座 , 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定