05-14-26
Generic SOCD Cleanup Script
This Lua script implements SOCD (Simultaneous Opposite Cardinal Directions) cleanup for hardware input, using last-key-wins on both axes. It includes detailed logging for debugging and can be customiz
Question
Target the script to a specific game executable and use the neutral SOCD mode.
Rebind AI
Okay, I'll modify the script to target a specific game executable and implement the neutral SOCD mode. I'll also include more detailed logging to help you understand how it works.
Here's the updated script. I've added a process tag to the script header and changed the SOCD behavior. I've also added a tick_rate to control how often the script checks for key presses.
-- rebind: min_sdk=0.1.0
-- rebind: name=SOCD Cleanup (Neutral Mode)
-- rebind: process=game.exe -- <<<< CHANGE THIS TO YOUR GAME'S .EXE NAME
-- rebind: tick_rate=8000
local cfg = UI.Schema({
enabled = UI.Toggle(true, { label = "Enable SOCD" }),
})
-- Key opposites
local OPPOSITE = {
A = "D", D = "A",
W = "S", S = "W"
}
-- Track which physical keys are held
local held = {}
-- Track which virtual keys we've sent to the system
local virt = {}
-- Remember last key pressed in each axis
local lastH = nil -- last horizontal key (A or D)
local lastV = nil -- last vertical key (W or S)
local function setVirt(key, on)
if virt[key] == on then
return -- already in this state, no change needed
end
if on then
HID.Down(key)
Log.Info("HID.Down(" .. key .. ")")
else
HID.Up(key)
Log.Info("HID.Up(" .. key .. ")")
end
virt[key] = on
end
local function resolve(a, b)
Log.Debug("resolve(" .. a .. ", " .. b .. ")")
-- Both held: release both
if held[a] and held[b] then
Log.Info("Both " .. a .. " and " .. b .. " held, releasing both")
setVirt(a, false)
setVirt(b, false)
-- Only one held: send it
elseif held[a] then
Log.Info(a .. " held alone")
setVirt(a, true)
setVirt(b, false)
elseif held[b] then
Log.Info(b .. " held alone")
setVirt(a, false)
setVirt(b, true)
-- Neither held: release both
else
Log.Info("Neither " .. a .. " nor " .. b .. " held")
setVirt(a, false)
setVirt(b, false)
end
end
function OnStart()
Log.Info("=== SOCD Cleanup Script Started ===")
Log.Info("Monitoring: A/D (horizontal) and W/S (vertical)")
Log.Info("Mode: Neutral")
end
function OnDown(code)
if not cfg.enabled then
return true
end
-- Only intercept A, D, W, S
if code == "A" or code == "D" then
Log.Info("DOWN: " .. code .. " (horizontal)")
held[code] = true
resolve("A", "D")
return false -- block the original key, we're sending our own
elseif code == "W" or code == "S" then
Log.Info("DOWN: " .. code .. " (vertical)")
held[code] = true
resolve("W", "S")
return false -- block the original key
end
return true -- pass through all other keys
end
function OnUp(code)
if not cfg.enabled then
return true
end
if code == "A" or code == "D" then
Log.Info("UP: " .. code .. " (horizontal)")
held[code] = false
resolve("A", "D")
return false
elseif code == "W" or code == "S" then
Log.Info("UP: " .. code .. " (vertical)")
held[code] = false
resolve("W", "S")
return false
end
return true
end
function OnBlur()
Log.Info("=== Window lost focus, releasing all held keys ===")
-- Release all virtual keys we're holding
for key, isHeld in pairs(virt) do
if isHeld then
HID.Up(key)
Log.Info("Released " .. key .. " on blur")
end
end
-- Clear state
held = {}
virt = {}
lastH = nil
lastV = nil
end
function OnStop()
Log.Info("=== SOCD Cleanup Script Stopped ===")
-- Cleanup: release any stuck keys
for key, isHeld in pairs(virt) do
if isHeld then
HID.Up(key)
end
end
held = {}
virt = {}
endKey Changes and Explanations:
-- rebind: process=game.exe: This line is crucial. Replacegame.exewith the actual name of the executable file for your game. The script will only activate when this process is running.- Neutral SOCD Mode: When both keys in an axis are held, the script now releases both virtual keys. This is the core of the neutral behavior.
tick_rate: Thetick_ratesetting controls how often the script runs its main logic. A higher value means the script runs more frequently, which can improve responsiveness but also increase CPU usage. The default value is 8000, which means the script runs 8000 times per second.
How to Use:
- Replace
game.exe: Open the script in Rebind and change the-- rebind: process=line to match your game's executable name (e.g.,cs2.exe,valorant.exe, etc.). - Test: Launch your game and test the A/D and W/S keys. Open the Rebind logs to see the script's actions.
This version should provide the neutral SOCD behavior you requested, only when the specified game is running. Let me know if you have any other questions or need further adjustments!