HOOZi文档
Skip to content

input ​

输入查询 + keybind formatter + 剪贴板 + 硬件设备输出。


input.is_active(path) → bool ​

参数:path : string —— 控件 full_path(hotkey 控件)

返回该 hotkey 当前是否处于 active 状态(按 mode 不同:Toggle = 已切到 on / Hold = 正按住 / Always = 永远 true)。


input.format(path, fn) ​

给 keybind 控件挂动态文字 + 颜色提示,formatter 只在该 hotkey 处于 active 状态(出现在 "active keybinds" 浮窗中)时调用。

参数:

  • path : string —— 菜单元素 full_path 或 Pattern B hotkey ID(两种都接受)
  • fn : function(id : string) → string | { text = string, color = {r,g,b,a} }

path 自动解析 ​

传 menu element full_path(自然语义)即可 —— 如果该元素是 KeybindControl 且内部把 keybind 重映射到稳定 ID,会自动跟随到那个稳定 ID。

调用形式解析过程
input.format("settings.display.menu", fn)→ 解析到 hotkey.menu_open
input.format("hotkey.menu_open", fn)→ 直接用
input.format("KbHints.g.alarm", fn)→ 用户自建 KeybindControl 无重映射,用 full_path

fn 返回类型 ​

返回行为
string用主题色显示该文本
table {text, color={r,g,b,a}}自定义文本 + 颜色
其他LOG_ERR + 走默认显示

Owner-scoped:脚本卸载时自动 unregister。


input.unformat(path) ​

path 解析逻辑与 input.format 相同。


input.clipboard_get() → string ​

读系统剪贴板。空时返空 string。

input.clipboard_set(text) ​

写系统剪贴板。

lua
local key = input.clipboard_get()
if key ~= "" then gui.notify:info("已读取: " .. key) end

input.clipboard_set("hello")

不提供 input.is_down(vk) —— 双机架构下 OS 按键 API 读的是程序所在机器而非游戏玩家。查玩家按键走 game.localplayer.* 字段(如 is_zooming、is_grenade)。详见 入门指南。


formatter 示例 ​

lua
-- formatter #1:纯 string
input.format("KbHints.g.alarm", function(id)
    return alarm_armed and "ARMED" or "OFF"
end)

-- formatter #2:返 {text, color} table
input.format("KbHints.g.stopwatch", function(id)
    local sec = os.clock() - start_t
    return {
        text  = string.format("%.1fs", sec),
        color = { 0.55, 0.85, 1.0, 1.0 },
    }
end)

-- formatter #3:按阈值动态变色
input.format("KbHints.g.counter", function(id)
    local label = string.format("× %d", counter)
    if counter == 0     then return { text = label, color = { 0.6, 0.6, 0.6, 1.0 } } end
    if counter < 10     then return { text = label, color = { 0.3, 1.0, 0.3, 1.0 } } end
    return { text = label, color = { 1.0, 0.45, 0.25, 1.0 } }
end)

硬件设备输出 ​

经外接输入设备(KMBOX Net / KMBOX B+ / MAKCU)向游戏机发送真实的鼠标键盘输入。

没连设备时全部 no-op 返回 false —— 不会报错,也不会走别的路径。写脚本前先用 input.device_connected() 判一下。

只有相对移动

input.move 是相对位移,没有 input.move_to(x, y)。

MAKCU 固件确实有一条 moveto(x, y)(KMBOX Net / B+ 都没有),但按官方 API 的说法它是"内部算出到达目标位置所需的 x/y 位移"再发出去 —— 底层仍是相对报文,需要一个可信的"当前光标位置"当参照。

在 FPS 里那个参照不存在:游戏走 raw input 吃 delta、把系统光标锁在窗口中心,屏幕坐标跟游戏内视角没有对应关系;加上双机架构下本程序也读不到游戏机的光标位置。所以 moveto 对瞄准没有意义,facade 没有接。

要"瞄向某个世界坐标"用 game.aimbot.set_predictor,让瞄准管线读 view_angle 反解出需要的 delta。


input.backend() → string ​

当前输入设备后端名。脚本据此做能力分支(各后端支持的动作不同,见下表)。

返回值含义
"disable"未选择设备
"write_view"内存接管(不经硬件,本节的函数全部无效)
"kmboxnet"KMBOX Net(网口)
"kmboxb+"KMBOX B+(串口)
"makcu"MAKCU(串口)

input.device_connected() → bool ​

设备是否已连接可用。

后端能力对照 ​

动作kmboxnetkmboxb+makcu
move / click / button(左键)✅✅✅
button 右键 / 中键 / 侧键✅⚠️✅
wheel✅⚠️✅
move_curve(固件侧插值)✅↩︎ 退化成 move✅
key_down / key_up / key_press✅✅❌
mask 鼠标左键✅✅✅
mask 其它鼠标键 / "x" / "y"✅❌✅
mask "wheel"✅❌❌
mask 键盘键✅❌❌
  • ⚠️ = KMBOX B+ 的这几条命令名是按已实证命令的规律外推的,未实机验证。固件不认时串口写入照样成功,所以返回 true 也可能实际没动作。
  • ❌ = 后端没有该能力,返回 false。别把 false 一律当成"设备没连" —— 先看这张表。
  • MAKCU 固件没有键盘 HID 通道,键盘三件套在它上面恒 false。

input.move(dx, dy) → bool ​

参数:dx : int, dy : int —— 相对位移(mickey 单位,正 = 右 / 下)

input.move_curve(dx, dy, ms?) → bool ​

参数:dx : int, dy : int, ms : int(可选,默认 20,上限 2000)

把一次大位移交给固件分段推送,轨迹比逐帧小步 move 更接近人手。

阻塞式推送

固件侧在整个 ms 期间占住设备,排在后面的瞄准 move 全被拖住。别放进每帧循环。

input.button(name, down) → bool ​

参数:name : string,down : bool

name别名
"left""lmb"
"right""rmb"
"middle""mmb" / "wheel_click"
"side1""mouse4" / "x1"
"side2""mouse5" / "x2"

input.click(name?) → bool ​

按下 + 松开一次。name 省略 = 左键。

input.wheel(delta) → bool ​

参数:delta : int —— 格数(正 = 前滚)


input.key_down(key) / input.key_up(key) / input.key_press(key) → bool ​

参数:key : string —— 单字符("r")或键名("shift" / "enter" / "f1" / "space" / "lctrl" / 方向键 "up" 等)

key_press = 按下 + 松开一次。

MAKCU 后端无键盘通道,这三个恒 false。


input.mask(what, enable) → bool ​

屏蔽玩家的物理输入,让它不再传给游戏。用于"接管某个键"的场景 —— 盒子拦掉玩家自己的按键,再由脚本决定什么时候真发出去。

参数:

  • what : string —— 鼠标键名(同 input.button)/ "x" / "y" / "wheel" / 键盘键名
  • enable : bool

键盘屏蔽的前提

只有物理键盘插在盒子上时键盘 mask 才真生效。键盘直连游戏机的话盒子拦不到,函数返回 true 也没有实际效果。

脚本卸载时所有 mask 自动解除,见下方「自动清理」。


自动清理 ​

设备输出里有状态的操作按脚本 owner 记账,脚本卸载(热重载 / 切配置 / 手动卸载)时自动还原:

操作卸载时
input.button(name, true) 按下未松自动松开
input.key_down(key) 按下未松自动松开
input.mask(what, true)自动解除

没有这层的话,脚本在按住左键时被卸载,按键会永久卡在盒子固件里 —— 游戏里表现为一直开火,且用户自己点鼠标也停不下来。

click / move / wheel / key_press 是瞬时操作,不需要清理。


与扳机的配合 ​

扳机靠"本机是否在开火"判断要不要让位,而脚本经盒子点的左键同样会让它以为玩家在手动开火。input.click("left") 和 input.button("left", false) 会自动通知扳机这一发是脚本点的,不需要脚本自己处理。

脚本持按左键期间扳机会让位不扣发 —— 这是正确行为:已经在持续开火了,扳机再点没有意义。


设备输出示例 ​

lua
-- 能力分支:不同后端能做的事不一样
local backend = input.backend()
if not input.device_connected() then
    gui.notify:warn("未连接输入设备")
    return
end

-- 缓慢画一个方块(固件侧插值,比逐帧 move 自然)
for _, d in ipairs({ {200,0}, {0,200}, {-200,0}, {0,-200} }) do
    input.move_curve(d[1], d[2], 150)
end

-- 侧键点射:按下 → 60ms → 松开
input.button("side1", true)
Delay(0.06, function() input.button("side1", false) end)

-- 接管 R 键:拦掉玩家的物理 R,自己决定何时真按
-- (仅 kmboxnet + 键盘插在盒子上时有效)
if backend == "kmboxnet" then
    input.mask("r", true)
    event.on("frame_update", function()
        if should_reload_now() then
            input.mask("r", false)
            input.key_press("r")
            input.mask("r", true)
        end
    end)
end