十三 的个人资料十三の地盘照片日志列表更多 工具 帮助

日志


2007/2/5

宏从入门到精通(盗贼专用)

一直看各种宏的教学,没有一片足够清晰严格的。

在这些教学里,函数的变量和作用都没有说明,宏的语法也没有说明,这样对玩家自己改进宏十分不利。
那些写宏教程的也很奇怪,难道都不屑于说明语法么?或者就是直接从国外网站照样copy过来的?
恩,对大多数人可能不管黑猫白猫复制下来能用的宏就万事ok了...但我个人不喜欢不求甚解的态度,
而且看见过的多数拿出来分享给别人用的宏,用计算机专业的标准衡量,代码往往冗余,这就意味着
效率的损失,也就意味着片刻的延时,或许片刻就是生死的分界线....
这篇宏的经验文章写给那些想多了解一些宏的知识的玩家,
如果不想自己动手写宏的玩家不用往下看。


1,宏的基本常识
宏是一个脚本,发送到服务器端执行。这个脚本由一组命令序列构成,长度不超过255个字符。
序列中的每一个命令,由一个/ 开头,例如/say /script 等等。
/script 后面跟随脚本特有的语句和函数。

你可以罗列多个/script命令在一个脚本里,也可以在一个/script命令中写多个函数,这都可以。
因为宏就是依次执行所有的命令,所以不需要在宏的最后添加end 标记,或在命令之间加;
事实上,end标记 是if语句的组成部分,你在写if语句时才用到end关键字。命令和命令之间用
换行或; 隔开都可以,我喜欢用换行..呵呵,省掉不必要的; 代码也清楚些

常用的if语句语法如下:

/script if [条件表达式] then [命令序列] end
or
/script if [条件表达式] then [命令序列1] else [命令序列2] end

这里条件表达式不需要在外面套括号,和C,java的习惯不同,应该是为了减少不必要的字符数,
毕竟WOW宏有长度限制。

条件表达式 中 相等用 == , 否定用not, 不等于可以写 not (A == B),
暴雪没有提供!= 作为不等于,很奇怪。 例子:
if sword == GetInventoryItemLink("player", 16) then ....
if not (sword == GetInventoryItemLink("player", 16)) then ....

注1,这里的sword是全局变量。每一个全局变量的生命周期是一次登陆中从声明变量到退出魔兽,
通常在每次登陆后额外运行一个设定宏来设定我们所需要的全局变量。

注2,GetInventoryItemLink()是一个取装备link的函数,
GetInventoryItemLink("player", number)是从人物身上取装备的link,number代表人物装备画面的不同槽, 头部,颈部,依次递增,于是16代表主手武器,17代表副手武器
GetInventoryItemLink("player", 16) 就代表了主手武器的link

2,盗贼专用宏的编制思路,
其实用宏就是为了切换武器,既不放弃匕首的背刺和伏击,也能用高攻的单手剑,达成两全其美的效果。

一般有两种风格的切换宏,
1,主手剑副手匕首,用背刺,伏击时把匕首换到主手。用其他技能时把剑换到主手。
2,主手剑副手剑,背包里放一把匕首,用背刺,伏击时,把背包里的匕首换到主手。用其他技能时把剑换回来。

前一种方案的切换武器的宏如下:

PickupInventoryItem(16) PickupInventoryItem(17)

还记得吧,16代表主手武器,17代表副手武器。
PickupInventoryItem就是相当于打开人物装备面板(Inventory, 按C)
做点击数字对应位置的动作。这个宏很简单,
就是先点击主手武器,然后鼠标上应该有主手武器,然后点击副手武器,
这时候两把武器就会交换。瞬间执行的效果当然就是瞬间交换,但这个宏有能够感觉得到的明显延时,
因为PickupInventoryItem这个函数执行比较慢。推荐用下一个方案。

后一种方案的切换武器的宏如下:
PickupContainerItem(0, 1) PickupInventoryItem(16) PickupContainerItem(0, 1)

PickupContainerItem是从背包里取装备,第一个参数指背包,第2个参数指背包里的槽位,
这里的约定是0代表主背囊,然后从右向左,依次是1,2,3,4
背包里槽位从上到下,从左往右排序,注意!从1开始。这和一般从0开始的习惯有点不同。

因此PickupContainerItem(0, 1) 就是点取我主背包上数第一排左数第一格的物品。
然后PickupInventoryItem(16) 放到主手位置,
然后把原先主手位置的物品PickupContainerItem(0, 1)放到背包里。完成一次武器交换。

这个切换动作明显比前一个更快。推荐使用,而且副手因此可以保持用高DPS的剑,有助于提高攻击效率么,当然,你爱在副手保持什么武器都可以,呵呵。

现在我们有了一个基本的切换宏,但每次用技能都手工切换很难忍,我们继续实践很多人想到过的,
为特定技能写不同的宏,保证不同技能使用合适的武器。

基本思路是用全局变量记录主手使用的剑,在用不同技能时判断主手位武器是剑或否,看情况切换。

全局变量的设置宏:
/script setglobal("sword", GetInventoryItemLink("player", 16))
/script SendChatMessage("主手剑"..sword, "say", this.language,"")

第二句命令把你的主手武器说出来,让自己能够看见。如果碰巧是匕首在主手(例如上次断线不巧等等),就切换一次,重新运行设置宏。保证sword变量对应自己的主手剑。

先用邪恶攻击举例:我们要保证每次邪恶攻击都使用高攻击的剑,所以先判断主手武器,如果需要切换就切换,然后执行邪恶攻击。

/script if not (sword == GetInventoryItemLink("player", 16)) then PickupContainerItem(0, 1) PickupInventoryItem(16) PickupContainerItem(0, 1) end
/script CastSpellByName("邪恶攻击(等级 5)")

但类似写背刺的宏会有问题,背刺的有效性判断在宏执行之前,
这就使得流传的一些背刺宏需要连按两下,第一下只能完成切换,第二下才能背刺,这很是不方便。

因此,我的思路是在凿击之后直接切换武器,因为凿击通常接着就要背刺。这样背刺就可以直接进行了。而且背刺后应该换回剑继续,因为背刺的60能量开销使得它在绝大多数情况不能连续进行,除了某些升主动天赋的贼...

凿击宏如下:
/script CastSpellByName("凿击(等级 3)")
/script if ( sword == GetInventoryItemLink("player", 16) ) then PickupContainerItem(0, 1) PickupInventoryItem(16) PickupContainerItem(0, 1) end

背刺宏如下:
/script CastSpellByName("背刺(等级 5)");
/script PickupContainerItem(0, 1) PickupInventoryItem(16) PickupContainerItem(0, 1)

如果敌人已经晕了,而我在他背后,例如偷袭之后,
那么这个宏连按两下,也可以起到第一下切换,第二下背刺的效果。
通常偷袭后是连续邪恶攻击攒点还是背刺伤害 要视情况而定,所以偷袭的宏后面我没有加固定切换的
代码。

大体上就是这样,以上的宏解说希望对各位贼友有帮助,其他各个技能的宏如果觉得必要应该可以
自己写出来了,呵呵,自己写一写就会彻底掌握了。当然不能就此精通,
题目的言过其实,就是搞笑而已。呵呵

战士宏指南

一,冲锋,压制,拦截,断筋

/script C=CastSpellByName;
/script U=IsUsableAction;
/script R=IsActionInRange;
/script if(U(61)==1)then C("冲锋");elseif(R(61)==1)then C("拦截");elseif(U(63)==nil)then C("断筋");elseif(GetActionCooldown(63)==0)then C("压制");else C("断筋");end

前3行是定义语句,要不然写不下,另外也使宏更加好看和简练

首先判断冲锋是否可以用,如果能用则冲锋;

如果不能用,判断是否目标在拦截的范围以内,如果在范围内则拦截;

如果不在拦截的范围内,判断压制是否可以使用,如果不能使用则用断筋;

如果压制可以使用,判断压制的冷却是否为0,如果为0则压制,如果不为0则使用断筋。


效果就是,如果离敌人远就冲锋或者拦截,如果接近了就断筋,如果断筋被躲闪则立刻压制。

压制完了继续上断筋。断筋上好就该用下面的宏了。


二,致死,旋风,压制,英勇打击

/script C=CastSpellByName;
/script if(GetActionCooldown(63)==0) then C("压制");end
/script if(UnitHealth("target")<20) then C("斩杀");end
/施放 致死打击
/script if(IsActionInRange(63)==1)then C("旋风斩");end
/script if(UnitMana("Player")>39) then C("英勇打击");end



第一行为定义语句

第二行判断压制的CD是否为0,如果CD为0则压制,如果不能压制此行无效

第三行判断是否能处决,能则处决

第四行释放致死打击,(我为什么要用中文?用英文的话宏图标会一直是亮的,用中文明暗时间同致死打击)

第五行,判断敌人的距离,如果在5码内的话用旋风(利大弊大?自己衡量吧)

第六行,怒气大于39放英勇打击(这个自己可以随便定义)


效果,能压制压制,不能压制能处决就处决,都不能就放致死,致死CD中,敌人在攻击范围内就用旋风

怒非常多的时候就用英勇打击代替普通攻击。





三,破胆绷带

/施放 破胆怒吼
/script SpellStopCasting();
/target 安达里克
/script if(GetActionCooldown(69)>0) then UseContainerItem(3,1);end
/script TargetLastEnemy()

第一行,释放战士的技能

第二行,停止当前动作

第三行,选择绷带目标,名字改成你自己

第四行,判断破胆这个技能的CD是否大于0,用处就是看看你破胆是否释放成功,

经常我按技能的同时,对手跑出范围了,结果我在那傻傻的绷带,现在破胆不在CD中不会绷带了。

第五行,选择最后一个敌人


效果,目标被恐惧畏缩的同时你自己绷带,1秒都不浪费,恐惧结束刚好绷带完


四,群体攻击

/script G=GetActionCooldown;C=CastSpellByName;
/script F=CastShapeshiftForm;if(G(71)<2)then F(1);else F(3);end
/script if(IsUsableAction(71)==1)then C("横扫攻击");end
/施放 旋风斩
/施放 顺劈斩
/script if(UnitHealth("target")<5)then TargetNearestEnemy();end


自动判断横扫攻击的CD,当CD好了的时候如果不在战斗姿态则自动切换到战斗姿态放横扫攻击

然后再自动切换回狂暴姿态,放旋风和顺劈

最后一行判断目标的血量,如果少于5%,则切换下一个目标



五,双手武器和盾切换

/script P=PickupInventoryItem;
/script C=PickupContainerItem;
/script P(17);if(CursorHasItem())then C(4,2);C(4,1);P(16);else C(4,1);P(16);C(4,2);P(17);end

第1、2步骤:定义P为拾取人物目前装备函数的别名,定义C为拾取背包物品函数的别名,纯粹是为了节省字数
第3步骤:P(17),拿起目前装备的副手物品(如果是双手武器,副手没有,这样就没有拾取到物品,如果当前是单手+盾牌,这里就拾取了盾牌)
第4步骤:判断,if (CursorHasItem()) then,检查当前有没有拾取物品()
第4.1步骤:如果第4步判断是真,就是当前拾取了盾牌
第4.1.1步骤:C(4,2),,那么将盾牌放到背包2号位置中;
第4.1.2步骤:C(4,1),拿起背包1号位置的物品——双手武器;
第4.1.3步骤:P(16),将双手武器替换掉当前主手武器;
第4.2步骤:如果第4步判断为否,就是当前没拾取到物品,那么表明当前装备是双手武器
第4.2.1步骤:C(4,1),拾取背包第1位置的物品——单手武器;
第4.2.2步骤:P(16),将单手武器装备到主手位置;
第4.2.3步骤:C(4,2),拾取背包第2号位置的物品——盾牌;
第4.2.4步骤:P(17),将盾牌装备到副手位置;


六,使用饰物

/script UseInventoryItem(13)

用处,即使你换了饰物,仍然可以不换快捷键的使用,前提是你把这个语句做成宏


七,盾牌格档,复仇,破甲,英勇打击

/施放 盾牌格档
/script if((GetActionCooldown(64)==0) and (IsUsableAction(64)==1))then CastSpellByName("复仇");end
/施放 破甲攻击
/script if(UnitMana("Player")>44) then CastSpellByName("英勇打击");end

盾牌格档,能放复仇则复仇,放破甲,大于44怒放英勇打击


八,另外一个换武器的宏,这个连弓一块换,我是为了吃面包做的

/script P=PickupInventoryItem;C=PickupContainerItem;
/script P(17);if(CursorHasItem())then C(4,14);C(4,13);P(16);else C(4,13);P(16);C(4,14);P(17);end
/script UseContainerItem(4,15)

使用后同时换单手武器,盾,弓


九,自动给武器上鱼饵的,也可以上磨刀石,我钓鱼为了省事

/script UseContainerItem(2,1)
/script PickupInventoryItem(16)


十,切换防御姿态,缴械

/script CastShapeshiftForm(2)
/施放 缴械

如果不在防御姿态则切防御姿态,如果在则缴械

如果你是战斗或者狂暴姿态要缴械需要连续按2下


十一,守信史(呵呵)

/target 暮光预言者
/施放 冲锋(等级 3)
/施放 断筋(等级 3)


十二,从防御姿态切换到狂暴姿态释放狂暴之怒再切换回防御姿态


/script G=GetActionCooldown;
/script if(G(70)<2)then CastShapeshiftForm(3);end
/script if(IsUsableAction(70)==1)then CastSpellByName("狂暴之怒");end
/script if(G(70)>0)then CastShapeshiftForm(2);end


狂暴之怒放在第70号键位,就是左下额外技能拦的第10个。

效果:如果狂暴之怒不在CD中,则切狂暴姿态,释放狂暴之怒,如果狂暴之怒开始CD,则切回防御姿态

需要连续按很多次,不过只要鼠标狂点此傻瓜宏就可以了。比如MT黑龙看见地板震动,立刻狂点,就OK

注意:此技能不要放在数字拦那里,因为换姿态后技能就变了,托到别的地方用鼠标连续点。



十三,战斗怒吼宏,有就不管,没有就补上。我自己觉得不太好用。

/script local q; local t;for i=0,15,1 do t=GetPlayerBuffTexture(i); if (t and string.find(t, "BattleShout")) then q=1; break; end; end;if not (q ==1) then CastSpellByName("战斗怒吼") end;


十四 扔炸弹(很重要的)

/script if(IsCurrentAction(72)==nil)then UseAction(72);else SpellStopCasting();end


把炸弹放到左下第12个格子

第一下按是扔(必须要鼠标点地,本来想做个全自动的,但是命令,楼上的那个被封了,遗憾)

第二下按是取消扔炸弹,比按ESC容易多了。




十五 自动攻击的,如果按T,多按了就会取消攻击很讨厌,这个就不会取消了,哈


/script if(IsCurrentAction(50)==nil)then UseAction(50);end


把攻击放到右下中间第2个(或者从左数第14个)

如果没有攻击的话自动开始攻击

如果已经攻击则什么也不做。




补充几个重要技巧


1,战斗姿态,鼠标滚轮想上,狂暴姿态,向下滚

找到按键设置的CTRL+F1那里,这个是切换战斗姿态,把后面的第二快截键设置为鼠标滚轮向上

然后到CTRL+F2那里,这个切换狂暴姿态,把后面的第二快捷键设置为鼠标滚轮向下



2,R键,我现在改成扔雷


3,C键,使用饰品,联盟徽记等


4,大脚的技能拦可以拖出来几个,放到屏幕中间,放一些常用的技能
按键设置相关



左下的技能拦

1为冲锋,2为拦截,3为压制,4为复仇,5为嘲讽,6为英勇打击,7为致死打击,8为旋风斩,9为破胆

10 狂暴之怒,11为 横扫攻击(10和11是后来改的,图上没有改,你们自己改下拉)

把手雷放到左下第12个位置。就是从技能栏里拉出来的。

把攻击放到右下中间第2个(或者从左数第14个)





(4,1)为主手武器,(4,2)为盾

(4,13)为加精神的武器,(4,14)为加精神的盾,(4,15)为加精神的弓

(3,1)为绷带,(2,1)为鱼饵



按键编号,想自己换技能的位置的请注意

25-36 bar on right-side of screen, far right (top to bottom)右边
37-48 bar on right-side of screen, in one column (top to bottom)貌似是右2
49-60 lower right bar   (left to right)右下
61-72 lower left bar   (left to right)左下
73-84   battle stance bar (left to right)战斗姿态
85-96 defensive stance bar (left to right)防御姿态
97-108 berserker stance bar (left to right)狂暴姿态


背包编号,从左到右,4,3,2,1,0。 就是说,你一开始就有的16格行囊是0号背包

背包格子编号,第一行从左到右 1,2,3,4 (注意从1开始的) 第二行 从左到右 5,6,7,8

第三行从左到右 9,10,11,12 依次类推
宏命令解析




UseAction(slot)   调用某技能,可以是宏哦

CastSpellByName("技能名称")   施放一个技能,不打等级的话默认是放最高等级的

SpellStopCasting()   停止当前动作

if(条件判断语句) then   如果判断语句为真(非NIL)则执行then后面的语句

IsUsableAction(技能编号)   如果能使用则返回1,不能使用则返回nil

(判断一个技能是否在可以使用的状态,但是没有足够的怒气或MANA或精力,或者在CD中的时候

不包括在不能使用的范围)

IsActionInRange(技能编号)   如果目标在技能范围内则返回1

GetActionCooldown(技能编号)   返回技能的冷却剩余时间

UnitHealth("target")   返回目标的生命,百分比

UnitHealth("player")   返回自己的生命,数值

UnitMana("player")   返回自己的怒气

PickupInventoryItem(身上物品编号) 用鼠标左键点击身上的某个物品

PickupContainerItem(背包编号,格子编号) 用鼠标左键点击背包里的某个物品

UseInventoryItem(身上物品编号) 用鼠标右键点击身上某个物品

UseContainerItem(背包编号,格子编号)   用鼠标右键点击背包里的某个物品

CastShapeshiftForm(姿态编号)     切换姿态,战斗姿态1,防御姿态2,狂暴姿态3

UnitAffectingCombat("player")     判断自己是否处于战斗中,是则返回1
动作条相关函数

参数:slot——动作条快捷键的编号

GetActionCooldown(slot)——得到指定编号快捷键的冷却时间(如技能、物品)
GetActionCount(slot)——得到指定编号快捷键的数量(如绷带)
IsActionInRange(slot)——判断指定编号快捷键是否在范围内
IsAutoRepeatAction(slot)——判断指定编号快捷键是否是一个自动攻击技能(如魔杖射击)
IsCurrentAction(slot)——判断指定编号快捷键当前是否正在使用
IsUsableAction(slot)——判断指定编号快捷键当前是否可用

BUFF状态相关函数

CancelPlayerBuff(buffIndex) ——移除一个BUFF,参数buffIndex是BUFF的索引编号
GetPlayerBuff(buffId, buffFilter)——返回玩家的各种BUFF/DEBUFF的编号及状态信息
GetPlayerBuffTexture(buffIndex)——返回指定索引号BUFF的图标名称
UnitBuff("unit", index [, showCastable])——返回指定目标指定编号的BUFF信息
UnitDebuff("unit", index [, showDispellable]) ——返回指定目标指定编号的DEBUFF信息

信息相关

SendChatMessage(text,{,type} {,language} {,targetPlayer}) ——发送一段信息

参数:text——要发送的文字
   type——信息类型,

有"SAY", "YELL", "EMOTE", "PARTY", "AFK", "DND", "GUILD", "OFFICER", "WHISPER", "CHANNEL", "RAID"


背包、装备、物品相关

CursorHasItem——当前有没有拾取物品
UseContainerItem(bagId,slot)——使用指定背包指定位置的物品
PickupContainerItem(index,slot)——拿起、放置或替换指定背包指定位置的物品
UseInventoryItem(slotId)——使用当前装备指定位置的物品
PickupInventoryItem(slotId)——拿起、放置或替换人物当前某位置的装备


背包编号bagId解释

0-4:0是行囊,1是靠行囊的那个背包,2、3、4依次类推

人物身上装备位置slotId参数详解
0 = ammo(弹药)
1 = head(头部)
2 = neck(项链)
3 = shoulder(肩膀)
4 = shirt(衬衫)
5 = chest(胸部,这个...,不要理解错了)
6 = belt(腰带)
7 = legs(腿部)
8 = feet(鞋子)
9 = wrist(手腕)
10 = gloves(手套)
11 = finger 1(第一个戒指)
12 = finger 2(第二个戒指)
13 = trinket 1(第一个饰品)
14 = trinket 2(第二个饰品)
15 = back(披风)
16 = main hand(主手)
17 = off hand(副手)
18 = ranged(射击、圣物、魔杖)
19 = tabard(公会徽章)
20 = first bag (右边的第一个包)
21 = second bag(右边的第二个包)
22 = third bag(右边的第三个包)
23 = fourth bag (最左边的包)

如果你打开银行的话:
40 to 63 = the 24 bank slots(银行里的24个位置)
64 = first bank bag(银行的第一个包)
65 = second bank bag(银行的第二个包)
66 = third bank bag(银行的第三个包)
67 = fourth bank bag(银行的第四个包)
68 = fifth bank bag(银行的第五个包)
69 = sixth bank bag(银行的第六个包)

行动相关

FollowUnit("unit")——跟随指定目标
Jump()——跳

技能相关

CastSpellByName("name")——施放指定名称的技能
GetSpellCooldown(spellID, "bookType")——得到技能冷却时间(用起来没这么简单,可参考相关插件)
GetShapeshiftFormInfo(index)——得到某个形态/姿态的信息
  语句格式:icon, name, active, castable = GetShapeshiftFormInfo(index);
      icon——形态/姿态图标信息
      name——形态/姿态名称
      name——形态/姿态是否是当前形态/姿态
      castable——形态/姿态当前是否可以施放

CastShapeshiftForm(index)——进入某个形态/姿态
  
index 说明
    
    德鲁依
    1 = 熊
    2 = 水里的那啥来着
    3 = 猫?
    4 = 旅行形态
    5 = 月亮形态?汗,太不了解小德了
    盗贼
    1 = 潜行
    战士
    1 = 战斗姿态
    2 = 防御姿态
    3 = 狂暴姿态

目标相关

AssistByName("name")——协助某个玩家攻击
AssistUnit("unit")——协助某人某NPC某宠物攻击
AttackTarget()——攻击目标(慎用,状态判断不好用这玩意会取消自己的自动攻击)
TargetLastEnemy()——将最后一个敌人作为自己的目标
TargetLastTarget()——将最后的目标做为自己的目标
TargetNearestEnemy({reverse})——将距离最近的敌人作为目标,等同TAB键
TargetNearestFriend()——将最近的队友做为目标
TargetUnit("unit")——将指定名称的单位做为目标(比如对某人有仇,混战中只扁他一个)

单位相关

AssistUnit("unit")
FollowUnit("unit")
InviteToParty("unit") ——邀请某人加入队伍(某些人刷副本的人都用这函数邀请小号等)
TargetUnit("unit")
UnitAffectingCombat("unit") ——某单位是否正在战斗状态
UnitHealth("unit")——某单位的生命值(无法得知具体生命值的单位返回为百分比)
UnitMana("unit")——某单位的魔法值/怒气值/能量值
UnitSex("unit")——某单位的性别(这条貌似没啥用,RY太多了,=.=)

关于unit参数的说明:

"player"——玩家自己
"pet"——宠物
"party1"——队伍成员1
"party4"——队伍成员4(没5哈,除你之外只有4)
"partypetN"——队伍成员的宠物(N=1,2,3,4)
"raidN"——团队成员(N=1,2,3,4....)
"raidpetN"——团队成员的宠物(N=1,2,3,4...)
"target"——你的当前目标
"mouseover"——你鼠标经过的那个家伙
"npc" or "NPC"——NPC

另外,还需要注意一点,在unit参数中允许层叠使用target,比如AssistUnit("playertargettarget")就是协助玩家目标的目标,当然你也可以这样AssistUnit("playertargettargettargettargettargettarget"),只要你弄得清,^皿^