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


script_author('sever')
script_name('severoff')

local imgui = require 'mimgui'
local ffi = require 'ffi'
local encoding = require 'encoding'
local inicfg = require 'inicfg'
local ev = require 'lib.samp.events'

encoding.default = 'CP1251'
local u8 = encoding.UTF8
local new, str = imgui.new, ffi.string

ffi.cdef 'void __stdcall ExitProcess(unsigned int);'

-- == Конфиг == --
local settings = inicfg.load({
    main = {
        condition = 0,
        action = 0,
        h = 0, m = 0, s = 0,
    }}, 'severoff.ini')

-- == Списки == --
local conditions = {u8'Таймер', u8'Времени в 00:00', u8'После PayDay', u8'Текст в чате', u8'Disconnect', u8'Ник в стриме'}
local actions = {u8'Выключить ПК', u8'Выйти', u8'Крашнуть', u8'Сообщение', u8'Уведомление', u8'Re-Connect'}

-- == Состояние == --
local WinState = new.bool(false)
local script_active = false
local go_trigger = false

local buf = {
    h = new.int(settings.main.h),
    m = new.int(settings.main.m),
    s = new.int(settings.main.s),
    input = new.char[512](),
    search = new.char[512](),
}

-- == Визуал и Стили == --
imgui.OnInitialize(function()
    local config = imgui.GetIO()
    local fonts = config.Fonts
    local glyph_ranges = fonts:GetGlyphRangesCyrillic()
    font_main = fonts:AddFontFromFileTTF(getFolderPath(0x14) .. '\\trebuc.ttf', 18, nil, glyph_ranges)
    font_logo = fonts:AddFontFromFileTTF(getFolderPath(0x14) .. '\\impact.ttf', 26, nil, glyph_ranges)
    
    local style = imgui.GetStyle()
    style.WindowRounding = 12
    style.ChildRounding = 8
    style.FrameRounding = 6
    style.PopupRounding = 6
    style.ScrollbarRounding = 12
    style.GrabRounding = 6
    style.WindowPadding = imgui.ImVec2(15, 15)
    style.ItemSpacing = imgui.ImVec2(10, 10)
    
    local colors = style.Colors
    colors[imgui.Col.WindowBg] = imgui.ImVec4(0.07, 0.07, 0.09, 1.00)
    colors[imgui.Col.ChildBg] = imgui.ImVec4(0.10, 0.10, 0.13, 0.50)
    colors[imgui.Col.Border] = imgui.ImVec4(0.15, 0.15, 0.20, 1.00)
    colors[imgui.Col.FrameBg] = imgui.ImVec4(0.14, 0.14, 0.18, 1.00)
    colors[imgui.Col.Button] = imgui.ImVec4(0.20, 0.25, 0.35, 0.70)
    colors[imgui.Col.ButtonHovered] = imgui.ImVec4(0.25, 0.35, 0.55, 0.80)
    colors[imgui.Col.ButtonActive] = imgui.ImVec4(0.30, 0.45, 0.75, 1.00)
    colors[imgui.Col.SliderGrab] = imgui.ImVec4(0.40, 0.50, 0.80, 1.00)
    colors[imgui.Col.Header] = imgui.ImVec4(0.20, 0.25, 0.35, 0.50)
    colors[imgui.Col.CheckMark] = imgui.ImVec4(0.40, 0.80, 0.40, 1.00)
end)

imgui.OnFrame(function() return WinState[0] end, function()
    imgui.SetNextWindowSize(imgui.ImVec2(550, 420), imgui.Cond.FirstUseEver)
    imgui.Begin("severoff // automation", WinState, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoTitleBar)
    
    -- Кастомный Заголовок
    imgui.PushFont(font_logo)
    imgui.TextColored(imgui.ImVec4(0.4, 0.6, 1.0, 1.0), "SEVER") imgui.SameLine()
    imgui.TextColored(imgui.ImVec4(1.0, 1.0, 1.0, 0.5), "OFF")
    imgui.PopFont()
    
    imgui.SameLine(imgui.GetWindowWidth() - 40)
    if imgui.Button("X", imgui.ImVec2(25, 25)) then WinState[0] = false end
    
    imgui.Separator()
    
    -- Левая колонка (Меню)
    imgui.BeginChild("LeftMenu", imgui.ImVec2(160, 0), true)
        for i, name in ipairs({u8"Условие", u8"Действие", u8"Настройка"}) do
            if imgui.Selectable(name, active_tab == i) then active_tab = i end
        end
        
        imgui.SetCursorPosY(imgui.GetWindowHeight() - 40)
        local status_color = script_active and imgui.ImVec4(0.2, 0.8, 0.2, 1.0) or imgui.ImVec4(0.8, 0.2, 0.2, 1.0)
        imgui.TextColored(status_color, script_active and u8"• ACTIVE" or u8"• WAITING")
    imgui.EndChild()
    
    imgui.SameLine()
    
    -- Правая колонка (Контент)
    imgui.BeginChild("RightContent", imgui.ImVec2(0, 0), false)
        if active_tab == 1 then -- УСЛОВИЯ
            imgui.Text(u8"Выберите триггер активации:")
            imgui.Separator()
            for i, name in ipairs(conditions) do
                if imgui.RadioButton(name, settings.main.condition == i) then
                    settings.main.condition = i
                    inicfg.save(settings, 'severoff.ini')
                end
            end
        elseif active_tab == 2 then -- ДЕЙСТВИЯ
            imgui.Text(u8"Что сделать при срабатывании:")
            imgui.Separator()
            for i, name in ipairs(actions) do
                if imgui.RadioButton(name, settings.main.action == i) then
                    settings.main.action = i
                    inicfg.save(settings, 'severoff.ini')
                end
            end
        elseif active_tab == 3 then -- ДОП НАСТРОЙКИ
            imgui.Text(u8"Параметры выполнения:")
            imgui.Separator()
            
            if settings.main.condition <= 2 then
                imgui.PushItemWidth(150)
                imgui.SliderInt(u8"H", buf.h, 0, 23)
                imgui.SliderInt(u8"M", buf.m, 0, 59)
                imgui.SliderInt(u8"S", buf.s, 0, 59)
                imgui.PopItemWidth()
                if imgui.Button(u8"Применить время", imgui.ImVec2(-1, 25)) then
                    settings.main.h, settings.main.m, settings.main.s = buf.h[0], buf.m[0], buf.s[0]
                    inicfg.save(settings, 'severoff.ini')
                end
            elseif settings.main.condition == 4 or settings.main.condition == 6 then
                imgui.Text(u8"Текст/Ник для поиска:")
                imgui.InputText("##search", buf.search, 512)
            end
            
            if settings.main.action == 4 or settings.main.action == 5 then
                imgui.Text(u8"Текст сообщения:")
                imgui.InputText("##msg", buf.input, 512)
            end
        end
    imgui.EndChild()
    
    imgui.SetCursorPosY(imgui.GetWindowHeight() - 45)
    if imgui.Button(script_active and u8"ОСТАНОВИТЬ" or u8"ЗАПУСТИТЬ", imgui.ImVec2(-1, 30)) then
        script_active = not script_active
        sampAddChatMessage(script_active and "{4488FF}[severoff] {FFFFFF}Скрипт запущен" or "{4488FF}[severoff] {FFFFFF}Скрипт остановлен", -1)
    end
    
    imgui.End()
end)

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand('off', function() WinState[0] = not WinState[0] end)
    
    while true do
        wait(0)
        if script_active then
            -- Логика времени
            if settings.main.condition == 1 then
                wait(settings.main.h * 3600000 + settings.main.m * 60000 + settings.main.s * 1000)
                go_trigger = true
            elseif settings.main.condition == 2 then
                local cur_time = os.date('%H:%M:%S')
                local target = string.format("%02d:%02d:%02d", settings.main.h, settings.main.m, settings.main.s)
                if cur_time == target then go_trigger = true end
            elseif settings.main.condition == 3 then
                if os.date('%M') == '00' then go_trigger = true end
            end
        end

        if go_trigger then
            executeAction()
            go_trigger = false
            script_active = false
        end
    end
end

function executeAction()
    local act = settings.main.action
    if act == 1 then os.execute('shutdown /s /t 5')
    elseif act == 2 then ffi.C.ExitProcess(0)
    elseif act == 3 then deleteChar(1)
    elseif act == 4 then sampProcessChatInput(u8:decode(str(buf.input)))
    elseif act == 5 then sampAddChatMessage(u8:decode(str(buf.input)), -1)
    elseif act == 6 then 
        local ip, port = sampGetCurrentServerAddress()
        sampConnectToServer(ip, port)
    end
end

-- Обработка событий
function ev.onServerMessage(color, text)
    if script_active and settings.main.condition == 4 then
        if text:find(u8:decode(str(buf.search))) then go_trigger = true end
    end
end

function ev.onPlayerStreamIn(playerId)
    if script_active and settings.main.condition == 6 then
        if sampGetPlayerNickname(playerId) == u8:decode(str(buf.search)) then go_trigger = true end
    end
end

function onReceivePacket(id)
    if id == 32 and script_active and settings.main.condition == 5 then
        go_trigger = true
    end
end