Вопросы по Lua скриптингу

Общая тема для вопросов по разработке скриптов на языке программирования Lua, в частности под MoonLoader.
  • Задавая вопрос, убедитесь, что его нет в списке частых вопросов и что на него ещё не отвечали (воспользуйтесь поиском).
  • Поищите ответ в теме посвященной разработке Lua скриптов в MoonLoader
  • Отвечая, убедитесь, что ваш ответ корректен.
  • Старайтесь как можно точнее выразить мысль, а если проблема связана с кодом, то обязательно прикрепите его к сообщению, используя блок [code=lua]здесь мог бы быть ваш код[/code].
  • Если вопрос связан с MoonLoader-ом первым делом желательно поискать решение на wiki.

Частые вопросы

Как научиться писать скрипты? С чего начать?
Информация - Гайд - Всё о Lua скриптинге для MoonLoader(https://blast.hk/threads/22707/)
Как вывести текст на русском? Вместо русского текста у меня какие-то каракули.
Изменить кодировку файла скрипта на Windows-1251. В Atom: комбинация клавиш Ctrl+Shift+U, в Notepad++: меню Кодировки -> Кодировки -> Кириллица -> Windows-1251.
Как получить транспорт, в котором сидит игрок?
Lua:
local veh = storeCarCharIsInNoSave(PLAYER_PED)
Как получить свой id или id другого игрока?
Lua:
local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- получить свой ид
local _, id = sampGetPlayerIdByCharHandle(ped) -- получить ид другого игрока. ped - это хендл персонажа
Как проверить, что строка содержит какой-то текст?
Lua:
if string.find(str, 'текст', 1, true) then
-- строка str содержит "текст"
end
Как эмулировать нажатие игровой клавиши?
Lua:
local game_keys = require 'game.keys' -- где-нибудь в начале скрипта вне функции main

setGameKeyState(game_keys.player.FIREWEAPON, -1) -- будет сэмулировано нажатие клавиши атаки
Все иды клавиш находятся в файле moonloader/lib/game/keys.lua.
Подробнее о функции setGameKeyState здесь: lua - setgamekeystate | BlastHack — DEV_WIKI(https://www.blast.hk/wiki/lua:setgamekeystate)
Как получить id другого игрока, в которого целюсь я?
Lua:
local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- получить хендл персонажа, в которого целится игрок
if valid and doesCharExist(ped) then -- если цель есть и персонаж существует
  local result, id = sampGetPlayerIdByCharHandle(ped) -- получить samp-ид игрока по хендлу персонажа
  if result then -- проверить, прошло ли получение ида успешно
    -- здесь любые действия с полученным идом игрока
  end
end
Как зарегистрировать команду чата SAMP?
Lua:
-- До бесконечного цикла/задержки
sampRegisterChatCommand("mycommand", function (param)
     -- param будет содержать весь текст введенный после команды, чтобы разделить его на аргументы используйте string.match()
    sampAddChatMessage("MyCMD", -1)
end)
Крашит игру при вызове sampSendChat. Как это исправить?
Это происходит из-за бага в SAMPFUNCS, когда производится попытка отправки пакета определенными функциями изнутри события исходящих RPC и пакетов. Исправления для этого бага нет, но есть способ не провоцировать его. Вызов sampSendChat изнутри обработчика исходящих RPC/пакетов нужно обернуть в скриптовый поток с нулевой задержкой:
Lua:
function onSendRpc(id)
  -- крашит:
  -- sampSendChat('Send RPC: ' .. id)

  -- норм:
  lua_thread.create(function()
    wait(0)
    sampSendChat('Send RPC: ' .. id)
  end)
end
 
Последнее редактирование:

AugustTN

Известный
1,353
471
как проверить находишься ли в снайперском режиме?
 
Последнее редактирование:

kiyoshii

Известный
26
18
вроде должно работать
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)

    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
хз почему, но не работает, энтер не нажимается
 

stickD

Участник
107
22
хз почему, но не работает, энтер не нажимается
извини это я туплю (кодировку ставь на windows 1251)
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')
local active = false
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end
function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
 
  • Нравится
Реакции: kiyoshii

kiyoshii

Известный
26
18
извини это я туплю (кодировку ставь на windows 1251)
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')
local active = false
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end
function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
теперь нажимается вроде, но дело в том что при первом нажатии энтера, должен появится диалог типо "вы хотите купить наркотики?" и две кнопки - купить и назад. После этого скрипт должен нажать ещё раз энтер, но у меня даже диалог почему-то не открывается. И после этого нажатия скрипт не продолжает работать. Буду очень рад если поможешь)
 
  • Нравится
Реакции: stickD

stickD

Участник
107
22
теперь нажимается вроде, но дело в том что при первом нажатии энтера, должен появится диалог типо "вы хотите купить наркотики?" и две кнопки - купить и назад. После этого скрипт должен нажать ещё раз энтер, но у меня даже диалог почему-то не открывается. И после этого нажатия скрипт не продолжает работать. Буду очень рад если поможешь)
напишу
 

Pashyka

Участник
220
17
Хочу сделать поиск по таблице и вывод кнопок, если совпадение есть, мне нужно чтобы при любом регистре искало нормально, но код ниже почему-то неработает, можете нацелить по ошибке?

Lua:
function imgui.OnDrawFrame()   
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText(u8'##SearchText', cmds, 384, u8"Поиск", 2)
        for k,v in pairs(cmd) do
            if cmds.v:len() > 0 then
                if string.lower(v):find(string.lower(cmds.v)) then
                    imgui.Button(v, imgui.ImVec2(-0.1, 0))
                end
            else
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
 

chapo

tg/inst: @moujeek
Всефорумный модератор
9,229
12,636
Хочу сделать поиск по таблице и вывод кнопок, если совпадение есть, мне нужно чтобы при любом регистре искало нормально, но код ниже почему-то неработает, можете нацелить по ошибке?

Lua:
function imgui.OnDrawFrame()  
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText(u8'##SearchText', cmds, 384, u8"Поиск", 2)
        for k,v in pairs(cmd) do
            if cmds.v:len() > 0 then
                if string.lower(v):find(string.lower(cmds.v)) then
                    imgui.Button(v, imgui.ImVec2(-0.1, 0))
                end
            else
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
Lua:
local items = {
    'tExt',
    'HELLo',
    'worLD'
}
local search = imgui.ImBuffer(256)

-- frame:
for k, v in ipairs(items) do
    if #search.v == 0 or v:lower():find(search.v:lower()) then
        imgui.Text(v)
    end
end
 

Pashyka

Участник
220
17
Lua:
local items = {
    'tExt',
    'HELLo',
    'worLD'
}
local search = imgui.ImBuffer(256)

-- frame:
for k, v in ipairs(items) do
    if #search.v == 0 or v:lower():find(search.v:lower()) then
        imgui.Text(v)
    end
end
Не робит, тоже не ищет, из-за кодировки может быть? Хотя вроде все учтено

Lua:
cmd = {
    u8"Привет тест",
    u8"Тест привет"
}
 

Pashyka

Участник
220
17
для русских символов нужно использовать кастомную функу rlower

Мб я тупой конечно, я нашел эту функцию, по сути она, но все равно не робит, по разному пробовал и string.rlower(v) и v.rlower()


Lua:
function imgui.OnDrawFrame()  
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText('##SearchText', cmds, 384, u8"Поиск", 2)
        for k, v in pairs(cmd) do
            if #cmds.v == 0 or string.rlower(v):find(string.rlower(cmds.v)) then
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
local russian_characters = {
    [168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я',
}
function string.rlower(s)
    s = s:lower()
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch + 32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end
 

stickD

Участник
107
22
теперь нажимается вроде, но дело в том что при первом нажатии энтера, должен появится диалог типо "вы хотите купить наркотики?" и две кнопки - купить и назад. После этого скрипт должен нажать ещё раз энтер, но у меня даже диалог почему-то не открывается. И после этого нажатия скрипт не продолжает работать. Буду очень рад если поможешь)
работает 100 проц, чекал сам
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        lua_thread.create( function()
            setVirtualKeyDown(0x0D, true)
            wait(100)
            setVirtualKeyDown(0x0D, false)
        end)
    end
end

function ev.onShowDialog(dialogId, style, title, button1, button2, text)
    if dialogId == 285 then
        if text:find('Вы собираетесь купить (%d+) грамм за (%d+) вирт') then
            sampSendDialogResponse(285, 1, 0, '')
        end
    end
end
 
  • Нравится
Реакции: kiyoshii

kiyoshii

Известный
26
18
работает 100 проц, чекал сам
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        lua_thread.create( function()
            setVirtualKeyDown(0x0D, true)
            wait(100)
            setVirtualKeyDown(0x0D, false)
        end)
    end
end

function ev.onShowDialog(dialogId, style, title, button1, button2, text)
    if dialogId == 285 then
        if text:find('Вы собираетесь купить (%d+) грамм за (%d+) вирт') then
            sampSendDialogResponse(285, 1, 0, '')
        end
    end
end
лучший, работает, спасибо огромное)
 
  • Влюблен
Реакции: stickD

Pashyka

Участник
220
17
Мб я тупой конечно, я нашел эту функцию, по сути она, но все равно не робит, по разному пробовал и string.rlower(v) и v.rlower()


Lua:
function imgui.OnDrawFrame() 
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText('##SearchText', cmds, 384, u8"Поиск", 2)
        for k, v in pairs(cmd) do
            if #cmds.v == 0 or string.rlower(v):find(string.rlower(cmds.v)) then
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
local russian_characters = {
    [168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я',
}
function string.rlower(s)
    s = s:lower()
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch + 32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end

@chapo Все функции перепробовал такого типа, ничего не выходит вообще
 

chapo

tg/inst: @moujeek
Всефорумный модератор
9,229
12,636
Возможно ли прочитать std::vector через ffi?
 

Sklaets

Активный
225
35
помогите

суть нужно ( imgui.Process = false) куда -то вставить но что не делаю скрипт перестает работать а когда пишу команду на открытие imgui пишет нету команды

Lua:
script_name('Telegram Notifications Source')
script_authors('ronnyscripts, ronny_evans')
--------________________________________________________________________--------
-- подключаем библиотеки
local effil = require("effil")
local imgui = require 'imgui'
require 'lib.moonloader'
local encoding = require("encoding")
encoding.default = 'CP1251'
u8 = encoding.UTF8

local main_window_state = imgui.ImBool(false)
local text_buffer = imgui.ImBuffer(256)





--------________________________________________________________________--------



imgui.Process = true




--------________________________________________________________________--------

chat_id = '' -- чат ID юзера
token = '' -- токен бота

local updateid -- ID последнего сообщения для того чтобы не было флуда

function threadHandle(runner, url, args, resolve, reject)
    local t = runner(url, args)
    local r = t:get(0)
    while not r do
        r = t:get(0)
        wait(0)
    end
    local status = t:status()
    if status == 'completed' then
        local ok, result = r[1], r[2]
        if ok then resolve(result) else reject(result) end
    elseif err then
        reject(err)
    elseif status == 'canceled' then
        reject(status)
    end
    t:cancel(0)
end

function requestRunner()
    return effil.thread(function(u, a)
        local https = require 'ssl.https'
        local ok, result = pcall(https.request, u, a)
        if ok then
            return {true, result}
        else
            return {false, result}
        end
    end)
end

function async_http_request(url, args, resolve, reject)
    local runner = requestRunner()
    if not reject then reject = function() end end
    lua_thread.create(function()
        threadHandle(runner, url, args, resolve, reject)
    end)
end

function encodeUrl(str)
    str = str:gsub(' ', '%+')
    str = str:gsub('\n', '%%0A')
    return u8:encode(str, 'CP1251')
end

function sendTelegramNotification(msg) -- функция для отправки сообщения юзеру
    msg = msg:gsub('{......}', '') --тут типо убираем цвет
    msg = encodeUrl(msg) -- ну тут мы закодируем строку
    async_http_request('https://api.telegram.org/bot' .. token .. '/sendMessage?chat_id=' .. chat_id .. '&text='..msg,'', function(result) end) -- а тут уже отправка
end

function get_telegram_updates() -- функция получения сообщений от юзера
    while not updateid do wait(1) end -- ждем пока не узнаем последний ID
    local runner = requestRunner()
    local reject = function() end
    local args = ''
    while true do
        url = 'https://api.telegram.org/bot'..token..'/getUpdates?chat_id='..chat_id..'&offset=-1' -- создаем ссылку
        threadHandle(runner, url, args, processing_telegram_messages, reject)
        wait(0)
    end
end

function calc(str) --это тестовая функция, её не требуется переносить в ваш код
    return assert(load("return "..str))()
end

function processing_telegram_messages(result) -- функция проверОчки того что отправил чел
    if result then
        -- тута мы проверяем все ли верно
        local proc_table = decodeJson(result)
        if proc_table.ok then
            if #proc_table.result > 0 then
                local res_table = proc_table.result[1]
                if res_table then
                    if res_table.update_id ~= updateid then
                        updateid = res_table.update_id
                        local message_from_user = res_table.message.text
                        if message_from_user then
                            -- и тут если чел отправил текст мы сверяем
                            local text = u8:decode(message_from_user) .. ' ' --добавляем в конец пробел дабы не произошли тех. шоколадки с командами(типо чтоб !q не считалось как !qq)
                            if text:match('^!qq') then
                                sendTelegramNotification('Ку')
                            elseif text:match('^!q') then
                                sendTelegramNotification('Привет!')
                            elseif text:match('^!stats') then
                                sendTelegramNotification('Это тестовая версия блин')
                            elseif text:match('^!calc') then
                                local arg = text:gsub('!calc ','',1) -- вот так мы получаем аргумент команды
                                if #arg > 0 then
                                    local result_calc = calc(arg)
                                    if result_calc then
                                        sendTelegramNotification('Вы ввели пример: '..arg..'\nОтвет: '..result_calc)
                                    else
                                        sendTelegramNotification('Неверный пример!')
                                    end
                                      
                                else
                                    sendTelegramNotification('Эм, ты не ввел аргумент')
                                end
                            else -- если же не найдется ни одна из команд выше, выведем сообщение
                                sendTelegramNotification('Неизвестная команда!')
                            end
                        end
                    end
                end
            end
        end
    end
end

function getLastUpdate() -- тут мы получаем последний ID сообщения, если же у вас в коде будет настройка токена и chat_id, вызовите эту функцию для того чтоб получить последнее сообщение
    async_http_request('https://api.telegram.org/bot'..token..'/getUpdates?chat_id='..chat_id..'&offset=-1','',function(result)
        if result then
            local proc_table = decodeJson(result)
            if proc_table.ok then
                if #proc_table.result > 0 then
                    local res_table = proc_table.result[1]
                    if res_table then
                        updateid = res_table.update_id
                    end
                else
                    updateid = 1 -- тут зададим значение 1, если таблица будет пустая
                end
            end
        end
    end)
end





function main()
    while not isSampAvailable() do
        wait(0)
    end
    getLastUpdate() -- вызываем функцию получения последнего ID сообщения
    sampRegisterChatCommand('telegram',function() -- тестовая команда
        sampAddChatMessage('[Telegram] Отправляю тестовое сообщение',-1)
        sendTelegramNotification('Тестовое сообщение от '..sampGetPlayerNickname(select(2, sampGetPlayerIdByCharHandle(PLAYER_PED)))) -- отправляем сообщение юзеру
    end)
    lua_thread.create(get_telegram_updates) -- создаем нашу функцию получения сообщений от юзера
    while true do
        wait(0)
    end
end





function main()
    while not isSampAvailable() do wait(0) end
    sampAddChatMessage("{FFFFFF}[Train{00FF04}Bot]: {FFFFFF}Бот на машиниста электропоезда {00FFFB}успешно загрузился!",-1)
    sampAddChatMessage("{FFFFFF}[Train{00FF04}Bot]: {FFFFFF}Автор: Skalets",-1)
    sampAddChatMessage("{FFFFFF}[Train{00FF04}Bot]: {FFFFFF}Чтобы настроить бота напишите {00FF04}/botmenu", -1)
    sampAddChatMessage("{FFFFFF}[Train{00FF04}Bot]: {FFFFFF}Чтобы Включить/Выключить бота {00FF04}/botwork", -1)
    getLastUpdate()
    hwin = ffi.C.GetActiveWindow()
    lua_thread.create(get_telegram_updates)
    sampRegisterChatCommand("botwork", cmd_bot)
    sampRegisterChatCommand("botmenu", cmd_menu)
    if not mainIni.prices then inicfg.save(mainIni) end
    if slap then
        wait(60000)
        slap = false
    end
    while true do
        wait(0)
        
        if testCheat('MENU') then
            show_main_window.v = not show_main_window.v
        end
        if testCheat('Work') then
                active = not active
           if active then
             sampAddChatMessage("{00FFC1}[Cotton{00FF6C}Lien{00FF04}Bot]{FFFFFF}: Бот {00FF04}Включен!",-1)
             startime = os.time()
          else
             sampAddChatMessage("{00FFC1}[Cotton{00FF6C}Lien{00FF04}Bot]{FFFFFF} Бот {ff0000}Выключен!",-1)
         end
      end
    end
end

--------________________________________________________________________--------

imgui.SwitchContext()
local style = imgui.GetStyle()
local colors = style.Colors
local clr = imgui.Col
local ImVec4 = imgui.ImVec4
local ImVec2 = imgui.ImVec2

style.WindowPadding = ImVec2(15, 15)
style.WindowRounding = 6.0
style.FramePadding = ImVec2(5, 5)
style.FrameRounding = 4.0
style.ItemSpacing = ImVec2(12, 8)
style.ItemInnerSpacing = ImVec2(8, 6)
style.IndentSpacing = 25.0
style.ScrollbarSize = 15.0
style.ScrollbarRounding = 9.0
style.GrabMinSize = 5.0
style.GrabRounding = 3.0

colors[clr.Text] = ImVec4(0.80, 0.80, 0.83, 1.00)
colors[clr.TextDisabled] = ImVec4(0.24, 0.23, 0.29, 1.00)
colors[clr.WindowBg] = ImVec4(0.06, 0.05, 0.07, 1.00)
colors[clr.ChildWindowBg] = ImVec4(0.07, 0.07, 0.09, 1.00)
colors[clr.PopupBg] = ImVec4(0.07, 0.07, 0.09, 1.00)
colors[clr.Border] = ImVec4(0.80, 0.80, 0.83, 0.88)
colors[clr.BorderShadow] = ImVec4(0.92, 0.91, 0.88, 0.00)
colors[clr.FrameBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
colors[clr.FrameBgHovered] = ImVec4(0.24, 0.23, 0.29, 1.00)
colors[clr.FrameBgActive] = ImVec4(0.56, 0.56, 0.58, 1.00)
colors[clr.TitleBg] = ImVec4(0.76, 0.31, 0.00, 1.00)
colors[clr.TitleBgCollapsed] = ImVec4(1.00, 0.98, 0.95, 0.75)
colors[clr.TitleBgActive] = ImVec4(0.80, 0.33, 0.00, 1.00)
colors[clr.MenuBarBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
colors[clr.ScrollbarBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
colors[clr.ScrollbarGrab] = ImVec4(0.80, 0.80, 0.83, 0.31)
colors[clr.ScrollbarGrabHovered] = ImVec4(0.56, 0.56, 0.58, 1.00)
colors[clr.ScrollbarGrabActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
colors[clr.ComboBg] = ImVec4(0.19, 0.18, 0.21, 1.00)
colors[clr.CheckMark] = ImVec4(1.00, 0.42, 0.00, 0.53)
colors[clr.SliderGrab] = ImVec4(1.00, 0.42, 0.00, 0.53)
colors[clr.SliderGrabActive] = ImVec4(1.00, 0.42, 0.00, 1.00)
colors[clr.Button] = ImVec4(0.10, 0.09, 0.12, 1.00)
colors[clr.ButtonHovered] = ImVec4(0.24, 0.23, 0.29, 1.00)
colors[clr.ButtonActive] = ImVec4(0.56, 0.56, 0.58, 1.00)
colors[clr.Header] = ImVec4(0.10, 0.09, 0.12, 1.00)
colors[clr.HeaderHovered] = ImVec4(0.56, 0.56, 0.58, 1.00)
colors[clr.HeaderActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
colors[clr.ResizeGrip] = ImVec4(0.00, 0.00, 0.00, 0.00)
colors[clr.ResizeGripHovered] = ImVec4(0.56, 0.56, 0.58, 1.00)
colors[clr.ResizeGripActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
colors[clr.CloseButton] = ImVec4(0.40, 0.39, 0.38, 0.16)
colors[clr.CloseButtonHovered] = ImVec4(0.40, 0.39, 0.38, 0.39)
colors[clr.CloseButtonActive] = ImVec4(0.40, 0.39, 0.38, 1.00)
colors[clr.PlotLines] = ImVec4(0.40, 0.39, 0.38, 0.63)
colors[clr.PlotLinesHovered] = ImVec4(0.25, 1.00, 0.00, 1.00)
colors[clr.PlotHistogram] = ImVec4(0.40, 0.39, 0.38, 0.63)
colors[clr.PlotHistogramHovered] = ImVec4(0.25, 1.00, 0.00, 1.00)
colors[clr.TextSelectedBg] = ImVec4(0.25, 1.00, 0.00, 0.43)
colors[clr.ModalWindowDarkening] = ImVec4(1.00, 0.98, 0.95, 0.73)

--------________________________________________________________________--------




function cmd_imgui(arg)
    main_window_state.v = not main_window_state.v
    imgui.Process = main_window_state.v
end

function imgui.OnDrawFrame()
    imgui.Begin("Train Bot | by skalets")
    imgui.End()
end