Skip to content

Haze Auto Dagger ​

Here's a Haze script that locks onto an enemy and throws a Sleep Dagger (ability 1) whenever mouse5 is pressed.

What this shows ​

  • Reading menu settings at runtime. config.get_float("fov") pulls the current value from the cheat's settings UI every tick. Drag the slider in-game and the script responds immediately. No reload needed.
  • fire_and_hold handles the post-fire lock for you. After pressing the ability, it keeps the snap aimed at the target for hold_time ms before returning control. Haze plays a throwing animation before the dagger actually leaves her hand, and if the snap stopped the moment the key was pressed, your aim would drift during the windup and the dagger would miss.
  • The while true + coroutine.yield() pattern. fire_and_hold yields internally during its hold window. For those yields to do anything, the calling code has to be inside a coroutine context, wrapping the body of on_tick in while true do ... coroutine.yield() end provides that. Each iteration is one tick; the coroutine.yield() at the bottom is what hands control back to the engine so it can call you again on the next tick.
  • targeting.get_fov(target, bone) returns the angle in degrees between your current aim and that bone. Useful for "fire when close enough" thresholds without doing the trig yourself.
  • snap_to_target() every tick, not once. The snap isn't sticky, each call moves the camera for that single frame. Calling it every tick while tracking is what creates the smooth follow before the dagger fires.

Script ​

lua
-- Haze Auto Dagger
-- Hold mouse5 -> track closest enemy -> fire when on target -> hold lock 200ms

name = "Haze Auto Dagger"
id = hero_id.haze

settings = {
    { key = "fov",        label = "FOV (degrees)",        type = "float", default = 15.0, min = 1.0, max = 30.0 },
    { key = "max_range",  label = "Max Range (m)",        type = "float", default = 30.0, min = 5.0, max = 100.0 },
    { key = "fire_angle", label = "Fire Threshold (deg)", type = "float", default = 1.5,  min = 0.3, max = 5.0 },
    { key = "hold_time",  label = "Lock After Fire (ms)", type = "float", default = 200,  min = 0, max = 2000 },
}

function on_tick()
    while true do
        local lp = local_player()
        if lp and lp:is_alive() and input.is_key_held(VK.XBUTTON2) then
            if lp:is_ability_ready(slot.ability1) then
                local target = targeting.find_closest_by_fov(
                    config.get_float("fov"),
                    config.get_float("max_range")
                )
                if target and target:is_targetable() then
                    snap_to_target(target, { bone = bone.chest })

                    local angle = targeting.get_fov(target, bone.chest)
                    if angle and angle < config.get_float("fire_angle") then
                        fire_and_hold(target, slot.ability1, {
                            bone = bone.chest,
                            hold_time = config.get_float("hold_time")
                        })
                        toast(string.format("Dagger → %s", target:hero_name() or "?"), 2, {
                            bg = {r=40, g=15, b=50, a=220},
                            text = {r=200, g=140, b=255},
                        })
                    end
                end
            end
        end
        coroutine.yield()
    end
end

Notes ​

id = hero_id.haze locks the script to Haze only. It goes idle automatically when you pick a different hero. Comment that line out (or delete it) if you want to try the same logic with another hero's ability 1.

bone.chest is a reasonable default for hero-sized targets at medium range. For long-range work where targets have more time to dodge, bone.pelvis gives a slightly higher hit rate because most strafing motion is horizontal at the upper body but the lower body lags. Try both.

If you want a more aggressive auto-throw, lower fire_angle won't help. It makes the script wait LONGER for a tight crosshair-to-target alignment. Going the other way (higher fire_angle, say 3-4 degrees) makes the script fire more eagerly, even when the snap hasn't fully caught up. That's a trade between fewer "perfect" shots and more "good-enough" ones.

Not affiliated with Valve Corporation.