05-19-26

Color Trigger Lua Script

This Lua script for Rebind uses hardware input to detect a target color on screen and trigger an action. Configure the color and tolerance in the UI for a responsive and customizable experience.

rebindlua scriptcolor triggerhardware inputscreenpixelscript

Question

Can you remake this Python script in Rebind? I've also included the config section.

python
import os
import json, time, threading, keyboard,sys
import win32.win32api as win32api 
from ctypes import WinDLL
import numpy as np
import bettercam
        
user32, kernel32, shcore = (
    WinDLL("user32", use_last_error=True),
    WinDLL("kernel32", use_last_error=True),
    WinDLL("shcore", use_last_error=True),
)

shcore.SetProcessDpiAwareness(2)
WIDTH, HEIGHT = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]

ZONE = 3.9
GRAB_ZONE = (
    int(WIDTH / 2 - ZONE),
    int(HEIGHT / 2 - ZONE),
    int(WIDTH / 2 + ZONE),
    int(HEIGHT / 2 + ZONE),
)


class elchapo:
    def __init__(supreme):
        supreme.sct = bettercam.create(output_color='BGRA', output_idx=0)
        supreme.elchapo = False
        supreme.elchapo_toggle = True
        supreme.exit_program = False 
       
        with open('config.json') as json_file:
            data = json.load(json_file)

        try:
            supreme.trigger_hotkey = int(data["trigger_hotkey"],16)
            supreme.trigger_delay = data["trigger_delay"]
            supreme.base_delay = data["base_delay"]
            supreme.color_tolerance = data["color_tolerance"]
            supreme.R = data["R"]
            supreme.G = data["G"]
            supreme.B = data["B"]
        except:
            print("ERROR LOADING CONFIG. MAKE SURE CONFIG.JSON IS LOCATED IN THE SAME DIRECTORY")
            

    def scanning(supreme):
        img = np.array(supreme.sct.grab(GRAB_ZONE))
        while img.any() == None:
            img = np.array(supreme.sct.grab(GRAB_ZONE))
        pixels = img.reshape(-1, 4)    
        color_mask = (
            (pixels[:, 0] > supreme.R -  supreme.color_tolerance) & (pixels[:, 0] < supreme.R +  supreme.color_tolerance) &
            (pixels[:, 1] > supreme.G -  supreme.color_tolerance) & (pixels[:, 1] < supreme.G +  supreme.color_tolerance) &
            (pixels[:, 2] > supreme.B -  supreme.color_tolerance) & (pixels[:, 2] < supreme.B +  supreme.color_tolerance)
        )
        matching_pixels = pixels[color_mask]
        if supreme.elchapo and len(matching_pixels) > 0:
            keyboard.press_and_release("l")
            time.sleep(0.06)

        
    def hold(supreme):
        while True:
            while win32api.GetAsyncKeyState(supreme.trigger_hotkey) < 0:
                supreme.elchapo = True
                supreme.scanning()
            else:
                time.sleep(0.5)


    def initialise(supreme):
        while not supreme.exit_program:
                supreme.hold()

elchapo().initialise()
json
{
    "trigger_hotkey":  "0x56",
    "always_enabled":  false,
    "trigger_delay":  40,
    "base_delay":  0,
    "color_tolerance":  55,
    "R":  200,
    "G":  55,
    "B":  200	
}

Rebind AI

I'll remake this as a Rebind script. This is a color trigger that fires a click when it detects a specific color in the center of the screen while a hotkey is held.

lua
-- rebind: min_sdk=0.1.0
-- rebind: name=Color Trigger
-- rebind: description=Fire when target color is detected at screen center

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable" }),
    trigger_key = UI.Keybind("V", { label = "Trigger Key (Hold)" }),
    
    target_r = UI.Slider(200, { min = 0, max = 255, label = "Red", group = "Target Color" }),
    target_g = UI.Slider(55, { min = 0, max = 255, label = "Green", group = "Target Color" }),
    target_b = UI.Slider(200, { min = 0, max = 255, label = "Blue", group = "Target Color" }),
    tolerance = UI.Slider(55, { min = 0, max = 255, label = "Tolerance", group = "Target Color" }),
    
    trigger_delay = UI.Slider(40, { min = 0, max = 200, suffix = "ms", label = "Trigger Delay", group = "Timing" }),
})

local scan_zone = 3.9  -- radius in pixels from center
local screen_w, screen_h = System.Screen()
local center_x, center_y = screen_w / 2, screen_h / 2

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

local function checkColor()
    local pixel = Screen.GetPixelColor(center_x, center_y)
    if not pixel then return false end
    
    local r = tonumber(pixel:sub(1, 2), 16)
    local g = tonumber(pixel:sub(3, 4), 16)
    local b = tonumber(pixel:sub(5, 6), 16)
    
    local dist = colorDistance(r, g, b, cfg.target_r, cfg.target_g, cfg.target_b)
    return dist <= cfg.tolerance
end

function OnDown(key)
    if not cfg.enabled then return true end
    
    if key == cfg.trigger_key then
        Run(function()
            while Input.IsDown(cfg.trigger_key) do
                if checkColor() then
                    HID.Press("L", 20)
                    Sleep(cfg.trigger_delay)
                else
                    Sleep(10)
                end
            end
        end)
        return false
    end
    
    return true
end

How it works:

  1. Target Color: Configure R/G/B values and tolerance in the UI (matches your config.json)
  2. Trigger Key: Hold the key (default V) to activate scanning
  3. Color Detection: Every tick while held, samples the center pixel and checks if it matches the target color within tolerance
  4. Fire: When a match is found, presses L and waits for the trigger delay before checking again

Key differences from your Python version:

  • No manual hotkey polling — Rebind hooks handle key state detection
  • Simpler color matching — uses Euclidean distance (same logic as your original)
  • UI config instead of JSON — settings persist automatically, editable in the UI
  • Non-blocking async — the scanning loop runs in a coroutine, doesn't freeze input

To adjust from your config:

  • trigger_key = "0x56" (V in hex)
  • target_r/g/b = your RGB values
  • tolerance = your color_tolerance
  • trigger_delay = your trigger_delay

The script automatically cleans up when you release the key or switch windows.

Learn more