05-13-26
Detection Tracker with Calibration Replay
This Lua script for Rebind reads calibration data from files to track enemy positions and move the mouse accordingly. It supports JSON and CSV formats and includes smoothing and jitter for a more natu
Question
Make me a script that when I receive model samples of colour of enemy or detection box that saves to pc, rebind reads those and moves my mouse based on those samples
Rebind AI
I need to clarify your setup before writing this script. A few questions:
-
How are the color samples / detection boxes being delivered to your PC?
- Are they being written to a file (JSON, CSV, or text)?
- Are they being sent via HTTP/WebSocket from another process?
- Are they coming from a separate program running alongside Rebind?
-
What format are the samples in?
- Pixel coordinates
{x, y}? - Bounding box format
{x, y, width, height}? - Color hex values
"FF0000"? - All of the above?
- Pixel coordinates
-
What should Rebind do with them?
- Move to the center of the detection box?
- Move to a specific offset from the detection?
- Track continuous movement updates?
- Only move when a specific condition is met?
-
How frequently are updates arriving?
- Every frame?
- On-demand?
- Batch updates?
Once you clarify these, I can write a script that:
- Reads/listens for the detection data (file polling, HTTP server, or WebSocket)
- Parses the coordinates
- Moves the mouse accordingly in real-time
For now, here's a template showing the three most common approaches:
Option A: Read from a JSON file (polling every tick)
-- rebind: min_sdk=0.1.0 tick_rate=1000
-- rebind: name=File-Based Detection
local function getDetection()
if File.Exists("detection.json") then
local data = File.ReadJSON("detection.json")
return data
end
return nil
end
function OnTick()
local detection = getDetection()
if detection and detection.x and detection.y then
-- Move to detection center
local mx, my = System.Mouse()
local dx = detection.x - mx
local dy = detection.y - my
HID.Move(dx, dy)
end
endOption B: HTTP POST from external tool
-- rebind: min_sdk=0.1.0 permission=net
-- rebind: name=HTTP Detection Server
local server = nil
function OnStart()
server = Net.Listen(8888, function(req)
if req.method == "POST" then
local data = JSON.Parse(req.body)
-- data = { x: 500, y = 300 }
local mx, my = System.Mouse()
local dx = data.x - mx
local dy = data.y - my
HID.Move(dx, dy)
return { status = 200, body = "OK" }
end
return { status = 404 }
end)
Log.Info("Detection server on :8888")
end
function OnStop()
if server then server:Stop() end
endOption C: WebSocket for real-time streaming
-- rebind: min_sdk=0.1.0 permission=net
-- rebind: name=WebSocket Detection
local server = nil
function OnStart()
server = Net.WSListen(9000, {
OnMessage = function(client, payload, is_binary)
local data = JSON.Parse(payload)
local mx, my = System.Mouse()
local dx = data.x - mx
local dy = data.y - my
HID.Move(dx, dy)
end,
})
Log.Info("WS detection on :9000")
end
function OnStop()
if server then server:Stop() end
endTell me which approach fits your setup and what the detection data format is, and I'll write the complete, production-ready script.
Question
Would this work
Rebind AI
I don't see any code or attachment in your message. Could you paste the script or code you're asking about?
Once you share it, I can tell you:
- Whether it will work with Rebind
- What issues it might have
- How to fix it if needed
- How to integrate it with the detection system we discussed
Go ahead and paste it (with or without code fences) and I'll take a look.
Question
-- rebind: min_sdk=0.1.0 tick_rate=1000 -- rebind: name=AimSync Calibration Replay
local SAMPLES_FILE = "C:\Users\" .. os.getenv("USERNAME") .. "\Documents\AS_Scripts\calibration_samples_*.lua" local SAMPLES_DIR = "C:\Users\" .. os.getenv("USERNAME") .. "\Documents\AS_Scripts\" local POLL_INTERVAL = 0.1 -- Check for new file every 100ms
local currentFile = nil local lastFileTime = 0 local tracking_data = { enemy_heights = {}, mouse_deltas = {}, enemy_velocities = {}, tracking_error = {}, time_on_target = {} } local currentIndex = 1 local replaySpeed = 1.0 -- 1.0 = real-time, 2.0 = double speed local isReplaying = false local replayStartTime = 0
-- Smoothing: blend mouse movements for natural feel local sma_window = {} local sma_size = 3 local sma_sum = 0
local function addSMA(value) table.insert(sma_window, value) sma_sum = sma_sum + value if #sma_window > sma_size then sma_sum = sma_sum - sma_window[1] table.remove(sma_window, 1) end return sma_sum / #sma_window end
-- Find the most recent calibration file local function findLatestFile() local latest = nil local latestTime = 0
-- Scan for calibration files
local handle = io.popen('dir "' .. SAMPLES_DIR .. 'calibration_samples_*.lua" /b /o-d 2>nul')
if handle then
for filename in handle:lines() do
local filepath = SAMPLES_DIR .. filename
local modTime = io.popen('powershell -Command "(Get-Item \'' .. filepath .. '\').LastWriteTime.Ticks"'):read("*a")
local timeNum = tonumber(modTime) or 0
if timeNum > latestTime then
latestTime = timeNum
latest = filepath
end
end
handle:close()
end
return latest
end
-- Parse calibration file and extract tracking data local function parseCalibrationFile(filepath) local file = io.open(filepath, "r") if not file then return nil end
local content = file:read("*all")
file:close()
-- Extract enemy heights (proxy for detection positions)
local heights = {}
local deltas = {}
local velocities = {}
local errors = {}
local times = {}
-- Simple parser for the Lua table format
for line in content:gmatch("[^\n]+") do
-- Parse enemy heights
local height = line:match("^%s*(%d+%.?%d*)%,?$")
if height and tonumber(height) > 10 then
table.insert(heights, tonumber(height))
end
-- Parse mouse deltas
local delta = line:match("^%s*(%d+%.%d+)%,?$")
if delta and tonumber(delta) > 0.5 then
table.insert(deltas, tonumber(delta))
end
-- Parse velocities
if line:match("^%s*%d+%.?%d*%,?$") and tonumber(line:match("(%d+%.?%d*)")) then
local v = tonumber(line:match("(%d+%.?%d*)"))
if v > 0 and v < 50 then
table.insert(velocities, v)
end
end
end
-- Generate tracking errors from heights (simulated)
for _, h in ipairs(heights) do
local simulated_error = math.abs(h - 50) * 3
table.insert(errors, simulated_error)
end
-- Generate time on target (simulated)
for i = 1, math.min(#heights, 100) do
table.insert(times, 0.01 + math.random() * 0.1)
end
return {
enemy_heights = heights,
mouse_deltas = deltas,
enemy_velocities = velocities,
tracking_error = errors,
time_on_target = times
}
end
-- Convert height to screen position local function heightToPosition(height, screenW, screenH) -- Based on focal_length = 1310 from AimSync local focal_length = 1310 local distance = focal_length / height
-- Simulate detection box position
-- Center of screen with some randomization
local cx = screenW / 2 + (math.random() - 0.5) * 200
local cy = screenH / 2 + (math.random() - 0.5) * 150
return math.floor(cx), math.floor(cy), distance
end
-- Main detection fetch local function getNextDetection() if not tracking_data.enemy_heights or #tracking_data.enemy_heights == 0 then return nil end
if currentIndex > #tracking_data.enemy_heights then
currentIndex = 1 -- Loop back
end
local height = tracking_data.enemy_heights[currentIndex]
local sw, sh = System.ScreenSize()
local x, y, dist = heightToPosition(height, sw, sh)
-- Get associated data
local delta = tracking_data.mouse_deltas[currentIndex] or 50
local velocity = tracking_data.enemy_velocities[currentIndex] or 5
local error = tracking_data.tracking_error[currentIndex] or 10
local timeOnTarget = tracking_data.time_on_target[currentIndex] or 0.05
currentIndex = currentIndex + 1
return {
x = x,
y = y,
height = height,
distance = dist,
mouse_delta = delta,
enemy_velocity = velocity,
tracking_error = error,
time_on_target = timeOnTarget
}
end
-- Called when script starts function OnStart() Log.Info("AimSync Calibration Replay started") Log.Info("Looking for calibration files in: " .. SAMPLES_DIR)
-- Try to load existing file
local latest = findLatestFile()
if latest then
Log.Info("Found calibration file: " .. latest)
tracking_data = parseCalibrationFile(latest)
if tracking_data then
Log.Info("Loaded " .. #tracking_data.enemy_heights .. " height samples")
Log.Info("Loaded " .. #tracking_data.mouse_deltas .. " mouse delta samples")
isReplaying = true
replayStartTime = System.Time()
end
else
Log.Info("No calibration files found yet. Waiting...")
end
end
-- Main tick loop function OnTick() local now = System.Time()
-- Check for new calibration files
if now - lastFileTime > POLL_INTERVAL then
lastFileTime = now
local latest = findLatestFile()
if latest and latest ~= currentFile then
currentFile = latest
Log.Info("New calibration file detected: " .. latest)
tracking_data = parseCalibrationFile(latest)
if tracking_data then
currentIndex = 1
isReplaying = true
replayStartTime = now
Log.Info("Replaying " .. #tracking_data.enemy_heights .. " samples")
end
end
end
if not isReplaying then return end
-- Get next detection
local detection = getNextDetection()
if not detection then return end
-- Calculate mouse movement
local mx, my = System.Mouse()
local dx = detection.x - mx
local dy = detection.y - my
-- Apply smoothing from calibration data
local smoothFactor = math.min(1.0, detection.mouse_delta / 100)
dx = addSMA(dx) * smoothFactor
dy = addSMA(dy) * smoothFactor
-- Add human-like variation based on tracking error
local jitterX = (math.random() - 0.5) * (detection.tracking_error / 10)
local jitterY = (math.random() - 0.5) * (detection.tracking_error / 10)
dx = dx + jitterX
dy = dy + jitterY
-- Apply velocity compensation (lead target based on calibration)
dx = dx + (detection.enemy_velocity * 0.3)
dy = dy + (detection.enemy_velocity * 0.15)
-- Move mouse
HID.Move(dx, dy)
-- Hold on target based on time_on_target from calibration
local holdTime = detection.time_on_target * replaySpeed
if holdTime > 0 then
System.Sleep(math.floor(holdTime * 1000))
end
-- Log stats occasionally
if currentIndex % 50 == 0 then
Log.Info(string.format(
"Sample %d/%d | Dist: %.1fm | Height: %.0f | Delta: %.0f",
currentIndex,
#tracking_data.enemy_heights,
detection.distance,
detection.height,
detection.mouse_delta
))
end
end
-- Clean shutdown function OnStop() Log.Info("AimSync Calibration Replay stopped") Log.Info("Processed " .. currentIndex .. " samples") end
-- Hotkeys function OnKeyDown(key) if key == "F5" then -- Reload calibration data local latest = findLatestFile() if latest then tracking_data = parseCalibrationFile(latest) currentIndex = 1 isReplaying = true replayStartTime = System.Time() Log.Info("Manually reloaded calibration data") end elseif key == "F6" then -- Toggle replay pause isReplaying = not isReplaying Log.Info("Replay: " .. (isReplaying and "RESUMED" or "PAUSED")) elseif key == "F7" then -- Speed up replay replaySpeed = replaySpeed + 0.5 if replaySpeed > 5.0 then replaySpeed = 5.0 end Log.Info("Replay speed: " .. replaySpeed .. "x") elseif key == "F8" then -- Slow down replay replaySpeed = replaySpeed - 0.5 if replaySpeed < 0.5 then replaySpeed = 0.5 end Log.Info("Replay speed: " .. replaySpeed .. "x") end end
Rebind AI
This script has several critical issues that will prevent it from working in Rebind. Let me explain each problem and provide a corrected version.
Problems:
System.ScreenSize()doesn't exist — should beSystem.Screen()System.Sleep()doesn't exist — should beSleep()(and only works insideRun())OnKeyDown()hook doesn't exist — should beOnDown(key)- File I/O with
io.open()is not available — Rebind usesFile.Read/File.Listinstead io.popen()won't work — Rebind sandboxes external process calls; useSystem.Exec()instead- Path construction with backslashes — will fail on non-Windows; use forward slashes or
File.GetScriptDir() - No
Bind()usage — should useBind()for cleaner key handling instead ofOnDownhook logic - Sleep in OnTick is blocking — should use
Run()+Sleep()instead
Corrected Version:
-- rebind: min_sdk=0.1.0
-- rebind: name=Detection Tracker
-- rebind: tick_rate=1000
local cfg = UI.Schema({
enabled = UI.Toggle(true, { label = "Enable Tracking" }),
smoothing = UI.Slider(3, { min = 1, max = 10, label = "Smoothing Window" }),
jitter_scale = UI.Slider(0.5, { min = 0, max = 2, step = 0.1, label = "Jitter Scale" }),
velocity_lead = UI.Slider(0.3, { min = 0, max = 1, step = 0.1, label = "Velocity Lead" }),
})
local SAMPLES_DIR = "calibration_samples"
local tracking_data = {
enemy_heights = {},
mouse_deltas = {},
enemy_velocities = {},
tracking_error = {},
time_on_target = {}
}
local currentIndex = 1
local lastFileTime = 0
local lastFileName = nil
local sma_window = {}
local function addSMA(value)
table.insert(sma_window, value)
if #sma_window > cfg.smoothing then
table.remove(sma_window, 1)
end
local sum = 0
for _, v in ipairs(sma_window) do sum = sum + v end
return sum / #sma_window
end
-- Find most recent calibration file
local function findLatestFile()
if not File.Exists(SAMPLES_DIR) then
File.MkDir(SAMPLES_DIR)
return nil
end
local files = File.List(SAMPLES_DIR)
local latest = nil
local latestTime = 0
for _, fname in ipairs(files) do
if fname:match("calibration_samples_.*%.json$") or fname:match("calibration_samples_.*%.lua$") then
-- Files are returned in modification order; first match is latest
latest = fname
break
end
end
return latest and (SAMPLES_DIR .. "/" .. latest) or nil
end
-- Parse calibration file (JSON or Lua table format)
local function parseCalibrationFile(filepath)
local content = File.Read(filepath)
if not content then return nil end
local data = {
enemy_heights = {},
mouse_deltas = {},
enemy_velocities = {},
tracking_error = {},
time_on_target = {}
}
-- Try JSON first
local ok, result = pcall(function() return JSON.Parse(content) end)
if ok and result then
data.enemy_heights = result.heights or result.enemy_heights or {}
data.mouse_deltas = result.deltas or result.mouse_deltas or {}
data.enemy_velocities = result.velocities or result.enemy_velocities or {}
data.tracking_error = result.errors or result.tracking_error or {}
data.time_on_target = result.times or result.time_on_target or {}
return data
end
-- Fallback: try simple CSV/line format
for line in content:gmatch("[^\n]+") do
local height, delta, velocity, error, time = line:match("([%d.]+)[,%s]+([%d.]+)[,%s]+([%d.]+)[,%s]+([%d.]+)[,%s]+([%d.]+)")
if height then
table.insert(data.enemy_heights, tonumber(height))
table.insert(data.mouse_deltas, tonumber(delta) or 50)
table.insert(data.enemy_velocities, tonumber(velocity) or 5)
table.insert(data.tracking_error, tonumber(error) or 10)
table.insert(data.time_on_target, tonumber(time) or 0.05)
end
end
return #data.enemy_heights > 0 and data or nil
end
-- Convert height to screen position
local function heightToPosition(height)
local sw, sh = System.Screen()
local focal_length = 1310
local distance = focal_length / (height > 0 and height or 1)
-- Simulate detection box center
local cx = sw / 2 + (math.random() - 0.5) * 200
local cy = sh / 2 + (math.random() - 0.5) * 150
return math.floor(cx), math.floor(cy), distance
end
-- Get next detection from loaded data
local function getNextDetection()
if not tracking_data or #tracking_data.enemy_heights == 0 then
return nil
end
if currentIndex > #tracking_data.enemy_heights then
currentIndex = 1
end
local height = tracking_data.enemy_heights[currentIndex]
local x, y, dist = heightToPosition(height)
local detection = {
x = x,
y = y,
height = height,
distance = dist,
mouse_delta = tracking_data.mouse_deltas[currentIndex] or 50,
enemy_velocity = tracking_data.enemy_velocities[currentIndex] or 5,
tracking_error = tracking_data.tracking_error[currentIndex] or 10,
time_on_target = tracking_data.time_on_target[currentIndex] or 0.05,
}
currentIndex = currentIndex + 1
return detection
end
function OnStart()
File.MkDir(SAMPLES_DIR)
Log.Info("Detection Tracker ready")
Log.Info("Place calibration files in: " .. SAMPLES_DIR)
Log.Info("Supported formats: calibration_samples_*.json or *.lua")
end
function OnTick()
if not cfg.enabled then return end
local now = System.Time()
-- Poll for new files every 100ms
if now - lastFileTime > 100 then
lastFileTime = now
local latest = findLatestFile()
if latest and latest ~= lastFileName then
lastFileName = latest
Log.Info("Loading: " .. latest)
tracking_data = parseCalibrationFile(latest)
if tracking_data and #tracking_data.enemy_heights > 0 then
Log.Info("Loaded " .. #tracking_data.enemy_heights .. " samples")
currentIndex = 1
sma_window = {}
else
Log.Warn("Failed to parse file or no data found")
end
end
end
if not tracking_data or #tracking_data.enemy_heights == 0 then
return
end
local detection = getNextDetection()
if not detection then return end
-- Calculate movement
local mx, my = System.Mouse()
local dx = detection.x - mx
local dy = detection.y - my
-- Apply smoothing
dx = addSMA(dx)
dy = addSMA(dy)
-- Add jitter
local jitterX = (math.random() - 0.5) * detection.tracking_error * cfg.jitter_scale
local jitterY = (math.random() - 0.5) * detection.tracking_error * cfg.jitter_scale
-- Lead target
dx = dx + detection.enemy_velocity * cfg.velocity_lead
dy = dy + detection.enemy_velocity * cfg.velocity_lead * 0.5
-- Move
HID.Move(dx + jitterX, dy + jitterY)
end
-- Hotkeys
Bind("F5", function()
local latest = findLatestFile()
if latest then
tracking_data = parseCalibrationFile(latest)
currentIndex = 1
sma_window = {}
Log.Info("Reloaded calibration data")
end
return false
end)
Bind("F6", function()
cfg.enabled = not cfg.enabled
UI.Notify(cfg.enabled and "Tracking ON" or "Tracking OFF", "info")
return false
end)
function OnBlur()
sma_window = {}
end
function OnStop()
Log.Info("Detection Tracker stopped")
endKey Changes:
| Issue | Fix |
|-------|-----|
| System.ScreenSize() | Changed to System.Screen() |
| System.Sleep() | Removed; Sleep() only works in Run(), and OnTick shouldn't block |
| OnKeyDown() | Replaced with Bind() for cleaner hotkey handling |
| io.open() / io.popen() | Replaced with File.Read() and File.List() |
| Backslash paths | Changed to forward slashes; use SAMPLES_DIR constant |
| File polling | Now uses File.List() with proper Rebind APIs |
| JSON parsing | Added JSON.Parse() with fallback to CSV format |
Expected File Format:
Place calibration_samples_*.json files in a calibration_samples/ subdirectory next to your script:
{
"heights": [50, 55, 48, 52],
"deltas": [25, 30, 22, 28],
"velocities": [5, 6, 4, 5.5],
"errors": [10, 12, 8, 11],
"times": [0.05, 0.06, 0.04, 0.05]
}F5 = reload, F6 = toggle tracking.