HOOZi文档
Skip to content

game

实时数据(read-only,写入抛 lua error)。访问字段 = 当前帧最新发布的快照。


game.localplayer

字段类型说明
indexintentity_list 索引
base / self_baseuint64实体内存基址,配 offsets + mem.read/write 自助读写任意属性。死亡观战时二者分叉:base 跟随被观战者,self_base 永远真实本机——读"我自己"的属性用 self_base
health / max_healthint当前 / 最大血量
shield / max_shieldint当前 / 最大护盾
origin / camera_originVec3实体 / 相机位置(死亡观战时 origin 跟随被观战者)
view_angleVec2{pitch, yaw}
sway_angleVec2含呼吸/sway 的子弹发射方向
view_offset / punch_angleVec3视图偏移 / 后坐力
abs_velocityVec3
flags_rawuint32m_fFlags 原始位(FL_ONGROUND 等)
team_num / squad_idint
platform_uidstringuint64 转 string
weapon_idint武器 string-table 索引
weapon_enumintsdk::ItemId 数值,比 weapon 字符串更可靠
weaponstringESP 显示用武器名
weapon_speed / weapon_scalenumber射速 / 蓄力进度
target_zoom_fovnumber武器开镜 fov
weapon_next_ready_timenumber
weap_state / burst_fire_index / ammo_in_clipint内部弹药状态
is_semi_auto / is_zooming / is_dead / is_down / is_skydive / is_grenade / is_hands / is_on_groundbool
time_basenumber世界时间基准
spec_indexint观战目标
backpack_tierint0=None / 1=White / 2=Blue / 3=Purple / 4=Gold
consumablestable16 槽消耗品库存(每槽 {item: uint16, count: uint16},count==0 表示空槽)

game.entities.players (pairs 可遍历)

每个 PlayerEntity 字段:

字段类型说明
indexintentity_list 索引
baseuint64实体内存基址,配 offsets + mem.read/write 自助读
name / weapon / legend / legend_icon_keystring
platform_uidstringuint64 转 string
rosteruint8名册标记位(pro/celeb/cheater/friends)
grade / kills / damage / xpint等级 / 击杀 / 伤害 / 经验
rank / rank_icon_key / rank_colorstring排名信息
rank_sourceint排名分数原始值
distancenumber
origin / head_pos / abs_velocityVec3
vec_min / vec_maxVec3碰撞盒 AABB
yawnumber偏航角
team_num / squad_idint
health / shield / max_shieldint
flagsintm_fFlags 状态位
weapon_idint武器 string-table 索引
spec_indexint该玩家正在观战的目标
last_visible_time / cloak_endtimenumber可见性 / 隐身时间戳
is_visible / is_down / is_dead / is_teammate / is_cloak / is_npcbool
in_screen / can_draw / has_bones / is_model_blocked / is_glow / is_wallbool渲染相关状态

#game.entities.players 不工作(userdata-backed 表无 #)—— 用 for _ in pairs(...) do n = n + 1 end 计数。

骨骼 / Skeleton

PlayerEntity 暴露 17 根骨骼世界坐标,配 game.BONE(部位常量)与 game.BONE_LINKS(连线表)画骨架 ESP。

成员 / 常量说明
player:bone(idx)部位 idx(0-based body part id)的世界坐标 Vec3;越界或骨骼未就绪返回零向量
player:has_fresh_bones()本帧 17 根骨是否真读到(false 时 bone() 多半是零,应跳过)
game.BONE部位命名常量表:head=0, upper_chest, chest, waist, hip, l_shoulder, l_elbow, l_hand, r_shoulder, r_elbow, r_hand, l_thigh, l_knee, l_foot, r_thigh, r_knee, r_foot=16
game.BONE_LINKS连线数组,每项 {a, b} 是一对部位 id(与原生骨架一致,共 16 段)

math.WorldToScreen(world) 返回 3 个值 (sx, sy, ok),不是 Vec2。

lua
-- 骨架 ESP:遍历连线,把每根骨投影到屏幕画线
local LINKS = game.BONE_LINKS
event.on("frame_update", function()
    for _, p in pairs(game.entities.players) do
        if p.is_visible and not p.is_dead and not p.is_teammate and p:has_fresh_bones() then
            for _, link in ipairs(LINKS) do
                local ax, ay, ok1 = math.WorldToScreen(p:bone(link[1]))
                local bx, by, ok2 = math.WorldToScreen(p:bone(link[2]))
                if ok1 and ok2 then
                    draw.line(ax, ay, bx, by, draw.u8(255, 255, 255, 200), 1.5)
                end
            end
        end
    end
end)

game.entities.loots (pairs 可遍历)

每个 LootEntity 字段:

字段类型说明
indexintentity_list 索引
baseuint64实体内存基址,配 offsets + mem.read/write 自助读
originVec3
distancenumber
model_namestring
model_hashuint32model_name 的 hash
classified_idintItemId 枚举数值
classified_name / item_id_str / base_namestring分类后的名字
quality_levelint0=未知, 1..5=COMMON..HEIRLOOM
weapon_name_indexint武器名 string-table 索引
custom_script_intint
context_idint

game.entities.projectiles (pairs 可遍历)

每个 ProjectileEntity 字段:

字段类型说明
indexintentity_list 索引
baseuint64实体内存基址,配 offsets + mem.read/write 自助读
kindstring"frag" / "thermite" / "arc_star" / "other" / "unknown"
originVec3
team_numint
dmg_radiusnumberm_DmgRadius (0x2f94)
owner_handle_rawuint32m_hOwnerEntity 原始 EHandle 位
weapon_class_indexuint16m_weaponClassIndex,配合 game.world 反查武器名
creation_timenumber实体出生时间(once_read 时 ctx.time)
is_throwablebool真玩家手雷(过滤静态 map 道具)
is_enemy / is_localbool

game.aimbot (read-only)

字段类型说明
target_indexint当前 aimbot 目标的实体索引(无目标时为 -1)
target_distancenumber (米)当前目标距离
predict_posVec3 | nilaimbot 内部 predict 后的目标位置
trigger_busybool扳机决策当前是否在 busy 状态(自定义扳机 HUD 用)
triggertable扳机详细状态快照(见下,trigger HUD 用)

weapon_next_ready_time 字段在 game.localplayer 上;trigger 状态不另立 namespace 防多渠道。

game.aimbot.trigger

所有时间戳是引擎时钟(QPC 秒,base::get_time)不是 time.game()/time.now()。表里带了同源的 now,倒计时直接用它算(如 ready_in = t.weapon_ready_at - t.now)。

字段类型说明
nownumber当前引擎时钟(QPC 秒),与下列时间戳同源;倒计时用它
busybool持有/释放窗口倒计时中
target_indexint当前评估目标(0 = 无)
pressedbool已 mouse_down
last_hitbool上次评估是否命中
snapshot_timenumber本快照 game 时间
release_at / again_atnumber计划 mouse_up / 下次允许触发时刻
visible_atnumber目标可见起点(react 计时起点)
weapon_ready_atnumber武器就绪时刻(含 rdyfudge)
react_window / again_window / release_windownumber反应 / 再触发 / 持有时长窗口
rdyfudge / radscalenumber就绪偏移 / 半径缩放
aim_offsetVec3该瞄部位相对 spine_head 的偏移
lua
event.on("frame_update", function()
    local t = game.aimbot.trigger
    if t.target_index ~= 0 then
        local ready_in = math.max(0, t.weapon_ready_at - t.now)
        draw.text(20, 200, draw.u8(255,255,255,255),
                  string.format("trigger: tgt=%d hit=%s ready_in=%.2f",
                                t.target_index, tostring(t.last_hit), ready_in))
    end
end)

自定义瞄准算法(移动/平滑 + 预测覆写)

让脚本注册自己的移动算法(进 dropdown)和预测算法(全局覆写)。执行模型:回调在 render 线程跑(与 Lua VM 同线程,无锁)。平滑节奏 = aim 发布率 ↔ 渲染帧率取小(render 不限速 → 高频);预测慢变,render 算好瞄点交 aim 线程 500Hz 消费,不掉频。原生「普通/PID」路径完全不受影响。

game.aimbot.solve(shooter, target_pos, target_vel, v0, gravity){pitch, yaw, time} | nil

原生弹道解算(无状态,可随便调)。pitch/yaw 为 Source 角(度,pitch 正=向下),time 为飞行时间(秒)。v0 ≤ 1 视为 hitscan(time=0);超出射程返回 nil。坐标 Vec3 世界系,速度 u/s,重力 u/s²。

game.aimbot.register_algorithm(name, fn)

注册一个「移动算法」。name 追加到 aim / 扳机的 移动算法 dropdown;用户选中后由本算法接管鼠标平滑。fn(state) 返回 dx, dy(mickey 位移,引擎自动累加子像素)。脚本卸载时自动注销。

只能在脚本加载主体(top-level)调用 —— deferred 回调(event.on("frame_update", ...) / Delay() / gui.Button 的 callback 等)里调会被拒绝并记限频日志,因为 owner 在 load 完成后已清空,注册没法绑定回正确脚本(避免静默 leak)。需要懒注册请把 register_algorithm 放主体里、用脚本侧 flag 控制启用。

state 字段:

字段类型说明
err_pitch / err_yawnumber (度)当前瞄准误差(已含预测补偿 + 死区清零)
dtnumber (秒)距本算法上次被调的时间
distancenumber (米)目标距离
zoomingbool是否开镜
mouse_sensnumber游戏内灵敏度(要屏幕一致可用 err/0.022/mouse_sens 换 mickey)
target_indexint目标实体索引
shooter / swayVec3 / Vec2发射点 / 当前参考视角
target / velocityVec3世界命中点 / 目标速度(u/s)

符号约定与原生一致:dx = -err_yaw·kdy = err_pitch·k

game.aimbot.set_predictor(fn)

全局复写预测算法fn(target) 返回世界瞄点 Vec3;aim 线程 500Hz 用它替原生 solve。传 nil 清除(回退原生)。target 字段:indexshooterheadoriginvelocity(Vec3)、distancev0gravity

同上 register_algorithm —— 只能在脚本加载主体调用。同时全局只能由一个脚本注册:已被其它脚本占用时拒绝且不会通知 Lua 侧(只记 throttled 日志),建议遵循"一进程一 predictor"约定或卸掉占用脚本后重试。

lua
local tab  = gui.tab("AimAlgo")
local g    = tab:group("g", "Lua 瞄准算法", 0, 0, 300, 0)
local gain = g:slider_float("gain", "强度 (mickey/度)", 0.55, 0.05, 2.0)
local lead = g:checkbox("lead", "预测覆写", true)

-- 自适应缓动平滑:进 dropdown,选中即生效
game.aimbot.register_algorithm("Lua 自适应", function(s)
    local mag  = math.sqrt(s.err_pitch^2 + s.err_yaw^2)
    local f    = gain:get() * (1.0 - 0.4 * math.exp(-mag))   -- 近身柔、远端满
    return -s.err_yaw * f, s.err_pitch * f
end)

-- 预测覆写:复用原生 solve 拿飞行时间,再按速度外推落点
game.aimbot.set_predictor(function(t)
    if not lead:get() then return t.head end
    local sol = game.aimbot.solve(t.shooter, t.head, t.velocity, t.v0, t.gravity)
    if not sol then return t.head end
    return Vec3(t.head.x + t.velocity.x * sol.time,
                t.head.y + t.velocity.y * sol.time,
                t.head.z + t.velocity.z * sol.time)
end)

game.world

字段类型说明
ringtable{origin=Vec3, radius_start=N, radius_end=N, time_start=N, time_end=N, is_active=bool};radius / origin 单位为游戏内 units(≈ inches),换米 ÷ 39.37
map_namestring当前地图字符串

game 顶层 method

方法返回说明
game:is_in_game()bool是否在游戏中(signon_state 综合 + 没在等待匹配)
game:signon_state()intclient_state.signon_state 原始值

示例

lua
local lp = game.localplayer
if lp.is_dead then return end

for _, p in pairs(game.entities.players) do
    if (not p.is_teammate) and p.is_visible and p.distance < 50 then
        log.info("敌人 " .. (p.name or "?") .. " 在 " .. p.distance .. "m")
    end
end

if game.world.map_name == "mp_rr_arena_skygarden" then
    -- ...
end