HOOZi文档
Skip to content

event

事件订阅。脚本卸载时订阅自动撤销,无需手写 event.off


event.on(name, fn) → handle

参数

  • name : string — 事件名,下表之一
  • fn : function — 回调

事件名 + 回调签名

事件名回调签名字段
"frame_update"fn(e)e.delta_time : number — z-order 在 ESP 之下
"render_post"fn(e)e.delta_time : number — z-order 在 ESP / FOV / menu 之上
"config_changed"fn(e)e.module_name : string — 配置 modify 时触发
"script_loaded"fn(e)e.script_path : string, e.is_reload : bool
"script_unloaded"fn(e)e.script_path : string
"menu_toggled"fn(e)e.visible : bool — MenuOpen 热键切换边沿触发
"weapon_changed"fn(e)e.prev_weapon : int, e.curr_weapon : int — local 手持武器边沿变化 (sdk::ItemId)
"map_changed"fn(e)e.prev_map : string, e.curr_map : string — 地图切换 (level_name 边沿)
"player_knocked"fn(e)倒地 (is_down false→true)。共用 player 生命周期字段 (见下)
"player_revived"fn(e)扶起复活 (is_down true→false 且未死亡)
"player_died"fn(e)死亡 (is_dead false→true)
"player_respawned"fn(e)重生 (is_dead true→false)

所有事件共用基类字段e.timestamp : int(毫秒 unix ts,懒计算), e.source : string

player 生命周期事件共用字段 (e.player_index : int, e.name : string, e.team_num : int, e.is_local : bool, e.is_teammate : bool)。

拆 4 个 player 事件名(不是单一 state 字段)的原因:

  • handler 不必写 if state == "knocked" 分支
  • 只关心某一类型时只订一个,不接其它事件,EventBus 按 type_index 分发零浪费

每帧渲染线程扫所有玩家对比上帧状态,边沿变化才 publish — 不会每帧 spam。首次见到的玩家不发事件(避免初始化时全员误报)。weapon_changed / map_changed 同款边沿语义。

frame_update vs render_post z-orderframe_update 写入的 vtx 落在 ESP / FOV / menu 之前;render_post 写入的 vtx 落在它们之后。两者都用屏幕相对坐标(系统统一做 viewport offset 修正)。HUD 类 mod 用 render_post 浮于 ESP 之上;底层信息显示用 frame_update

每渲染帧触发(绑定屏幕渲染节奏,144Hz / 240Hz 时也是 144/240 次每秒)。draw.* 必须挂在 frame_updaterender_post 每帧 call —— 前景 draw list 每帧重置,漏一帧就是空白闪烁。

重活(数据计算、网络等)由脚本自己累计 e.delta_time 节流,见 入门指南

返回handle : number —— 用于 event.off


event.off(handle)

显式取消订阅(一般无需手动)。


自定义事件 — 脚本间通信

除上述内置事件外,任何其他事件名都进 Lua 自定义事件通道。

event.on(name, fn) → handle

任何不在内置事件名清单的 name 自动走自定义通道。fn 签名是 function(...) —— 收到 event.emit(name, ...) 透传的全部参数。

event.emit(name, ...)

触发自定义事件,同步派发到该 name 下所有 handler。不允许 emit 到内置事件名(防止脚本伪造系统事件),尝试 emit "frame_update" 等会被拒绝。

handler 异常被捕获不会中断后续派发。脚本卸载时该脚本注册的所有自定义事件订阅自动撤销。

lua
-- 脚本 A:监听
event.on("hp_changed", function(player_name, new_hp, old_hp)
    print(player_name, "blood:", old_hp, "→", new_hp)
end)

-- 脚本 B:广播
event.emit("hp_changed", "alice", 30, 100)

示例

lua
event.on("frame_update", function(e)
    -- 每渲染帧调,dt 与 time.delta() 等价
    do_something(e.delta_time)
end)

event.on("script_unloaded", function(ue)
    if ue.script_path ~= _SCRIPT_PATH then return end
    -- 只对自己被卸载做处理(极少数场景:缓冲区 flush)
end)

-- 菜单显隐:toast 跟随显示
event.on("menu_toggled", function(e)
    if e.visible then gui.notify:info("menu opened") end
end)

-- 玩家生命周期:队友倒地告警
event.on("player_knocked", function(e)
    if e.is_teammate then gui.notify:warn(e.name .. " 倒地了!", 3) end
end)

event.on("player_died", function(e)
    if e.is_local then gui.notify:error("你死了", 2) end
end)

-- HUD 浮于 ESP 之上:用 render_post 而不是 frame_update
event.on("render_post", function(e)
    draw.text(draw.font("default"), 24, 100, 100, 0xFFFFFFFF, "On top of ESP")
end)

-- 武器切换时刷一次:换枪自动切配置/重置弹道学
event.on("weapon_changed", function(e)
    print(string.format("weapon: %d → %d", e.prev_weapon, e.curr_weapon))
end)

-- 地图切换时重置本局统计
event.on("map_changed", function(e)
    print("map:", e.prev_map, "→", e.curr_map)
    -- reset local round stats
end)