游戏可以这样玩
日历
网志分类
· 所有网志 (14)
· 插件介绍 (4)
· 界面修改 (5)
· 转载精华 (5)
最新的评论
站内搜索
友情链接
· 我的歪酷 非非共享界

订阅 RSS

0036834

歪酷博客

专门用来发布,交流,展示自己通过插件制作的各种wow(魔兽世界)效果图,欢迎有兴趣者共同切磋。
凡人狼 @ 2006-02-25 17:20

在DAB,DUF,DART还没有被汉化的时代,经常会出现中文字体无法显示的问题,经常被人说成是英文版本的问题,确实在汉化版出现后,这样的问题少了很多,不过还是有必要对字体问题做一番解释。

cwow中不存在中英文字体的冲突问题,理论上说,wow应该也能显示中文,关键就是个字库的定义问题,一个字体就是一个字库,为什么中文字体动辄好几兆,而英文字体就几十k呢?原因就是中文字体里边有好几千的汉字,而英文字库只有大小写加一起不到100个文字。

想要显示中文,只要把显示中文这个位置的字体的对应文件设置成一个中文字体就可以了。

wow默认的字体存在fonts目录下边,1.10以前,我们可以通过直接在fonts目录下边存储同名的font文件而达到替换系统默认字体的目的,而1.10版以后,据说blz要改变文件读取顺序,优先读取mpq里边的文件,这也就是说我们不能再这样简单的修改字体了,只能通过修改mpq里边的文件来达到同样的目的。具体怎样改,1.10来了再说。


目前我们使用的许多插件,是自己自带了字体文件的,而在使用的时候可以直接指向这里,而不是指向系统默认字体,这就给我们提供了便利的修改可能。

比如duf目录下的customfonts目录,里边有font1.ttf-font5.ttf五个字体,我们如果想要使用中文字体,只要替换进去或者原封不动的拷进去,再在duf的字体定义框里输入这个中文字体的名字就可以了。

具体方法是:

1将中文字体拷入DUF下的CUSTOMFONTS目录,替换掉系统原有的DUF_Font1.ttf就正常了,名字就用DUF_Font1.ttf,因为duf的默认字体不是font1就是font2。

2将中文字体拷入DUF下的CUSTOMFONTS目录,然后进入游戏,在游戏中把所有DUF_Font1.ttf改成拷进去的这个中文字体的名字(中文字体请用字母和数字命名,不要使用汉字命名)。

同理,可以任意在游戏中修改字体对应文件,只要事先将中英文字体拷入FONTS目录即可,很多很漂亮的效果都来自于漂亮的字体。 

总结下来,字体替换就是两种方法,一个是偷梁换柱,不改名字,改字体,另一个是指鹿为马,在游戏中制定你自己喜欢的字体文件作为显示字体。

这样说是否都明白了?



还有人经常问:哪里有好看的字体,哪里有准圆字体?

最简单的回答:www.google.com ,我一般是不管发字体的。

为了对提问者负责,我就再多说两句。在哪里可以找到漂亮的中英文,数字字体呢?3个来源。

1.互联网,字库网站多的是,各种特效字体都有。一般中文分为简体和繁体,字库越大,字越全。英文字库数量极其庞大,而且效果N多,但是注意,一部分的英文字库没有数字的字体,大部分的英文字库没有特殊符号的字体,如%。这个需要自己挑选一下。

目前我在使用的中文字体就有方正综艺简体,华康少女文字简体,准圆体。

2.windows系统目录下的fonts目录,是用windows的都有这个目录,里边最少也有几种中文字体,有几十种常用英文字体,我的英文字体就是直接从里边拷过来的,不是从网上找的,这里的字体一般都有对应的数字字体。

3.高手给出的界面压缩包,这里很可能找到漂亮的英文数字字体,外国人总是比中国人对英文字体更在行,而且英文字体也小,几十k就可以了,放在压缩包里也有可能,多去看看人家的成品,很多都给了字体。


知道了字体的原理之后,1.10之后,我们想用我们喜欢的字体也是很容易的,估计狂鼠会比我更关心字体问题,到时候就等他来解决,我只管写教程就可以了。




 
凡人狼 @ 2006-02-25 15:56

首先,为什么要制作custom文件,因为custom和defult是D系列都有的两个通用设置,其中,defult是系统默认设置,最好不要改动,custom则是系统提供给D系列用户最方便的交流方式,可以自己制作CUSTOM文件,用来传播交流,下载者只需要将DAB_custom.lua文件拷入自己的DAB在addons下的目录里,而不用去改变在WTF里边的存档文件。同理,如果你下载的别人的配置,他不够专业,没有提供custom文件,你也可以制作,这样就不会影响到自己的原有设定。

只不过制作起来并不是傻瓜化的,至少现在还不是,需要自己手动改一下,不过改起来还是相当方便的。

制作工具以我常用的NOTEPAD++为准,其他的编辑软件也可以,大同小异。

首先介绍一个常识:汉字的显示,在LUA和XML文件里,如果想要正常的显示和输入汉字,必须使用UTF-8作为编码格式。

在格式选项里可以设置。



下边讲解custom文件的制作方式。

首先打开自己在wtf下边的那个存档文件,或者你下载的那个存档文件,打开后找到你的目标存档的名字,这个名字不是你的人物名,而是你存储设置时候输入的名字,比如:“文化人”,或者你下载的文档里边的设置名字:“菲菲”,等等。

因为UTF-8的存在,可能用搜索功能查找汉字可能会找不到,你就自己手动找吧,其实也很简单,通过视图里边的折叠功能,你可以把文件的长度变的很短。


这样就方便你查找了。

然后找到你的目标设置名字,一定要是设置名,而不是角色名或者服务器名。


找到之后,把设置名后边那个大括号里边的所有内容都拷贝下来,这里如果用专业的编辑工具,大括号的范围会非常明显,不容易选错。如果选错了就多试几次。

然后打开你的DAB或者DUF的目录,找到DAB_CUSTOM.LUA或者DUF_CUSTOM.LUA文件,打开,你会发现,他们的结构非常相似,你只要把DAB_CUSTOM_SETTINGS ={}中间的内容完全替换成你刚刚拷贝的内容就可以了。


是不是非常容易?然后你打开进入游戏之后,直接load这个CUSTOM的设置就搞定了。

不过还是要提醒一下,load之后请马上新建一个设置,这样可以保留你的CUSTOM设置,而且,以前D系列的CUSTOM和defult设置的自动存储有点问题,可能你做了改动重起之后不会保留,这点需要注意。



 
凡人狼 @ 2006-02-24 11:24

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

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

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

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



 
凡人狼 @ 2006-02-24 11:23

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的论坛参与讨论喔.也许
大家会找到一些意想不到,但是又很有帮助的模块喔.我个人就已经发现有人设计了一个挖矿
采要的模块,这个模块会把你最到过的挖矿以及采药的地点纪录下来,然后显示在地图上.怎
么样,很有用吧.


 
凡人狼 @ 2006-02-24 11:22

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