Начинающий
- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 189
- Реакции
- 5
Народ, кто сейчас гоняет в Hell Let Loose и устал бороться с отдачей на автоматике, решил слить вам старую, но до сих пор рабочую тему. Это LUA-скрипт для Logitech G HUB, портированный с сессионок под HLL. По факту это простая RCS-паста, но работает стабильно, если руки прямые и понимаете, как настраивать сенсу.
Техническая часть:
Скрипт полностью экстернальный, работает на уровне макросов логитековского софта. Никаких инжектов, поэтому с античитом проблем минимум, если не наглеть с пресетами. Логика простая: при зажиме ЛКМ, если нажата кнопка ADS, скрипт имитирует движение мыши вниз с поправкой на горизонтальную отдачу конкретного ствола.
Важные нюансы:
Юзайте на свой страх и риск, хотя для HLL такие макросы в 99% случаев летят мимо античита. Кто уже тестил под текущие патчи — отпишитесь, как по ощущениям, не детектит ли софт логитековскую активность? И если кто допиливал оффсеты отдачи под последние стволы, кидайте свои правки, обсудим.
Техническая часть:
Скрипт полностью экстернальный, работает на уровне макросов логитековского софта. Никаких инжектов, поэтому с античитом проблем минимум, если не наглеть с пресетами. Логика простая: при зажиме ЛКМ, если нажата кнопка ADS, скрипт имитирует движение мыши вниз с поправкой на горизонтальную отдачу конкретного ствола.
- Конфиг: Под DPI 800 и 40% сенсу в игре. Под другие значения придется править переменные в секции operators.
- Функционал: Переключение сторон (AXIS/ALIES), смена стволов через кнопки мыши, поддержка первичного/вторичного оружия.
- Рандомизация: Добавлена микро-поправка на разброс (randomLevelX/Y), чтобы не было идеальной прямой линии вниз, что немного снижает риск подозрения со стороны сервера.
Код:
--[[
HLL - RCS (Recoil Control System)
Version: 1488 (English, variables & comments translated and clarified)
Author: heinrich himmler (converted and documented by ChatGPT)
Quick documentation (brief):
- Purpose: lightweight, configurable RCS script for Logitech G HUB (Lua).
- Requirements: Logitech G HUB, DPI/sens recommended in header.
Controls (default):
- Toggle RCS on/off: CapsLock
- Switch side (AXISUSSR/ALIES): Right Ctrl + ScrollButton (middle mouse button by default)
- Next operator: Mouse button 7
- Previous operator: Mouse button 8
- Switch primary weapon: Ctrl + ScrollButton
- Switch secondary weapon / cycle secondaries: Alt + ScrollButton
- Fire with RCS active: Left mouse button (ADS required if configured)
License & modification: This script is provided as-is. You are free to modify, adapt and redistribute your own versions. Keep responsible use in mind.
NOTE: The documentation below and inline comments explain the code and available commands. Use the menu (Log output) to confirm current operator/weapon and RCS status.
]]
-- Enable primary mouse events for G HUB
EnablePrimaryMouseButtonEvents(true)
-- ====== CONFIGURATION ======
local toggleLock = "capslock" -- lock key used to toggle RCS on/off
local requireADS = true -- require aiming down sights (mouse button 3) for RCS to run
-- ====== BUTTONS (customize per your mouse) ======
local nextButton = 7 -- next operator
local prevButton = 8 -- previous operator
local scrollButton = 3 -- scroll click (used with modifiers)
-- ====== RANDOMIZATION SETTINGS (adjust only if you know what you're doing) ======
local randomLevelX = 0.20
local randomLevelY = 0.10
-- ====== FIXED OPERATOR ORDER (do not change programmatically) ======
local operatorOrder = {
AXISUSSR = {"MP40","GEWEHR-43","STG","MG-34","PPSH","PPSH-DRUM",},
ALIES = {"BRITISHTOMMY","USTOMMY","M1-CARABINE","M1-GARAND","USLMG","BAR","GREASE",}
}
-- ====== OPERATORS (you may add/update following this structure) ======
local operators = {
AXISUSSR = {
["MP40"] = {primaries = {{name = "MP40", value = 1, aggression = 9, horizontal = -0.1}}, secondaries = {}},
["GEWEHR-43"] = {primaries = {{name = "PPSH NORMAL MAG", value = 4.5, aggression = 9, horizontal = -0.42}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["STG"] = {primaries = {{name = "MP40", value = 1.22, aggression = 9, horizontal = -0.3}}, secondaries = {}},
["MG-34"] = {primaries = {{name = "MG-34", value = 0.2, aggression = 9, horizontal = -0.1}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["PPSH"] = {primaries = {{name = "PPSH NORMAL MAG", value = 1.55, aggression = 9, horizontal = -0.3}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["PPSH-DRUM"] = {primaries = {{name = "PPSH", value = 1.8, aggression = 9, horizontal = -0.55}}, secondaries = {{name = "SMG-12", value = 6.5, aggression = 9, horizontal = 0.6}}}
},
ALIES = {
["BRITISHTOMMY"] = {primaries = {{name = "TOMMY GUN", value = 1.1, aggression = 9, horizontal = 0.2}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["USTOMMY"] = {primaries = {{name = "TOMMY GUN", value = 1.1, aggression = 9, horizontal = 0.2}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["M1-CARABINE"] = {primaries = {{name = "M1-HITMARKRIFLE", value = 1.8, aggression = 9, horizontal = -0.35}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["M1-GARAND"] = {primaries = {{name = "M1-GARAND", value = 4.5, aggression = 9, horizontal = -0.42}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["USLMG"] = {primaries = {{name = "TOMMY GUN", value = 0.2, aggression = 9, horizontal = 0}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["BAR"] = {primaries = {{name = "TOMMY GUN", value = 1.4, aggression = 9, horizontal = 0}}, secondaries = {{name = "SMG-11", value = 10.0, aggression = 9, horizontal = 0.0}}},
["GREASE"] = {primaries = {{name = "GREASE GUN", value = 7.1, aggression = 9, horizontal = 0.0}}, secondaries = {{name = "SMG-12", value = 6.5, aggression = 9, horizontal = 0.0}}}
}
}
-- ====== INTERNAL STATE (do not edit below unless you know what you are doing) ======
local currentSide = "AXISUSSR"
local operatorList = operatorOrder[currentSide]
local currentIndex = 1
local usingSecondary = false
local rcsActive = false
local lastLockState = nil
local memory = { AXISUSSR = {index = 1, secondary = false}, ALIES = {index = 1, secondary = false} }
-- Helper: default weapon object (prevents nil access)
local function defaultWeapon()
return { name = "N/A", value = 0, aggression = 1, horizontal = 0 }
end
local function GetCurrentOperator()
return operatorList[currentIndex]
end
local function GetCurrentWeapon()
local op = GetCurrentOperator()
local opData = operators[currentSide][op]
if not opData then return defaultWeapon(), "Primary" end
if not opData.primaryIndex or opData.primaryIndex > #opData.primaries then opData.primaryIndex = 1 end
if not opData.secondaryIndex or opData.secondaryIndex > #opData.secondaries then opData.secondaryIndex = 1 end
if usingSecondary and #opData.secondaries > 0 then
return opData.secondaries[opData.secondaryIndex] or defaultWeapon(), "Secondary"
else
return opData.primaries[opData.primaryIndex] or defaultWeapon(), "Primary"
end
end
-- Print an organized menu into the G HUB log (OutputLogMessage)
local function PrintMenu()
ClearLog()
local op = GetCurrentOperator()
local weapon, wtype = GetCurrentWeapon()
local opData = operators[currentSide][op] or { primaries = {}, secondaries = {} }
-- Ensure valid indexes
if not opData.primaryIndex or opData.primaryIndex < 1 or opData.primaryIndex > #opData.primaries then opData.primaryIndex = 1 end
if not opData.secondaryIndex or opData.secondaryIndex < 1 or opData.secondaryIndex > #opData.secondaries then opData.secondaryIndex = 1 end
local sideIcon = (currentSide == "AXISUSSR") and "卐" or "✡︎"
local primaryName = "N/A"
if #opData.primaries > 0 and opData.primaries[opData.primaryIndex] then
primaryName = opData.primaries[opData.primaryIndex].name
end
local primaryMsg = "Primary: " .. primaryName
if #opData.primaries > 1 then primaryMsg = primaryMsg .. " [" .. tostring(opData.primaryIndex) .. "/" .. tostring(#opData.primaries) .. "]" end
local secondaryMsg = "Secondary: N/A"
if #opData.secondaries > 0 then
local sname = opData.secondaries[opData.secondaryIndex] and opData.secondaries[opData.secondaryIndex].name or "N/A"
secondaryMsg = "Secondary: " .. sname
if #opData.secondaries > 1 then secondaryMsg = secondaryMsg .. " [" .. tostring(opData.secondaryIndex) .. "/" .. tostring(#opData.secondaries) .. "]" end
end
local activeWeaponMsg = "N/A"
if wtype == "Secondary" then
activeWeaponMsg = (opData.secondaries[opData.secondaryIndex] and opData.secondaries[opData.secondaryIndex].name or "N/A") .. " [Secondary]"
else
activeWeaponMsg = (opData.primaries[opData.primaryIndex] and opData.primaries[opData.primaryIndex].name or "N/A") .. " [Primary]"
end
OutputLogMessage("╔════════════════════════════════════╗\n")
OutputLogMessage("║ HELL LET LOOSE | Version 1488 HH ║\n")
OutputLogMessage("╚════════════════════════════════════╝\n")
OutputLogMessage("📌 Status:\n")
OutputLogMessage(" • Side: %s %s\n", currentSide, sideIcon)
OutputLogMessage(" • Toggle (%s): %s\n\n", string.upper(toggleLock), rcsActive and "✔️ ON" or "❌ OFF")
OutputLogMessage("🎯 Current Operator:\n")
OutputLogMessage(" • Name: %s\n", op)
OutputLogMessage(" • Active Weapon: %s\n\n", activeWeaponMsg)
OutputLogMessage("🔫 Weapons:\n")
OutputLogMessage(" • %s\n", primaryMsg)
OutputLogMessage(" • %s\n\n", secondaryMsg)
local v = weapon and weapon.value or 0
local h = weapon and weapon.horizontal or 0
local agg = weapon and weapon.aggression or 0
OutputLogMessage(" • Stats => V: %.2f | H: %.2f | Agg: %d\n", v, h, agg)
OutputLogMessage("══════════════════════════════════════")
end
-- Update toggle state when lock key changes
local function UpdateToggle()
local state = IsKeyLockOn(toggleLock)
if state ~= lastLockState then
rcsActive = state
lastLockState = state
PrintMenu()
end
end
-- Switch primary weapon for current operator (cycles primaries)
local function SwitchPrimary()
local op = GetCurrentOperator()
local opData = operators[currentSide][op]
if not opData then return end
if usingSecondary then
usingSecondary = false
elseif #opData.primaries > 1 then
opData.primaryIndex = (opData.primaryIndex or 1) % #opData.primaries + 1
end
memory[currentSide].secondary = usingSecondary
PrintMenu()
end
-- Switch to / cycle secondary weapon for current operator
local function SwitchSecondary()
local op = GetCurrentOperator()
local opData = operators[currentSide][op]
if not opData then return end
if #opData.secondaries > 0 then
if usingSecondary then
opData.secondaryIndex = (opData.secondaryIndex or 1) % #opData.secondaries + 1
else
usingSecondary = true
if not opData.secondaryIndex or opData.secondaryIndex > #opData.secondaries then
opData.secondaryIndex = 1
end
end
else
usingSecondary = false
end
memory[currentSide].secondary = usingSecondary
PrintMenu()
end
-- Change operator preset left/right
local function ChangePreset(delta)
currentIndex = (currentIndex - 1 + delta + #operatorList) % #operatorList + 1
usingSecondary = false
memory[currentSide].index = currentIndex
memory[currentSide].secondary = usingSecondary
PrintMenu()
end
-- Switch side (AXISUSSR/ALIES) and remember indices per side
local function SwitchSide()
memory[currentSide].index = currentIndex
memory[currentSide].secondary = usingSecondary
currentSide = (currentSide == "AXISUSSR") and "ALIES" or "AXISUSSR"
operatorList = operatorOrder[currentSide]
currentIndex = memory[currentSide].index or 1
usingSecondary = memory[currentSide].secondary or false
PrintMenu()
end
-- MAIN EVENT LOOP HANDLER
function OnEvent(event, arg)
-- always update toggle state on events
UpdateToggle()
if event == "PROFILE_ACTIVATED" then
-- seed RNG once when profile is activated to get better randomization
if math and math.randomseed and GetRunningTime then
math.randomseed(GetRunningTime())
math.random(); math.random(); math.random()
end
lastLockState = IsKeyLockOn(toggleLock)
rcsActive = lastLockState
operatorList = operatorOrder[currentSide]
currentIndex = memory[currentSide].index or 1
usingSecondary = memory[currentSide].secondary or false
PrintMenu()
return
end
if event == "PROFILE_DEACTIVATED" then
-- clean state when profile is deactivated
rcsActive = false
lastLockState = false
return
end
if event == "MOUSE_BUTTON_PRESSED" then
if arg == prevButton then
ChangePreset(-1)
return
elseif arg == nextButton then
ChangePreset(1)
return
elseif arg == scrollButton then
-- centralized scroll button with modifiers
if IsModifierPressed("rctrl") then
SwitchSide()
return
elseif IsModifierPressed("ctrl") and not IsModifierPressed("rctrl") then
SwitchPrimary()
return
elseif IsModifierPressed("alt") then
SwitchSecondary()
return
end
end
end
-- Fire behavior when RCS is active and left button is pressed
if event == "MOUSE_BUTTON_PRESSED" and arg == 1 then
local weapon, _ = GetCurrentWeapon()
if not weapon then weapon = defaultWeapon() end
local accumX, accumY = 0, 0
local canRun = rcsActive and (not requireADS or IsMouseButtonPressed(3))
if canRun then
repeat
UpdateToggle()
if not rcsActive then break end
if requireADS and not IsMouseButtonPressed(3) then break end
-- safer random: use math.random integer range
local rndX = (math.random(-100, 100) / 100) * randomLevelX
local rndY = (math.random(-100, 100) / 100) * randomLevelY
accumX = accumX + (weapon.horizontal or 0) + rndX
accumY = accumY + (weapon.value or 0) + rndY
local moveX, fracX = math.modf(accumX)
local moveY, fracY = math.modf(accumY)
accumX, accumY = fracX, fracY
if moveX ~= 0 or moveY ~= 0 then
-- depending on the game's input mapping you may need to invert Y: MoveMouseRelative(moveX, -moveY)
MoveMouseRelative(moveX, moveY)
end
Sleep(weapon.aggression or 1)
until not IsMouseButtonPressed(1)
end
end
end
-- End of translated and cleaned v6.6
-- Documentation: see header block for controls and license note.
Важные нюансы:
- В Grease Gun еще не забивал значения, руки не дошли, сами допишите по аналогии с остальными пушками.
- Скрипт требует включения макросов в самом софте Logitech.
- Если чувствуете, что прицел уводит не туда — играйтесь с параметром value (вертикаль) и horizontal.
Юзайте на свой страх и риск, хотя для HLL такие макросы в 99% случаев летят мимо античита. Кто уже тестил под текущие патчи — отпишитесь, как по ощущениям, не детектит ли софт логитековскую активность? И если кто допиливал оффсеты отдачи под последние стволы, кидайте свои правки, обсудим.