|
|
本帖最后由 雨落霜枫 于 2026-11-11 20:39 编辑
用AutoHotkey 写的一个宏,我完善了大部分功能,但是还是有诸多缺陷,搞了一个月,实在是撅不动这个代码了,放弃我又不甘心,所以到论坛请大佬帮忙完善一下。这个是配合CustomKeys改键文本使用。缺陷:无法使用shift键+A键来A单位,点击英雄和建筑生成单位的时候,英雄会放出快速施法的技能后变成双击鼠标悬浮单位,建筑是生产一个单位的同时变成双击该建筑的失焦。或许还有其他缺陷,我没测试出来。
代码如下:
#SingleInstance Force
#NoEnv
#InstallKeybdHook
SendMode Event
SetBatchLines -1
SetKeyDelay, 0, 30 ; PressDuration 30ms,提高 DX8 游戏对修饰键的识别率
CoordMode, Mouse, Screen
; ========== 可调整参数 ==========
CAST_DELAY := 40 ; 英雄技能/物品 快速施法延迟
REPEAT_DELAY := 60 ; 建筑/农民长按重复间隔(ms)
BUFFER_DELAY := 15 ; Alt 组合键发送后的额外缓冲
LEVELUP_DELAY := 100 ; F键升级确认延迟
CHECK_INTERVAL := 2000 ; 游戏进程检测间隔
; ========== 按键列表 ==========
ALL_KEYS := ["q","w","e","r","a","s","d","f","z","x","c","v"]
gameRunning := false
SetTimer, CheckWarcraft, %CHECK_INTERVAL%
; ========== 仅魔兽窗口激活时注册热键 ==========
#IfWinActive ahk_exe War3.exe
for _, k in ALL_KEYS
{
; F键单独绑定包含“学习”确认的逻辑
if (k = "f")
Hotkey, % "$" k, DoQuickCastF, On
else
Hotkey, % "$" k, DoQuickCast, On
; 所有键均注册 Alt 组合键用于建筑/农民
Hotkey, % "$!" k, DoQuickTrain, On
}
#IfWinActive
; ========== 第一套逻辑:英雄/物品快速施法(普通键)==========
DoQuickCast:
key := SubStr(A_ThisHotkey, 2)
Send {%key%}
Sleep %CAST_DELAY%
Click
While GetKeyState(key, "P")
{
Sleep %REPEAT_DELAY%
Send {%key%}
Sleep %CAST_DELAY%
Click
}
return
; ========== F键专属逻辑:英雄升级确认 + 快速施法 ==========
DoQuickCastF:
Send {f}
Sleep %LEVELUP_DELAY%
MouseGetPos, , , , ctrl
ControlGetText, txt, , ahk_id %ctrl%
if InStr(txt, "学习")
Click
else
Click
While GetKeyState("f", "P")
{
Sleep %REPEAT_DELAY%
Send {f}
Sleep %CAST_DELAY%
Click
}
return
; ========== 第二套逻辑:建筑/农民快速训练(Alt组合键,防鼠标中断)==========
DoQuickTrain:
key := SubStr(A_ThisHotkey, 3)
; 首次触发
Send {Alt Down}
Send {%key%}
Send {Alt Up}
Sleep %BUFFER_DELAY%
; 长按循环:每次发送前显式释放 Alt,防止鼠标移动触发菜单关闭
While GetKeyState(key, "P")
{
Sleep %REPEAT_DELAY%
Send {Alt Up}
Send {Alt Down}
Send {%key%}
Send {Alt Up}
Sleep %BUFFER_DELAY%
}
return
; ========== 工具函数与进程检测 ==========
ProcessExist(name)
{
Process, Exist, %name%
return ErrorLevel != 0
}
CheckWarcraft:
running := ProcessExist("War3.exe")
if (running && !gameRunning)
gameRunning := true
else if (!running && gameRunning)
gameRunning := false
return
|
|