AHK 按键宏教程

一个非常提高效率的工具,一个按键就能映射到一大串很长很长的宏,懒人必备。

接下来以游戏永劫无间的按键宏为例,介绍一下如何制作一套按键宏脚本。

此处代码仅供研究与学习使用,禁止商用。

进程判断

使用 #IfWinActive 来判断当前的进程

1
#IfWinActive, ahk_exe NarakaBladepoint.exe

这样当前台应用不是 NarakaBladepoint.exe 时当前脚本就不会生效。

怎么知道是哪个类名/应用/进程?安装 AHK 后开始菜单中输入 Window Spy 就知道了。

全局变量

定义变量需要使用 var := val 这样的格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a := 1
global b := 2
c := 3

func() ; 调用函数 func

func()
{
; a 不是全局变量,访问不了,弹出空字符串
MsgBox, % a

; b 是全局变量,弹出 2
MsgBox, % b

; 在函数里也可以将 c 变成全局变量
global c
; 弹出 3
MsgBox, % c
}

如果不使用 :=,则右边会视作字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
MyVar1 = 123
MyVar2 = my string

if MyVar2 = my string ; 与字符串比较
{
MsgBox MyVar2 contains the string "my string".
}
if MyVar1 > 100 ; 与数值比较
{
MsgBox MyVar1 contains %MyVar1%, greater than 100.
}

MyVarConcatenated = %MyVar1% %MyVar2% ; 123 my string

MsgBox 语句和最后一句赋值语句中 MyVar1 被两个百分号包围着,此处会显示 MyVar1 变量的值。

条件判断

如上面的示例,使用 if 关键字,右边的小括号表示包含一个表达式;

如果缺少括号,后面的内容则当做“非表达式 if 语句”,限定一个比较运算符(即不能包含AND、OR等),且需要百分号将变量包起

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if (addBaiLieZhan)	; 如果结束后释放百裂斩
{
if (addXiaPi) ; 如果先下劈再等待下劈后摇
{
if (shunBu) ; 瞬步升龙,同时间高度低,等待时间少
{
sleep, 550
}
else ; 滑步升龙,高度高,要等久一点
{
sleep, 600
}
}
else ; 不下劈,直接百裂斩
{
if (shunBu) ; 瞬步升龙
{
sleep, shengLongWait ; 等待升龙动作
}
}
; 接百裂斩
sleep, 900 ; 等升龙/百裂斩落地
send {RButton down} ; 开始蓄力
sleep, 900 ; 蓄力时间
send {RButton up} ; 蓄力释放
}

循环

Loop x 语句,x可以是一个常数,或者变量

例如循环颠勺,totalCount 是函数传进来的参数:

1
2
3
4
5
6
count := 0
Loop, %totalCount%
{
count++
; 执行单次颠勺命令
}

函数

函数中的内容不会主动执行,需要手动调用

1
2
3
4
funcName()
{
; 函数体
}

例如抽帧振函数:

1
2
3
4
5
6
7
chouZhenZheng()
{
send {XButton2 down}
send {Space}
send {XButton2 up}
return
}

可以带有参数:

1
2
3
dianShao(shunBu, totalCount, addXiaPi, addBaiLieZhan)
{
}

功能总开关

首先需要定义一个全局变量:

1
global Enabled := true

F9:: 表示当按下 F9 这个按键时,后面的脚本生效;

接下来使用 if else 来切换开关,并弹出提示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
F9::
{
if (!Enabled)
{
Enabled := true
ToolTip, Enabled AHK ; 开启提示(不会自动隐藏)
}
else
{
Enabled := false
ToolTip, Disable AHK
}

SetTimer, RemoveToolTip, 1000 ; 跳转到定时隐藏提示的Label

return
}

Tooltip

弹出的提示并不会自动移除,所以在外面还需要添加一个定时移除的label,并在显示提示后调用:

1
2
3
4
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return

模拟按键

调用 send text,直接发送字符串,如以下代码会模拟按下字符串按键 “Hello”(H=shift+h):

1
send Hello

特殊按键,需要使用 {} 的形式,如左Shift键:

1
send {LShift}

可以指定按下/释放:

1
2
3
send {LShift down}	; 按下shift
sleep, 100 ; 等待按下100ms
send {LShift up} ; 松开shift

一些按键可以简写:

  • win} -> #

  • ctrl -> ^

  • alt -> !

1
Send ^c!{tab}pasted:^v

按键序列还可以用于定义字符串的缩写,即热字符串 。例如,下例将 btw 定义为 by the way 的缩写,无论何时你输入 btw 后再输入空格或逗号,都会被替换成 “by the way”:

1
::btw::by the way

鼠标点击

1
click 123,456

激活窗口

例如激活默认标题的记事本

1
2
3
4
5
6
7
8
9
10
IfWinExist Untitled - Notepad	; 如果存在,则激活
{
WinActivate
}
else ; 不存在,打开后再激活
{
Run Notepad
WinWait Untitled - Notepad
WinActivate
}

一些常用的窗口管理命令:

  • IfWinActive :检查指定的窗口是否处于激活状态。
  • WinWaitActive :等待指定的窗口处于激活状态(通常在发送窗口激活指令——比如按下 Control-F 来弹出查找窗口——后使用)。
  • WinClose :关闭指定的窗口。
  • WinMove :移动或/且调整窗口大写。
  • WinMinimizeWinMaximizeWinRestore :分别是最小化、最大化和恢复指定的窗口。

启动程序

1
2
3
4
5
Run Notepad
Run C:/My Documents/Address List.doc
Run C:/My Documents/My Shortcut.lnk
Run www.yahoo.com
Run mailto:someone@somedomain.com
1
2
#n::Run Notepad
^!c::Run calc.exe

脚本功能

  1. 抽帧振(X1)
    • 秒放振刀,实现红光还没出来就振刀
    • 攻击后按这个按键还会攻击,需要蹲跳闪配合
  2. 切拳头(X1)
    • 可用于平A两下后快速切拳头蓄力攻击,对手振刀/蓄力都会被打
    • 结合快速切武器达到出其不意的效果,对手看你拳头想打蓄力,切回来振刀
  3. 快速切枪(枪斗术)(G)
    • 快速切枪、切武器,一直按住鼠标左键切换后自动攻击/蓄力
    • 如果连续两下切太快(未处于后摇)会导致第二下变成移动
    • 如果是弓箭、无眼铳等可蓄力武器,按住左键切换后瞬间松开左键可立刻攻击
    • 切到近战武器时可立刻蓄转振,速度很快,可达到无红光振刀
  4. 鸟铳快射(N)
    • 以非常快的速度连射 3/4 下
    • 需要保证至少能闪避 2/3 次,否则后面会做卡顿动作
    • 支持鸟铳、弓箭、五眼铳
    • 参数一:射击3次(false)还是4次(true)
  5. 火男一键颠勺(J)
    • 火男开大后一键颠勺(需要 冲拳+平A 打出敌人僵直再使用)
    • 建议满精力天赋,否则可能精力不够
    • 参数一:滑步升龙(false)还是瞬步升龙(true)。瞬步最多4下,滑步最多12下
    • 参数二:颠勺次数,一般为3/4/6/9/12。3很稳,6大概率,第七下很可能落地
    • 参数三:结束后是否下劈。下劈大概率打不中除非刚颠起来,不建议用
    • 参数四:结束落地是否接右蓄百裂斩
  6. 火男无限平A
    • TODO

总代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#IfWinActive, ahk_exe NarakaBladepoint.exe

global Enabled := true
global stopAction := false

; 功能总开关
F9::
{
if (!Enabled)
{
Enabled := true
ToolTip, Enabled AHK
}
else
{
Enabled := false
ToolTip, Disable AHK
}

SetTimer, RemoveToolTip, 1000

return
}
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return


; 鼠标前面的侧键X1:抽帧振/切拳头 自选
XButton1::
{
if (!Enabled)
{
return
}

; 切拳头
; 可用于平A两下后快速切拳头蓄力攻击
; 结合快速切武器来出其不意
;send 0

chouZhenZheng() ; 抽帧振
return
}

; 按下Shift时鼠标前面的侧键(特化)
LCtrl & LShift & XButton1::
{
if (!Enabled)
{
return
}

;send 0 ; 切拳头
chouZhenZheng() ; 抽帧振(似乎作用不大)
return
}

; 切枪攻击
G::
{
if (!Enabled)
{
send g
return
}

qiangDouShu()
return
}

; 鸟铳快射(三下)
N::
{
if (!Enabled)
{
send n
return
}

niaoChongKuaiShe(false)
return
}

; 一键颠勺
; 按J开始,再次按J关闭
J::
{
if (!Enabled)
{
send j
return
}

dianShao(false, 6, false, false)
return
}

; 取消一键颠勺
; 需要颠勺中疯狂按才有效
K::
{
if (!Enabled)
{
send k
return
}

dianShaoIng := false
return
}


;==============================================================

; 抽帧振0(有些人吹得很厉害,但实测没啥用)
; 但是有时候会莫名变成闪避翻滚后再振刀
chouZhenZheng0()
{
send {Space}
sleep, 5
send {D}
send {XButton2 down}
send {LButton down}
send {RButton down}
sleep, 100
send {LButton up}
send {XButton2 up}
send {RButton up}
return
}

; 抽帧振
; 先按快捷振刀,再按空格
chouZhenZheng()
{
send {XButton2 down}
send {Space}
send {XButton2 up}
send {space up}
return
}

; 快速切枪、切武器,一直按住鼠标左键自动攻击/蓄力
; 如果连续两下切太快(不处于后摇)会导致第二下变成移动
; 可配合方向键微调方向,但几乎没作用
; 如果是弓箭、无眼铳等可蓄力武器,按住左键切换后瞬间松开可立刻攻击
; 切到近战武器时可立刻蓄转振
qiangDouShu()
{
; 切另一个武器
send {Shift down} ; 短闪
MouseClick,WheelDown,,,20,0,D,R ; 滚轮切换武器,打断短闪(有时候不需要精力)
send {Shift up} ; 短闪结束
MouseClick,WheelDown,,,10,0,D,R ; 得留着,不然有时候会只闪避不切刀

;sleep, 200 ; 等待射击后摇

; 切回来(有问题)
;send {Shift down}
;MouseClick,WheelDown,,,10,0,D,R
;send {Shift up}
;MouseClick,WheelDown,,,10,0,D,R

return
}

; 鸟铳快射,连续射3/4下
; 需要保证至少能闪避2/3次,否则后面会做卡顿动作
; 支持鸟铳、弓箭、无眼铳
niaoChongKuaiShe(enable4)
{
pressWait := 20 ; 鼠标按下时间
shotWait := 160 ; 射击后无法操作时间(150),由于系统延时需要适当调高
shiftWait := 400 ; 长闪后无法操作时间(400)

; 射第一下
send {LButton down}
sleep, pressWait
send {LButton up}

sleep, shotWait ; 等待射击结束
send {Shift down} ; 长闪取消后摇
sleep, shiftWait ; 等待长闪动作

; 射第二下
send {LButton down}
sleep, pressWait
send {Shift up}
send {LButton up}

sleep, shotWait
send {Shift down}
sleep, shiftWait

; 射第三下
if (enable4)
{
send {LButton down}
sleep, pressWait
send {Shift up}
send {LButton up}

sleep, shotWait
send {Shift down}
sleep, shiftWait
}

; 射第四下
send {LButton down}
sleep, pressWait
send {Shift up}
send {LButton up}

return
}

; 火男开大颠勺,中途再调用则停止
; 需要确保满精力天赋
; 参数一:滑步升龙(false)还是瞬步升龙(true)。瞬步最多4下,滑步最多12下
; 参数二:颠勺次数,一般为3/4/6/9/12。3很稳,6大概率,第七下很可能落地
; 参数三:结束后是否下劈。下劈大概率打不中除非刚颠起来,不建议用
; 参数四:结束落地是否接右蓄百裂斩
global dianShaoIng := false
dianShao(shunBu, totalCount, addXiaPi, addBaiLieZhan)
{
if (dianShaoIng)
{
dianShaoIng := false
return
}
dianShaoIng := true

pressWait := 30 ; 鼠标按下时间

; 开始第一下(攻击或者跑步中)
count := 0

Loop, %totalCount%
{
count++


if (count == 1)
{
; 第一下开始
}
if (shunBu)
{
sleep, 450 ; 等待上一次原地升龙动作,瞬步要快
}
else if (shunBu || count == 2 || count == 5 || count == 8 || count == 11)
{
; 滑步升龙的原地升龙后
sleep, 500 ; 等待上一次原地升龙动作
}
else if ((count == 4 && totalCount != 4) || count == 7 || count == 10)
{
sleep, 1000 ; 准备原地升龙,等待上一次升龙落地
}
else
{
sleep, 300 ; 等待上一次滑铲升龙,动作比原地升龙更快
}

if (shunBu) ; 瞬步升龙
{
if (count != 1)
{
send {a down}
send {LShift down} ; 移动打断升龙
sleep, 50
send {a up}
send {LShift up}
}
sleep, 150 ; 等待左移落地

send {c down} ; 下蹲
sleep pressWait ; 等待下蹲动作

send {RButton down} ; 升龙
sleep, pressWait
send {RButton up}
send {c up}
}
else if (shunBu || count == 1 || (count == 4 && totalCount != 4) || count == 7 || count == 10)
{
; 瞬步升龙 / 滑步升龙中的原地升龙
send {c down}
sleep, 20 ; 等待下蹲
send {RButton down} ; 升龙
sleep, pressWait
send {RButton up}
send {c up}
}
else
{
; 滑步升龙
send {a down}
send {LShift down} ; 移动打断升龙
sleep, 250 ; 等待左移落地
send {c down} ; 滑铲
sleep 100 ; 滑铲一段时间

send {RButton down} ; 滑铲升龙
sleep, pressWait
send {RButton up}
send {a up}
send {LShift up}
send {c up}
}
ToolTip, attack: %count%

if (!dianShaoIng)
{
break
}
}

SetTimer, RemoveToolTip, 1000
if (!dianShaoIng)
{
return
}
dianShaoIng := false

shengLongWait := 280 ; 等升龙起来的时间
if (shunBu)
{
shengLongWait := 450 ; 瞬步升龙需要再等等
}

if (addXiaPi)
{
; 接下劈
sleep, shengLongWait ; 等升龙起来
;send {RButton}
send {RButton down}
sleep, pressWait
send {RButton up}
}

if (addBaiLieZhan)
{
; 等待下劈后摇
if (addXiaPi)
{
if (shunBu)
{
sleep, 550
}
else
{
sleep, 600
}
}
else
{
if (shunBu)
{
sleep, shengLongWait
}
}

; 接百裂斩
sleep, 900 ; 等升龙/百裂斩落地
send {RButton down} ; 下劈
sleep, 900
send {RButton up}
}

return
}