05-14-26

Advanced Recoil Control System Script

This Lua script for hardware input provides an advanced recoil control system (RCS) with multiple weapon profiles, rapid fire, and customizable settings. Control recoil in your favorite games with thi

rebindlua scriptrecoil controlRCShardware inputscriptrapid fire

Question

Does this use HID.Move()?

Rebind AI

Yes, this uses HID.Move() to apply recoil control.

This script is a Recoil Control System (RCS).

lua
-- rebind: name=RCS FPS2 v2 Pubg
-- rebind: tick_rate=1000

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

    -- Slot 1
    slot1_ar_rcs  = UI.Slider(1.4, { min = 0.1, max = 30, step = 0.1, suffix = "px/tick", label = "Slot 1 AR",  group = "Slot 1" }),
    slot1_smg_rcs = UI.Slider(1.2, { min = 0.1, max = 30, step = 0.1, suffix = "px/tick", label = "Slot 1 SMG", group = "Slot 1" }),
    slot1_mode    = UI.Select("AR", { "AR", "SMG" },                  { label = "Slot 1 Weapon",                     group = "Slot 1" }),
    slot1_rf      = UI.Toggle(false,                                  { label = "Rapid Fire on Slot 1",              group = "Slot 1" }),

    -- Slot 2
    slot2_sks_pull = UI.Slider(58, { min = 10, max = 200, step = 1,   suffix = "px",      label = "Slot 2 SKS Pull", group = "Slot 2" }),
    slot2_smg_rcs  = UI.Slider(1.2, { min = 0.1, max = 30, step = 0.1, suffix = "px/tick", label = "Slot 2 SMG",     group = "Slot 2" }),
    slot2_mode     = UI.Select("SKS", { "SKS", "SMG" },               { label = "Slot 2 Weapon",                     group = "Slot 2" }),
    slot2_rf       = UI.Toggle(false,                                  { label = "Rapid Fire on Slot 2",              group = "Slot 2" }),

    -- Slot 3 (Pistol)
    slot3_sks_pull = UI.Slider(58, { min = 10, max = 200, step = 1,   suffix = "px",      label = "Slot 3 SKS Pull", group = "Slot 3" }),
    slot3_mode     = UI.Select("Continuous", { "Continuous", "SKS Kick" },  { label = "Slot 3 Fire Mode",        group = "Slot 3" }),
    slot3_rcs      = UI.Slider(1, { min = 0.1, max = 30, step = 0.1, suffix = "px/tick", label = "Slot 3 RCS",     group = "Slot 3" }),
    slot3_kick     = UI.Slider(58, { min = 10, max = 200, step = 1,   suffix = "px",      label = "Slot 3 Kick",     group = "Slot 3" }),
    slot3_rf       = UI.Toggle(false,                                  { label = "Rapid Fire on Slot 3",              group = "Slot 3" }),

    -- General
    half_mult    = UI.Slider(50,   { min = 10, max = 90, suffix = "%",     label = "Half Speed Multiplier", group = "General" }),
    max_duration = UI.Slider(2500, { min = 500, max = 6000, suffix = "ms", label = "Max RCS Duration",      group = "General" }),
    
    -- Stability
    min_output   = UI.Slider(0.1,  { min = 0.0, max = 1.0, step = 0.1,   label = "Min Output", tooltip = "Prevents micro-jitters",  group = "General" }),

    -- Rapid Fire
    rf_interval = UI.Slider(10, { min = 1, max = 50, step = 1, suffix = "ms", label = "Rapid Fire Interval", group = "Rapid Fire" }),
    rf_hold_ms  = UI.Slider(5,  { min = 1, max = 50, step = 1, suffix = "ms", label = "Rapid Fire Hold",     group = "Rapid Fire" }),
})

local active_slot = 1
local half_rcs = false
local rcs_task = nil

local function get_rcs_value()
    if active_slot == 1 then
        return cfg.slot1_mode == "AR" and cfg.slot1_ar_rcs or cfg.slot1_smg_rcs
    elseif active_slot == 2 then
        return cfg.slot2_smg_rcs
    else
        return cfg.slot3_rcs
    end
end

local function get_rcs_multiplier()
    return half_rcs and (cfg.half_mult / 100) or 1.0
end

local function is_sks_mode()
    return (active_slot == 2 and cfg.slot2_mode == "SKS") or 
           (active_slot == 3 and cfg.slot3_mode == "SKS Kick")
end

local function is_rapid_fire()
    if active_slot == 1 then return cfg.slot1_rf end
    if active_slot == 2 then return cfg.slot2_rf end
    if active_slot == 3 then return cfg.slot3_rf end
    return false
end

local function stop_rcs_task()
    if rcs_task and rcs_task:IsRunning() then
        rcs_task:Cancel()
        rcs_task = nil
    end
end

function OnDown(key)
    local shift = Input.IsDown("LShift") or Input.IsDown("RShift")
    local ctrl  = Input.IsDown("LCtrl") or Input.IsDown("RCtrl")

    -- RCS on/off: Shift+5
    if key == "5" and shift and not ctrl then
        cfg.enabled = not cfg.enabled
        UI.Notify(cfg.enabled and "RCS ON" or "RCS OFF", "info")
        return false
    end

    -- Slot 1 mode: Ctrl+5
    if key == "5" and ctrl and not shift then
        cfg.slot1_mode = cfg.slot1_mode == "AR" and "SMG" or "AR"
        UI.Notify("Slot 1: " .. cfg.slot1_mode, "info")
        return false
    end

    -- Slot 2 mode: Ctrl+6
    if key == "6" and ctrl and not shift then
        cfg.slot2_mode = cfg.slot2_mode == "SKS" and "SMG" or "SKS"
        UI.Notify("Slot 2: " .. cfg.slot2_mode, "info")
        return false
    end

    -- Slot 3 mode: Ctrl+7
    if key == "7" and ctrl and not shift then
        cfg.slot3_mode = cfg.slot3_mode == "Continuous" and "SKS Kick" or "Continuous"
        UI.Notify("Slot 3: " .. cfg.slot3_mode, "info")
        return false
    end

    -- Slot selection
    if not ctrl and not shift then
        if key == "1" or key == "Q" then
            active_slot = 1
            stop_rcs_task()
            UI.Notify("Slot 1 (" .. cfg.slot1_mode .. ")", "info")
        elseif key == "2" then
            active_slot = 2
            stop_rcs_task()
            UI.Notify("Slot 2 (" .. cfg.slot2_mode .. ")", "info")
        elseif key == "3" then
            active_slot = 3
            stop_rcs_task()
            UI.Notify("Slot 3 (" .. cfg.slot3_mode .. ")", "info")
        end
    end

    -- Half-speed toggle
    if key == "Z" then
        half_rcs = not half_rcs
        UI.Notify(half_rcs and "Half RCS ON" or "Half RCS OFF", "info")
        return true
    end

    -- Half-speed off
    if (key == "C" or key == "LCtrl" or key == "RCtrl") and half_rcs then
        half_rcs = false
        UI.Notify("Half RCS OFF", "info")
        return true
    end

    -- Mouse1 with right-click held: activate RCS
    if key == "Mouse1" and cfg.enabled and Input.IsDown("Mouse2") then
        
        -- Rapid Fire
        if is_rapid_fire() then
            stop_rcs_task()
            local mult = get_rcs_multiplier()
            local rcs_val = get_rcs_value() * mult
            
            rcs_task = Run(function()
                local rcs_accum = 0
                while Input.IsDown("Mouse1") and Input.IsDown("Mouse2") and cfg.enabled do
                    HID.Down("Mouse1")
                    Sleep(cfg.rf_hold_ms)
                    HID.Up("Mouse1")
                    
                    rcs_accum = rcs_accum + rcs_val
                    local pixels = math.floor(rcs_accum + 0.5)
                    if math.abs(pixels) >= cfg.min_output then
                        HID.Move(0, pixels)
                        rcs_accum = rcs_accum - pixels
                    end
                    Sleep(cfg.rf_interval)
                end
                -- Ensure Mouse1 is released when loop exits
                HID.Up("Mouse1")
            end)
            return false
        end

        -- SKS single shot
        if is_sks_mode() then
            local mult = get_rcs_multiplier()
            local pull_value = active_slot == 2 and cfg.slot2_sks_pull or cfg.slot3_sks_pull
            local pixels = math.floor(pull_value * mult)
            if pixels > 0 then
                HID.Move(0, pixels)
            end
            return true
        end

        -- Continuous RCS (AR/SMG) - FULL STRENGTH UNTIL MAX_DURATION, THEN STOP
        stop_rcs_task()
        local mult = get_rcs_multiplier()
        local rcs_base = get_rcs_value() * mult
        local start_time = System.Time()
        
        rcs_task = Run(function()
            local rcs_accum = 0
            
            while Input.IsDown("Mouse1") and Input.IsDown("Mouse2") and cfg.enabled do
                local elapsed = System.Time() - start_time
                
                -- FULL RCS UNTIL max_duration, THEN STOP
                if elapsed < cfg.max_duration then
                    rcs_accum = rcs_accum + rcs_base
                    
                    local pixels = math.floor(rcs_accum + 0.5)
                    if math.abs(pixels) >= cfg.min_output then
                        HID.Move(0, pixels)
                        rcs_accum = rcs_accum - pixels
                    end
                end
                
                Sleep(1)  -- Tick every 1ms for smooth output
            end
        end)
        return true
    end

    return true
end

function OnUp(key)
    -- Don't stop here - let the loops exit naturally via Input.IsDown() checks
    return true
end

function OnBlur()
    stop_rcs_task()
    half_rcs = false
end

function OnStop()
    stop_rcs_task()
end

Features

  • Recoil Compensation: Reduces vertical recoil. The script moves the mouse downwards to counteract the upward kick of the weapon.
  • Weapon Profiles: Supports different recoil values for different weapons or weapon modes (AR, SMG, SKS, Pistol).
  • Rapid Fire: Includes a rapid-fire mode.
  • Customization: Offers a range of settings to fine-tune the recoil compensation.
  • Slot-Based Configuration: Allows you to configure different settings for different weapon slots.
  • Half Speed Mode: Provides a half-speed mode for more control.

Configuration

The script uses a UI schema for configuration. Here's a breakdown of the settings:

  • enabled: Enables or disables the RCS.
  • slot1_ar_rcs: Recoil compensation value for AR in slot 1.
  • slot1_smg_rcs: Recoil compensation value for SMG in slot 1.
  • slot1_mode: Selects the weapon mode for slot 1 (AR or SMG).
  • slot1_rf: Enables rapid fire for slot 1.
  • slot2_sks_pull: Pull value for SKS in slot 2.
  • slot2_smg_rcs: Recoil compensation value for SMG in slot 2.
  • slot2_mode: Selects the weapon mode for slot 2 (SKS or SMG).
  • slot2_rf: Enables rapid fire for slot 2.
  • slot3_sks_pull: Pull value for pistol in slot 3.
  • slot3_mode: Selects the fire mode for slot 3 (Continuous or SKS Kick).
  • slot3_rcs: Recoil compensation value for pistol in slot 3.
  • slot3_kick: Kick value for pistol in slot 3.
  • slot3_rf: Enables rapid fire for slot 3.
  • half_mult: Multiplier for half-speed mode.
  • max_duration: Maximum duration for continuous RCS.
  • min_output: Minimum output value to prevent micro-jitters.
  • rf_interval: Rapid fire interval in milliseconds.
  • rf_hold_ms: Rapid fire hold time in milliseconds.

How it Works

  1. Initialization: The script initializes the UI schema with various settings for recoil control, rapid fire, and other features.
  2. Input Handling (OnDown):
    • Activation: The RCS is activated when Mouse1 (left mouse button) is pressed and Mouse2 (right mouse button) is held, and cfg.enabled is true.
    • Rapid Fire: If rapid fire is enabled, the script enters a loop that rapidly clicks Mouse1 with a specified interval and hold time.
    • SKS Mode: If SKS mode is active, the script moves the mouse down by a fixed amount (pull_value).
    • Continuous RCS: For AR/SMG, the script calculates the recoil compensation based on the current settings and moves the mouse down continuously until max_duration is reached.
    • Slot Selection: The script allows you to select different weapon slots using keys 1, 2, and 3, and changes the active slot.
    • Half-Speed Toggle: The script provides a toggle for half-speed mode, which reduces the recoil compensation.
  3. Input Handling (OnUp): The OnUp function is implemented, but does nothing, allowing the loops in OnDown to exit naturally when the mouse buttons are released.
  4. Blur Handling (OnBlur): When the game window loses focus, the script stops any active RCS tasks and disables half-speed mode.
  5. Stop Handling (OnStop): When the script is stopped, it cancels any active RCS tasks.