Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Исходник [Скрипт] Hell Let Loose — RCS для Logitech G HUB с поддержкой всех видов оружия

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
189
Реакции
5
Народ, кто сейчас гоняет в Hell Let Loose и устал бороться с отдачей на автоматике, решил слить вам старую, но до сих пор рабочую тему. Это LUA-скрипт для Logitech G HUB, портированный с сессионок под HLL. По факту это простая RCS-паста, но работает стабильно, если руки прямые и понимаете, как настраивать сенсу.

Техническая часть:
Скрипт полностью экстернальный, работает на уровне макросов логитековского софта. Никаких инжектов, поэтому с античитом проблем минимум, если не наглеть с пресетами. Логика простая: при зажиме ЛКМ, если нажата кнопка ADS, скрипт имитирует движение мыши вниз с поправкой на горизонтальную отдачу конкретного ствола.

  1. Конфиг: Под DPI 800 и 40% сенсу в игре. Под другие значения придется править переменные в секции operators.
  2. Функционал: Переключение сторон (AXIS/ALIES), смена стволов через кнопки мыши, поддержка первичного/вторичного оружия.
  3. Рандомизация: Добавлена микро-поправка на разброс (randomLevelX/Y), чтобы не было идеальной прямой линии вниз, что немного снижает риск подозрения со стороны сервера.

Код:
Expand Collapse Copy
--[[
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.

Важные нюансы:
  1. В Grease Gun еще не забивал значения, руки не дошли, сами допишите по аналогии с остальными пушками.
  2. Скрипт требует включения макросов в самом софте Logitech.
  3. Если чувствуете, что прицел уводит не туда — играйтесь с параметром value (вертикаль) и horizontal.

Юзайте на свой страх и риск, хотя для HLL такие макросы в 99% случаев летят мимо античита. Кто уже тестил под текущие патчи — отпишитесь, как по ощущениям, не детектит ли софт логитековскую активность? И если кто допиливал оффсеты отдачи под последние стволы, кидайте свои правки, обсудим.
 
Народ, кто сейчас гоняет в Hell Let Loose и устал бороться с отдачей на автоматике, решил слить вам старую, но до сих пор рабочую тему. Это LUA-скрипт для Logitech G HUB, портированный с сессионок под HLL. По факту это простая RCS-паста, но работает стабильно, если руки прямые и понимаете, как настраивать сенсу.

Техническая часть:
Скрипт полностью экстернальный, работает на уровне макросов логитековского софта. Никаких инжектов, поэтому с античитом проблем минимум, если не наглеть с пресетами. Логика простая: при зажиме ЛКМ, если нажата кнопка ADS, скрипт имитирует движение мыши вниз с поправкой на горизонтальную отдачу конкретного ствола.

  1. Конфиг: Под DPI 800 и 40% сенсу в игре. Под другие значения придется править переменные в секции operators.
  2. Функционал: Переключение сторон (AXIS/ALIES), смена стволов через кнопки мыши, поддержка первичного/вторичного оружия.
  3. Рандомизация: Добавлена микро-поправка на разброс (randomLevelX/Y), чтобы не было идеальной прямой линии вниз, что немного снижает риск подозрения со стороны сервера.

Код:
Expand Collapse Copy
--[[
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.

Важные нюансы:
  1. В Grease Gun еще не забивал значения, руки не дошли, сами допишите по аналогии с остальными пушками.
  2. Скрипт требует включения макросов в самом софте Logitech.
  3. Если чувствуете, что прицел уводит не туда — играйтесь с параметром value (вертикаль) и horizontal.

Юзайте на свой страх и риск, хотя для HLL такие макросы в 99% случаев летят мимо античита. Кто уже тестил под текущие патчи — отпишитесь, как по ощущениям, не детектит ли софт логитековскую активность? И если кто допиливал оффсеты отдачи под последние стволы, кидайте свои правки, обсудим.
я б тебе написал но не хочу любовные письма получать
 
Назад
Сверху Снизу