05-10-26

Smart Crouch Toggle with Movement Detection

This Lua script for Rebind provides a smart crouch toggle with movement detection. It offers toggle, hold, and auto-release modes, with options for strafing, spam prevention, and custom movement keys,

rebindlua scriptcrouchtogglemovementdetectionhardware input

Question

Pixel color trigger with randomized delay

Rebind AI

I'll create a pixel color trigger script that monitors screen color at the cursor and fires an action when a target color is detected, with randomized delay to avoid detection patterns.

Before I write the script, let me clarify a few things:

  1. What action should trigger? Click, key press, or something else?
  2. Which mouse button or key? (e.g., Mouse1 for left click)
  3. Should the script scan continuously or only while a key is held?
  4. What's your tolerance for color matching? (e.g., how close does the pixel need to match?)

For now, I'll create a general-purpose version that clicks when a target color is detected, with all these as configurable options:

lua
-- rebind: min_sdk=0.1.0
-- rebind: name=Pixel Color Trigger
-- rebind: description=Fire action when screen pixel matches target color

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable" }),

    target_color = UI.Text("FF0000", {
        label = "Target Color (hex)",
        placeholder = "RRGGBB",
        maxLength = 6,
        group = "Detection",
    }),

    tolerance = UI.Slider(20, {
        min = 0,
        max = 100,
        label = "Color Tolerance",
        suffix = "px distance",
        group = "Detection",
    }),

    sample_x = UI.Slider(50, {
        min = 0,
        max = 100,
        label = "Sample X",
        suffix = "%",
        tooltip = "Horizontal position (0=left, 100=right)",
        group = "Detection",
    }),

    sample_y = UI.Slider(50, {
        min = 0,
        max = 100,
        label = "Sample Y",
        suffix = "%",
        tooltip = "Vertical position (0=top, 100=bottom)",
        group = "Detection",
    }),

    action = UI.Select("Left Click", { "Left Click", "Right Click", "Double Click", "Press Space" }, {
        group = "Action",
    }),

    delay_min = UI.Slider(50, {
        min = 0,
        max = 500,
        label = "Delay Min",
        suffix = "ms",
        group = "Randomization",
    }),

    delay_max = UI.Slider(150, {
        min = 0,
        max = 1000,
        label = "Delay Max",
        suffix = "ms",
        group = "Randomization",
    }),

    cooldown = UI.Slider(100, {
        min = 0,
        max = 1000,
        label = "Cooldown",
        suffix = "ms",
        tooltip = "Prevent spam triggers",
        group = "Randomization",
    }),

    scan_mode = UI.Select("Continuous", { "Continuous", "Hold Key" }, {
        group = "Scan Mode",
    }),

    hold_key = UI.Keybind("Mouse3", {
        label = "Hold to Scan",
        showIf = "scan_mode:Hold Key",
        group = "Scan Mode",
    }),
})

local lastTriggerTime = 0

local function hexToRgb(hex)
    if not hex or #hex ~= 6 then return 255, 0, 0 end
    return tonumber(hex:sub(1, 2), 16), tonumber(hex:sub(3, 4), 16), tonumber(hex:sub(5, 6), 16)
end

local function colorDistance(hex1, hex2)
    local r1, g1, b1 = hexToRgb(hex1)
    local r2, g2, b2 = hexToRgb(hex2)
    return math.sqrt((r2 - r1) ^ 2 + (g2 - g1) ^ 2 + (b2 - b1) ^ 2)
end

local function shouldScan()
    if cfg.scan_mode == "Continuous" then
        return true
    else
        return Input.IsDown(cfg.hold_key)
    end
end

local function executeAction()
    local now = System.Time()
    if now - lastTriggerTime < cfg.cooldown then
        return
    end

    lastTriggerTime = now

    local delay = Math.Random(cfg.delay_min, cfg.delay_max)

    After(delay, function()
        Run(function()
            if cfg.action == "Left Click" then
                HID.Press("Mouse1", 30)
            elseif cfg.action == "Right Click" then
                HID.Press("Mouse2", 30)
            elseif cfg.action == "Double Click" then
                HID.Press("Mouse1", 30)
                Sleep(50)
                HID.Press("Mouse1", 30)
            elseif cfg.action == "Press Space" then
                HID.Press("Space", 50)
            end
        end)
    end)
end

function OnTick()
    if not cfg.enabled or not shouldScan() then
        return
    end

    local sw, sh = System.Screen()
    local px = math.floor(sw * cfg.sample_x / 100)
    local py = math.floor(sh * cfg.sample_y / 100)

    local pixel = Screen.GetPixelColor(px, py)
    if not pixel then
        return
    end

    if colorDistance(pixel, cfg.target_color) <= cfg.tolerance then
        executeAction()
    end
end

function OnStop()
    -- cleanup if needed
end

How it works:

  1. Color Detection: Samples a pixel at a configurable screen position (% of screen width/height)
  2. Tolerance Matching: Uses Euclidean distance in RGB space to match colors within your tolerance
  3. Randomized Delay: Fires the action after a random delay (min/max) to avoid detection patterns
  4. Cooldown: Prevents rapid re-triggering on the same color
  5. Scan Modes:
    • Continuous: Always scanning
    • Hold Key: Only scan while holding a modifier (e.g., Mouse3)
  6. Actions: Left click, right click, double-click, or press space

Usage:

  • Set Target Color to the hex color you want to detect (e.g., FF0000 for red)
  • Adjust Tolerance based on how close the match needs to be (higher = more lenient)
  • Set Sample X/Y to pick the screen position to monitor
  • Configure Delay Min/Max for randomization
  • Choose Scan Mode (always on or hold a key to activate)

The randomized delay is useful if you want to avoid detection by avoiding instant reactions to color changes.

Learn more:

Question

Can I set the action to a key press?

Rebind AI

Yes, you can configure the script to press a key. Here's the updated script with a key press option:

lua
-- rebind: min_sdk=0.1.0
-- rebind: name=Pixel Color Trigger
-- rebind: description=Fire action when screen pixel matches target color

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable" }),

    target_color = UI.Text("FF0000", {
        label = "Target Color (hex)",
        placeholder = "RRGGBB",
        maxLength = 6,
        group = "Detection",
    }),

    tolerance = UI.Slider(20, {
        min = 0,
        max = 100,
        label = "Color Tolerance",
        suffix = "px distance",
        group = "Detection",
    }),

    sample_x = UI.Slider(50, {
        min = 0,
        max = 100,
        label = "Sample X",
        suffix = "%",
        tooltip = "Horizontal position (0=left, 100=right)",
        group = "Detection",
    }),

    sample_y = UI.Slider(50, {
        min = 0,
        max = 100,
        label = "Sample Y",
        suffix = "%",
        tooltip = "Vertical position (0=top, 100=bottom)",
        group = "Detection",
    }),

    action = UI.Select("Left Click", { "Left Click", "Right Click", "Double Click", "Press Space", "Press Key" }, {
        group = "Action",
    }),

    key_to_press = UI.Keybind("Space", {
        label = "Key to Press",
        showIf = "action:Press Key",
        group = "Action",
    }),

    delay_min = UI.Slider(50, {
        min = 0,
        max = 500,
        label = "Delay Min",
        suffix = "ms",
        group = "Randomization",
    }),

    delay_max = UI.Slider(150, {
        min = 0,
        max = 1000,
        label = "Delay Max",
        suffix = "ms",
        group = "Randomization",
    }),

    cooldown = UI.Slider(100, {
        min = 0,
        max = 1000,
        label = "Cooldown",
        suffix = "ms",
        tooltip = "Prevent spam triggers",
        group = "Randomization",
    }),

    scan_mode = UI.Select("Continuous", { "Continuous", "Hold Key" }, {
        group = "Scan Mode",
    }),

    hold_key = UI.Keybind("Mouse3", {
        label = "Hold to Scan",
        showIf = "scan_mode:Hold Key",
        group = "Scan Mode",
    }),
})

local lastTriggerTime = 0

local function hexToRgb(hex)
    if not hex or #hex ~= 6 then return 255, 0, 0 end
    return tonumber(hex:sub(1, 2), 16), tonumber(hex:sub(3, 4), 16), tonumber(hex:sub(5, 6), 16)
end

local function colorDistance(hex1, hex2)
    local r1, g1, b1 = hexToRgb(hex1)
    local r2, g2, b2 = hexToRgb(hex2)
    return math.sqrt((r2 - r1) ^ 2 + (g2 - g1) ^ 2 + (b2 - b1) ^ 2)
end

local function shouldScan()
    if cfg.scan_mode == "Continuous" then
        return true
    else
        return Input.IsDown(cfg.hold_key)
    end
end

local function executeAction()
    local now = System.Time()
    if now - lastTriggerTime < cfg.cooldown then
        return
    end

    lastTriggerTime = now

    local delay = Math.Random(cfg.delay_min, cfg.delay_max)

    After(delay, function()
        Run(function()
            if cfg.action == "Left Click" then
                HID.Press("Mouse1", 30)
            elseif cfg.action == "Right Click" then
                HID.Press("Mouse2", 30)
            elseif cfg.action == "Double Click" then
                HID.Press("Mouse1", 30)
                Sleep(50)
                HID.Press("Mouse1", 30)
            elseif cfg.action == "Press Space" then
                HID.Press("Space", 50)
            elseif cfg.action == "Press Key" then
                HID.Press(cfg.key_to_press, 50)
            end
        end)
    end)
end

function OnTick()
    if not cfg.enabled or not shouldScan() then
        return
    end

    local sw, sh = System.Screen()
    local px = math.floor(sw * cfg.sample_x / 100)
    local py = math.floor(sh * cfg.sample_y / 100)

    local pixel = Screen.GetPixelColor(px, py)
    if not pixel then
        return
    end

    if colorDistance(pixel, cfg.target_color) <= cfg.tolerance then
        executeAction()
    end
end

function OnStop()
    -- cleanup if needed
end

Key Changes:

  • Added a new option in the action dropdown: "Press Key".
  • Added a key_to_press keybind option, which appears when "Press Key" is selected.

Now, you can select "Press Key" and choose the desired key to trigger when the color is detected.

Question

Smart crouch toggle with movement check

Rebind AI

I'll create a smart crouch toggle that automatically manages crouch state based on movement input, preventing accidental crouch locks and enabling contextual behavior.

First, let me clarify your needs:

  1. What's your crouch key? (e.g., C, LCtrl, Space)
  2. What movement keys should trigger "moving" state? (e.g., W, A, S, D)
  3. Should crouch auto-release when moving? Or just track movement state?
  4. Do you want different behavior for different movement directions? (e.g., crouch-strafe vs crouch-walk)
  5. Should there be a "force crouch" mode that ignores movement?

For now, I'll create a comprehensive version with all these options:

lua
-- rebind: min_sdk=0.1.0
-- rebind: name=Smart Crouch Toggle
-- rebind: description=Context-aware crouch with movement detection

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable" }),

    crouch_key = UI.Keybind("C", {
        label = "Crouch Key",
        group = "Binding",
    }),

    mode = UI.Select("Toggle", { "Toggle", "Hold", "Auto-Release" }, {
        label = "Crouch Mode",
        tooltip = "Toggle: tap to crouch/uncrouch. Hold: crouch while held. Auto-Release: uncrouch when moving.",
        group = "Behavior",
    }),

    movement_keys = UI.Text("WASD", {
        label = "Movement Keys",
        placeholder = "e.g., WASD",
        maxLength = 10,
        group = "Detection",
    }),

    auto_release_on_move = UI.Toggle(true, {
        label = "Auto-Release on Forward Move",
        tooltip = "Uncrouch when pressing W",
        showIf = "mode:Auto-Release",
        group = "Detection",
    }),

    strafe_aware = UI.Toggle(true, {
        label = "Strafe Aware",
        tooltip = "Allow crouch while strafing (A/D)",
        group = "Detection",
    }),

    crouch_held = UI.Toggle(false, {
        label = "Force Hold Crouch",
        group = "Override",
    }),

    prevent_spam = UI.Toggle(true, {
        label = "Prevent Spam Toggles",
        group = "Safety",
    }),

    toggle_cooldown = UI.Slider(50, {
        min = 0,
        max = 200,
        label = "Toggle Cooldown",
        suffix = "ms",
        showIf = "prevent_spam",
        group = "Safety",
    }),
})

local crouchActive = false
local lastToggleTime = 0
local crouchTask = nil

local function isMoving()
    local moveKeys = cfg.movement_keys:upper()
    for i = 1, #moveKeys do
        if Input.IsDown(moveKeys:sub(i, i)) then
            return true
        end
    end
    return false
end

local function isMovingForward()
    return Input.IsDown("W")
end

local function isStrafing()
    return Input.IsDown("A") or Input.IsDown("D")
end

local function shouldAllowCrouch()
    -- Force hold mode overrides everything
    if cfg.crouch_held then
        return true
    end

    -- Auto-release mode: uncrouch if moving forward
    if cfg.mode == "Auto-Release" and cfg.auto_release_on_move and isMovingForward() then
        return false
    end

    -- Strafe aware: allow crouch while strafing only if configured
    if cfg.strafe_aware then
        -- Allow crouch if only strafing (A/D), but not forward (W)
        return not isMovingForward()
    end

    return true
end

local function setCrouch(on)
    if on then
        HID.Down(cfg.crouch_key)
    else
        HID.Up(cfg.crouch_key)
    end
end

local function toggleCrouch()
    local now = System.Time()

    -- Cooldown check
    if cfg.prevent_spam and (now - lastToggleTime) < cfg.toggle_cooldown then
        return
    end

    lastToggleTime = now

    if cfg.mode == "Toggle" then
        crouchActive = not crouchActive
        if crouchActive and not shouldAllowCrouch() then
            crouchActive = false
        end
        setCrouch(crouchActive)
    end
end

function OnDown(key)
    if key == cfg.crouch_key and cfg.enabled then
        if cfg.mode == "Toggle" then
            toggleCrouch()
            return false
        elseif cfg.mode == "Hold" then
            if shouldAllowCrouch() then
                HID.Down(cfg.crouch_key)
                crouchActive = true
            end
            return false
        elseif cfg.mode == "Auto-Release" then
            if shouldAllowCrouch() then
                crouchActive = true
                HID.Down(cfg.crouch_key)
            end
            return false
        end
    end

    return true
end

function OnUp(key)
    if key == cfg.crouch_key and cfg.enabled then
        if cfg.mode == "Hold" or cfg.mode == "Auto-Release" then
            HID.Up(cfg.crouch_key)
            crouchActive = false
            return false
        end
    end

    return true
end

function OnTick()
    if not cfg.enabled or cfg.mode ~= "Auto-Release" then
        return
    end

    -- Auto-release: uncrouch if movement conditions change
    if crouchActive then
        if not shouldAllowCrouch() then
            HID.Up(cfg.crouch_key)
            crouchActive = false
        end
    end
end

function OnBlur()
    if crouchActive then
        HID.Up(cfg.crouch_key)
        crouchActive = false
    end
end

function OnStop()
    if crouchActive then
        HID.Up(cfg.crouch_key)
        crouchActive = false
    end
end

Three crouch modes:

  1. Toggle: Tap crouch key to crouch/uncrouch. Won't activate if movement conditions prevent it.
  2. Hold: Crouch while key is held (traditional). Respects movement checks on press.
  3. Auto-Release: Like toggle, but automatically uncrouches if you press forward (W) or violate movement rules.

Key Features:

  • Strafe Aware: Allows crouching while strafing (A/D) but blocks if moving forward (W)
  • Force Hold: Override toggle and hold modes to maintain crouch state
  • Prevent Spam: Optional cooldown to prevent accidental rapid toggles
  • Custom Movement Keys: Edit which keys count as "moving"
  • OnBlur Cleanup: Automatically releases crouch when window loses focus

Usage Examples:

  • Casual crouch: Mode=Toggle, Strafe Aware=on (tap C to crouch, stay crouched while strafing, but moving forward uncrouch)
  • Hold crouch: Mode=Hold (traditional press-to-hold behavior, respects movement)
  • Peek crouch: Mode=Auto-Release with Force Hold=on (forces crouch, auto-releases if you move forward)

Learn more: