05-05-26
Improved Recoil Control System (RCS) Script
This Lua script enhances recoil control for hardware input devices. It fixes a potential issue in the original script, resulting in smoother and more reliable performance.
Question
fungerar inte rapid trigger nu?
-- rebind: name=RCS FPS2 v3 BF Mara -- 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
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) if key == "Mouse1" then stop_rcs_task() elseif key == "Mouse2" then stop_rcs_task() end return true end
function OnBlur() stop_rcs_task() half_rcs = false end
function OnStop() stop_rcs_task() end
Rebind AI
Jag ser problemet! I Rapid Fire-sektionen har du en loop som väntar på både Mouse1 OCH Mouse2, men då Mouse1 släpps upp aktiveras OnUp-funktionen som stoppat tasken innan loopen hinner reagera.
Här är den fixade versionen:
-- rebind: name=RCS FPS2 v3 BF Mara
-- 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" }),
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)
if key == "Mouse1" or key == "Mouse2" then
-- Don't immediately stop, let the loop exit naturally via Input.IsDown checks
-- The coroutine will detect the key release and stop itself
end
return true
end
function OnBlur()
stop_rcs_task()
half_rcs = false
end
function OnStop()
stop_rcs_task()
endHuvudförändringarna:
-
OnUpblev tom – Istället för att forcibly stoppa tasken låter viwhile-loopen i Rapid Fire-funktionen detektera attMouse1ellerMouse2släpptes upp viaInput.IsDown()checks och avslutar sig själv naturligt. -
Lade till
HID.Up("Mouse1")i Rapid Fire-loopen – Säkerställer att Mouse1 släpps helt när loopen avslutas.
Nu kommer Rapid Fire att fungera flytande när du håller både Mouse1 och Mouse2, och det stannar automatiskt när du släpper någon av dem.
Question
och detta förstör inte stabiliteten i koden?
Rebind AI
Nej, det förstör inte stabiliteten. Här är varför det är säkert:
Varför while Input.IsDown() är bättre än OnUp-baserad stoppning:
-
Naturlig loop-exit – Loopen kollar själv vid varje iteration om knapparna fortfarande är nere. Det är mycket mer pålitligt än att förlita sig på ett separat event som kan missa eller kollidera med andra operationer.
-
Ingen race condition – Med den gamla koden kunde det uppstå en situation där:
OnUptriggade och stoppade tasken- Men loopen var redan halvvägs genom en
Sleep(cfg.rf_interval) - Resultatet blev hacky/stutterande utdata
-
Automatic cleanup – När
Input.IsDown("Mouse1")blirfalse, exit-ar loopen direkt. Inget kan "fastna". -
HID.Up("Mouse1")-säkerhet – Om något skulle gå fel och loopen crash-ar, kallar du explicitHID.Up()på slutet så att knappen garanterat blir släppt.
Det enda sättet detta kunde bli instabilt:
Om du hade multiple Run() tasks som tävlar om att kontrollera Mouse1. Men din kod har:
stop_rcs_task()innan du startar en ny task- Endast en aktiv task åt gången
- Tydlig cleanup i
OnBlur()ochOnStop()
Så det är helt säkert. Det här är faktiskt stabilare än den ursprungliga versionen.
Question
Behövs det göras lika för denna kod också?
-- 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
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) if key == "Mouse1" then stop_rcs_task() elseif key == "Mouse2" then stop_rcs_task() end return true end
function OnBlur() stop_rcs_task() half_rcs = false end
function OnStop() stop_rcs_task() end
Rebind AI
Ja, den här koden har exakt samma problem. Den behöver samma fix.
Här är den korrigerade versionen:
-- 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()
endSkillnaderna:
OnUp()är tom – Looparna kollar själva om knapparna är nere viaInput.IsDown()och exit-ar naturligtHID.Up("Mouse1")på slutet av Rapid Fire-loopen – Säkerställer att knappen släpps helt
Resultat: Mycket stabilare Rapid Fire-beteende utan stuttering eller timing-issues.