Загрузка данных


EnablePrimaryMouseButtonEvents(true)

-- УПРАВЛЕНИЕ
-- №5 перед стрельбой или во время ЛКМ: запустить помощь.
-- После запуска боковую можно отпустить.
-- Отпустил ЛКМ: движение останавливается.
-- Быстро нажал ЛКМ снова: помощь запускается заново.
--
-- При отпущенной ЛКМ:
-- Alt + №5        = увеличить силу
-- Ctrl + №5       = уменьшить силу
-- Alt + Ctrl + №5 = вернуть исходную силу

-- ===== НАСТРОЙКИ =====

local sideButton = 5

local startWindowMs = 3000 -- Ожидание ЛКМ после боковой, мс
local restartWindowMs = 500 -- Ожидание новой очереди после отпускания ЛКМ

local startStep = 3
local endStep = 14
local rampMs = 1900
local delayMs = 7
local horizontalStep = 0
local smoothRamp = true

local defaultPower = 100
local powerStep = 5
local minPower = 50
local maxPower = 200

local debugLog = true -- false = отключить подробный журнал

-- ===== ДАЛЬШЕ МЕНЯТЬ НЕ НУЖНО =====

local power = defaultPower
local pendingUntil = nil

local function SetPower(value, label)
    power = math.max(minPower, math.min(maxPower, value))
    OutputLogMessage(
        "%s | POWER: %d%% | START: %.2f | END: %.2f\n",
        label, power,
        startStep * power / 100,
        endStep * power / 100
    )
end

function OnEvent(event, arg)
    if event == "PROFILE_ACTIVATED" then
        EnablePrimaryMouseButtonEvents(true)
        pendingUntil = nil
        SetPower(defaultPower, "READY")
        return
    end

    if event == "PROFILE_DEACTIVATED" then
        pendingUntil = nil
        return
    end

    if event ~= "MOUSE_BUTTON_PRESSED" then return end
    if arg ~= 1 and arg ~= sideButton then return end

    if debugLog then
        OutputLogMessage("PRESS: %d\n", arg)
    end

    local now = GetRunningTime()
    local leftHeld = IsMouseButtonPressed(1)
    local shouldStart = false

    if arg == sideButton then
        -- Регулировка силы при отпущенной ЛКМ
        if not leftHeld then
            local alt = IsModifierPressed("alt")
            local ctrl = IsModifierPressed("ctrl")

            if alt or ctrl then
                pendingUntil = nil

                if alt and ctrl then
                    SetPower(defaultPower, "RESET")
                elseif alt then
                    SetPower(power + powerStep, "UP")
                else
                    SetPower(power - powerStep, "DOWN")
                end
                return
            end
        end

        if leftHeld then
            -- Полученного события боковой достаточно
            shouldStart = true
        else
            pendingUntil = now + math.max(startWindowMs, 0)
            if debugLog then OutputLogMessage("WAIT LMB\n") end
            return
        end

    elseif arg == 1 then
        -- Ожидание после боковой или предыдущей очереди
        local withinWindow =
            pendingUntil ~= nil and now <= pendingUntil

        shouldStart = withinWindow
            or IsMouseButtonPressed(sideButton)
    end

    if debugLog then
        OutputLogMessage(
            "CHECK | start=%s | left=%s\n",
            tostring(shouldStart),
            tostring(IsMouseButtonPressed(1))
        )
    end

    if not shouldStart then return end

    -- Короткое ожидание обновления состояния ЛКМ
    if arg == 1 then
        local checkStarted = GetRunningTime()

        while not IsMouseButtonPressed(1)
            and GetRunningTime() - checkStarted < 20 do
            Sleep(1)
        end
    end

    if not IsMouseButtonPressed(1) then
        if debugLog then OutputLogMessage("LMB NOT HELD\n") end
        return
    end

    -- Запуск подтверждён: расходуем ожидание
    pendingUntil = nil
    if debugLog then OutputLogMessage("START\n") end

    -- Каждая очередь начинает усиление заново
    local startedAt = GetRunningTime()
    local remainder = 0

    while IsMouseButtonPressed(1) do
        local progress = math.min(
            (GetRunningTime() - startedAt) / math.max(rampMs, 1), 1
        )

        local step = startStep + (endStep - startStep) * progress
        if not smoothRamp then step = math.floor(step) end

        local movement = step * power / 100 + remainder
        local wholeStep = math.floor(movement)
        remainder = movement - wholeStep

        MoveMouseRelative(horizontalStep, wholeStep)

        local pauseStarted = GetRunningTime()
        repeat
            if not IsMouseButtonPressed(1) then break end
            Sleep(1)
        until GetRunningTime() - pauseStarted >= math.max(delayMs, 1)
    end

    -- Движение остановлено.
    -- Разрешаем быстро начать следующую очередь без боковой.
    if restartWindowMs > 0 then
        pendingUntil = GetRunningTime() + restartWindowMs
    else
        pendingUntil = nil
    end

    if debugLog then
        OutputLogMessage(
            "STOP | RESTART WINDOW: %d ms\n",
            math.max(restartWindowMs, 0)
        )
    end
end