Вопросы по 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
 
Последнее редактирование:

Izvinisb

Известный
Проверенный
963
601
Как сделать запрет на сворачивание imgui окна?
Как сделать запрет на сворачивание imgui окна?
Lua:
imgui.WindowFlags.NoCollapse
 
  • Нравится
Реакции: CaJlaT

Tak

Известный
178
70
Как сделать чтобы окно imgui было активным постоянно, пока действует условие(например галочка в чекбоксе), даже если основное окно закрыто?
Основное окно можно закрыть через if, а на дополнительном просто выключить курсор, при этом включив управление персонажем.

Lua:
function imgui.OnDrawFrame()
  -- первое окно
  imgui.Begin('Window 1')
  imgui.Text('Text 123')
  imgui.End()

  -- второе окно
  imgui.Begin('Window 2')
  imgui.Text('Text 321')
  imgui.End()
end
 

Cod

Участник
117
15
Помогите решить.
Lua:
local array_1 = {10, 2, 244, 25, 100, 5, 1}
local array_2 = {2, 10, 25, 244}
2 массива, нужно чтобы скрипт выводил: 100, 5, 1, . Т.е те, которых нет во 2 массиве, но в 1 есть
 
Последнее редактирование:

Tak

Известный
178
70
Помогите решить.
Lua:
local array_1 = {10, 2, 244, 25, 100, 5, 1}
local array_2 = {122, 24, 10, 2}
2 массива, нужно чтобы скрипт выводил: 10, 2. Т.е те, которых нет во 2 массиве, но в 1 есть
Можно взять первое значение из первого массива, сравнить со всеми значениями второго массива, что-то сделать если ==. Взять второе значение из первого массива, и снова пройтись по второму массиву.
 

Fott

Простреленный
3,470
2,387
Как сделать выполнение чего либо после спавна игрока ( тоесть игрок умер, или же админ заспавнил)
 

Izvinisb

Известный
Проверенный
963
601
Помогите решить.
Lua:
local array_1 = {10, 2, 244, 25, 100, 5, 1}
local array_2 = {122, 24, 10, 2}
2 массива, нужно чтобы скрипт выводил: 10, 2. Т.е те, которых нет во 2 массиве, но в 1 есть
Всмысле 10, 2 если эти цифры есть как в первом массиве так и во втором
 

tlwsn

Известный
537
85
Как можно скрыть серверное сообщение в чате кроме как return false в хуке?
 

K.Reed

Новичок
1
0
Доброго времени суток.
Проблема следующая, открываю я диаолог с помощью команды /dokl, при клике по строке, перехожу в нужный мне диалог, к примеру 1338, но при клике там по строкам, диалог просто закрывается и никаких действий не происходит. Если же вызвать эти дилоги отдельно (сопр, патруль), то все отлично работает.

Код:
function dokl()
sampShowDialog(3001, "ВМО+ | Меню докладов", "тест\ntest", "Ок", "Отмена", 2)
lua_thread.create(doklcheck)
end

function doklcheck()
while sampIsDialogActive() do
wait(0)
local result, button, listitem = sampHasDialogRespond(3001)
if result then
if button == 1 then
if listitem == 0 then
sampShowDialog(1338, "ВМО+ | Меню сопровождения", "1. Доклад о начале сопровождения {FF0000}(В хаммере)\n2. Докдал о начале сопровождения {FF0000}(В грузовике)\n3. Доклад о завершении сопровождения {FF0000}(В хаммере)\n4. Доклад о завершении сопровождения{FF0000}(В грузовике)\n5. Мегафон {7CFC00}(Не мешать движению колонны)", "Ок", "Отмена", 2)
local result, button, listitem = sampHasDialogRespond(1338)
end
if listitem == 1 then
sampShowDialog(1337, "ВМО+ | Patrol", "1. Доклад о начале патруля\n2. Доклад о ведении патруля\n3. Доклад о байкерах в секторе\n4. Доклад об оборах в секторе \n5. Доклад о нейтрализации вражеских единиц\n6. Мегафон покинуть территорию\n7. Крикнуть покинуть территорию\n8. Доклад о завершении патруля ", "Ок", "Отмена", 2)
local result, button, listitem = sampHasDialogRespond(1337)
end
end
end
end
end

Ниже код этих диалогов

Lua:
function sopr()
    sampShowDialog(1338, "ВМО+ | Меню сопровождения", "1. Доклад о начале сопровождения {FF0000}(В хаммере)\n2. Докдал о начале сопровождения {FF0000}(В грузовике)\n3. Доклад о завершении сопровождения {FF0000}(В хаммере)\n4. Доклад о завершении сопровождения{FF0000}(В грузовике)\n5. Мегафон {7CFC00}(Не мешать движению колонны)", "Ок", "Отмена", 2)
    lua_thread.create(soprchecker)
end

function soprchecker()
        while sampIsDialogActive() do
        wait(0)
        local result, button, listitem = sampHasDialogRespond(1338)
        if result then
            if button == 1 then
                if listitem == 0 then
            sampSendChat(TeamTag .. "Начали сопровождение колонны снабжения. Напарник: #nap#")
        end            
        if listitem == 1 then
            sampSendChat(TeamTag .."Начал сопровождение колонны снабжения на пассажирском. Водитель: #nap#")
        end        
        if listitem == 2 then
            sampSendChat(TeamTag .."Завершили сопровождение колонны снабжения. Напарник: #nap#")
        end    
        if listitem == 3 then
            sampSendChat(TeamTag .."Завершил сопровождение колонны снабжения. Водитель: #nap#")
        end        
        if listitem == 4 then
            sampSendChat("/m [LVa] Ведется сопровождение колонны снабжения!")
            wait(800)
            sampSendChat("/m [LVa] Не препятствуйте движению колонны или мы откроем огонь на поражение!")
        end
    end
end
end
end    

function patrulhelper()
    sampShowDialog(1337, "ВМО+ | Patrol", "1. Доклад о начале патруля\n2. Доклад о ведении патруля\n3. Доклад о байкерах в секторе\n4. Доклад об оборах в секторе \n5. Доклад о нейтрализации вражеских единиц\n6. Мегафон покинуть территорию\n7. Крикнуть покинуть территорию\n8. Доклад о завершении патруля ", "Ок", "Отмена", 2)
    lua_thread.create(checker)
end

function checker()
    while sampIsDialogActive() do
    wait(0)
    local result, button, listitem = sampHasDialogRespond(1337)
    if result then
        if button == 1 then    
            if listitem == 0 then
        sampSendChat(TeamTag .."Начали патруль окрестностей LV Army. Напарник: #nap#")
    end    
    if listitem == 1 then
        sampSendChat(TeamTag .."Ведем патруль окрестностей LV Army, в секторе: ".. SquareName .. ". Напарник: #nap#")
    end    
    if listitem == 2 then
        sampSendChat(TeamTag .."В секторе ".. SquareName .. ". Замечены байкеры")
    end    
    if listitem == 3 then
        sampSendChat(TeamTag .."В секторе ".. SquareName .. ". Замечены оборы")
    end    
    if listitem == 4 then
        sampSendChat(TeamTag .."Вражеские единицы нейтрализованы в секторе: " .. SquareName)
    end    
    if listitem == 5 then
        sampSendChat("/m [LVa] Немедленно покиньте территорию армии Las Venturas")
        wait(800)
        sampSendChat("/m [LVa] В противном случае мы будем вынуждены открыть огонь")
    end    
    if listitem == 6 then
        sampSendChat("/s Немедленно покиньте территорию армии Las Venturas")
        wait(800)
        sampSendChat("/s В противном случае мы будем вынуждены открыть огонь")
    end    
    if listitem == 7 then
        sampSendChat(TeamTag .. "Завершили патруль окрестностей LV Army. Напарник: #nap#")
                end
            end
        end
    end
end
 

neverlane

t.me/neverlane00
Друг
1,010
1,162
Доброго времени суток.
Проблема следующая, открываю я диаолог с помощью команды /dokl, при клике по строке, перехожу в нужный мне диалог, к примеру 1338, но при клике там по строкам, диалог просто закрывается и никаких действий не происходит. Если же вызвать эти дилоги отдельно (сопр, патруль), то все отлично работает.

Код:
function dokl()
sampShowDialog(3001, "ВМО+ | Меню докладов", "тест\ntest", "Ок", "Отмена", 2)
lua_thread.create(doklcheck)
end

function doklcheck()
while sampIsDialogActive() do
wait(0)
local result, button, listitem = sampHasDialogRespond(3001)
if result then
if button == 1 then
if listitem == 0 then
sampShowDialog(1338, "ВМО+ | Меню сопровождения", "1. Доклад о начале сопровождения {FF0000}(В хаммере)\n2. Докдал о начале сопровождения {FF0000}(В грузовике)\n3. Доклад о завершении сопровождения {FF0000}(В хаммере)\n4. Доклад о завершении сопровождения{FF0000}(В грузовике)\n5. Мегафон {7CFC00}(Не мешать движению колонны)", "Ок", "Отмена", 2)
local result, button, listitem = sampHasDialogRespond(1338)
end
if listitem == 1 then
sampShowDialog(1337, "ВМО+ | Patrol", "1. Доклад о начале патруля\n2. Доклад о ведении патруля\n3. Доклад о байкерах в секторе\n4. Доклад об оборах в секторе \n5. Доклад о нейтрализации вражеских единиц\n6. Мегафон покинуть территорию\n7. Крикнуть покинуть территорию\n8. Доклад о завершении патруля ", "Ок", "Отмена", 2)
local result, button, listitem = sampHasDialogRespond(1337)
end
end
end
end
end

Ниже код этих диалогов

Lua:
function sopr()
    sampShowDialog(1338, "ВМО+ | Меню сопровождения", "1. Доклад о начале сопровождения {FF0000}(В хаммере)\n2. Докдал о начале сопровождения {FF0000}(В грузовике)\n3. Доклад о завершении сопровождения {FF0000}(В хаммере)\n4. Доклад о завершении сопровождения{FF0000}(В грузовике)\n5. Мегафон {7CFC00}(Не мешать движению колонны)", "Ок", "Отмена", 2)
    lua_thread.create(soprchecker)
end

function soprchecker()
        while sampIsDialogActive() do
        wait(0)
        local result, button, listitem = sampHasDialogRespond(1338)
        if result then
            if button == 1 then
                if listitem == 0 then
            sampSendChat(TeamTag .. "Начали сопровождение колонны снабжения. Напарник: #nap#")
        end           
        if listitem == 1 then
            sampSendChat(TeamTag .."Начал сопровождение колонны снабжения на пассажирском. Водитель: #nap#")
        end       
        if listitem == 2 then
            sampSendChat(TeamTag .."Завершили сопровождение колонны снабжения. Напарник: #nap#")
        end   
        if listitem == 3 then
            sampSendChat(TeamTag .."Завершил сопровождение колонны снабжения. Водитель: #nap#")
        end       
        if listitem == 4 then
            sampSendChat("/m [LVa] Ведется сопровождение колонны снабжения!")
            wait(800)
            sampSendChat("/m [LVa] Не препятствуйте движению колонны или мы откроем огонь на поражение!")
        end
    end
end
end
end   

function patrulhelper()
    sampShowDialog(1337, "ВМО+ | Patrol", "1. Доклад о начале патруля\n2. Доклад о ведении патруля\n3. Доклад о байкерах в секторе\n4. Доклад об оборах в секторе \n5. Доклад о нейтрализации вражеских единиц\n6. Мегафон покинуть территорию\n7. Крикнуть покинуть территорию\n8. Доклад о завершении патруля ", "Ок", "Отмена", 2)
    lua_thread.create(checker)
end

function checker()
    while sampIsDialogActive() do
    wait(0)
    local result, button, listitem = sampHasDialogRespond(1337)
    if result then
        if button == 1 then   
            if listitem == 0 then
        sampSendChat(TeamTag .."Начали патруль окрестностей LV Army. Напарник: #nap#")
    end   
    if listitem == 1 then
        sampSendChat(TeamTag .."Ведем патруль окрестностей LV Army, в секторе: ".. SquareName .. ". Напарник: #nap#")
    end   
    if listitem == 2 then
        sampSendChat(TeamTag .."В секторе ".. SquareName .. ". Замечены байкеры")
    end   
    if listitem == 3 then
        sampSendChat(TeamTag .."В секторе ".. SquareName .. ". Замечены оборы")
    end   
    if listitem == 4 then
        sampSendChat(TeamTag .."Вражеские единицы нейтрализованы в секторе: " .. SquareName)
    end   
    if listitem == 5 then
        sampSendChat("/m [LVa] Немедленно покиньте территорию армии Las Venturas")
        wait(800)
        sampSendChat("/m [LVa] В противном случае мы будем вынуждены открыть огонь")
    end   
    if listitem == 6 then
        sampSendChat("/s Немедленно покиньте территорию армии Las Venturas")
        wait(800)
        sampSendChat("/s В противном случае мы будем вынуждены открыть огонь")
    end   
    if listitem == 7 then
        sampSendChat(TeamTag .. "Завершили патруль окрестностей LV Army. Напарник: #nap#")
                end
            end
        end
    end
end
Lua:
function sopr()
    sampShowDialog(1338, "ВМО+ | Меню сопровождения", "1. Доклад о начале сопровождения {FF0000}(В хаммере)\n2. Докдал о начале сопровождения {FF0000}(В грузовике)\n3. Доклад о завершении сопровождения {FF0000}(В хаммере)\n4. Доклад о завершении сопровождения{FF0000}(В грузовике)\n5. Мегафон {7CFC00}(Не мешать движению колонны)", "Ок", "Отмена", 2)
    lua_thread.create(soprchecker)
end

function soprchecker()
        while sampIsDialogActive() do
        wait(0)
        end
        local result, button, listitem = sampHasDialogRespond(1338)
        if result then
            if button == 1 then
                if listitem == 0 then
            sampSendChat(TeamTag .. "Начали сопровождение колонны снабжения. Напарник: #nap#")
        end            
        if listitem == 1 then
            sampSendChat(TeamTag .."Начал сопровождение колонны снабжения на пассажирском. Водитель: #nap#")
        end        
        if listitem == 2 then
            sampSendChat(TeamTag .."Завершили сопровождение колонны снабжения. Напарник: #nap#")
        end    
        if listitem == 3 then
            sampSendChat(TeamTag .."Завершил сопровождение колонны снабжения. Водитель: #nap#")
        end        
        if listitem == 4 then
            sampSendChat("/m [LVa] Ведется сопровождение колонны снабжения!")
            wait(800)
            sampSendChat("/m [LVa] Не препятствуйте движению колонны или мы откроем огонь на поражение!")
        end
    end
end
end    

function patrulhelper()
    sampShowDialog(1337, "ВМО+ | Patrol", "1. Доклад о начале патруля\n2. Доклад о ведении патруля\n3. Доклад о байкерах в секторе\n4. Доклад об оборах в секторе \n5. Доклад о нейтрализации вражеских единиц\n6. Мегафон покинуть территорию\n7. Крикнуть покинуть территорию\n8. Доклад о завершении патруля ", "Ок", "Отмена", 2)
    lua_thread.create(checker)
end

function checker()
    while sampIsDialogActive() do
    wait(0)
    end
    local result, button, listitem = sampHasDialogRespond(1337)
    if result then
        if button == 1 then    
            if listitem == 0 then
        sampSendChat(TeamTag .."Начали патруль окрестностей LV Army. Напарник: #nap#")
    end    
    if listitem == 1 then
        sampSendChat(TeamTag .."Ведем патруль окрестностей LV Army, в секторе: ".. SquareName .. ". Напарник: #nap#")
    end    
    if listitem == 2 then
        sampSendChat(TeamTag .."В секторе ".. SquareName .. ". Замечены байкеры")
    end    
    if listitem == 3 then
        sampSendChat(TeamTag .."В секторе ".. SquareName .. ". Замечены оборы")
    end    
    if listitem == 4 then
        sampSendChat(TeamTag .."Вражеские единицы нейтрализованы в секторе: " .. SquareName)
    end    
    if listitem == 5 then
        sampSendChat("/m [LVa] Немедленно покиньте территорию армии Las Venturas")
        wait(800)
        sampSendChat("/m [LVa] В противном случае мы будем вынуждены открыть огонь")
    end    
    if listitem == 6 then
        sampSendChat("/s Немедленно покиньте территорию армии Las Venturas")
        wait(800)
        sampSendChat("/s В противном случае мы будем вынуждены открыть огонь")
    end    
    if listitem == 7 then
        sampSendChat(TeamTag .. "Завершили патруль окрестностей LV Army. Напарник: #nap#")
                end
            end
        end
end
попробуй
 

Tak

Известный
178
70
Помогите решить.
Lua:
local array_1 = {10, 2, 244, 25, 100, 5, 1}
local array_2 = {2, 10, 25, 244}
2 массива, нужно чтобы скрипт выводил: 100, 5, 1, . Т.е те, которых нет во 2 массиве, но в 1 есть
Может есть способ проще, но я как вижу, так и сделал =)

Берет первое значение из первого массива, и начинает проходить по всем значениям из второго массива. Если вдруг нашел совпадение overlap = true, когда доходит до последнего значения во втором массиве, т.е. это когда b == #two, прроверяет совпадения (overlap), и если false - записывает первое значение из первого массива в total = {}. И так повторяет с каждым числом из первого массива.

Если вставить в .lua и запустить samp, то в консоли sampfuncs`а будут значения из массива total
Lua:
function main()
    local one = {32, 85, 5, 3, 2, 1, 12, 53, 78} -- первый
    local two = {12, 56, 32, 23, 85, 78} -- второй
    local total = {}              -- тут будут все числа которых нет во втором массиве
    -- 5; 3; 2; 1; 53;

    for i = 1, #one do
        local overlap = false
        for b = 1, #two do
            if one[i] == two[b] then
                overlap = true
            end
            if b == #two and overlap == false then
                total[#total + 1] = one[i]
            end
        end
    end
    for z = 1, #total do
        print(total[z])
    end
end
Подскажите пожалуйста, как заголовок окна imgui.Begin выровнять по центру? (Когда-то давно находил, а сейчас найти не могу =( )
 
Последнее редактирование:
  • Нравится
Реакции: Cod

Cod

Участник
117
15
Может есть способ проще, но я как вижу, так и сделал =)

Берет первое значение из первого массива, и начинает проходить по всем значениям из второго массива. Если вдруг нашел совпадение overlap = true, когда доходит до последнего значения во втором массиве, т.е. это когда b == #two, прроверяет совпадения (overlap), и если false - записывает первое значение из первого массива в total = {}. И так повторяет с каждым числом из первого массива.

Если вставить в .lua и запустить samp, то в консоли sampfuncs`а будут значения из массива total
Lua:
function main()
    local one = {32, 85, 5, 3, 2, 1, 12, 53, 78} -- первый
    local two = {12, 56, 32, 23, 85, 78} -- второй
    local total = {}              -- тут будут все числа которых нет во втором массиве
    -- 5; 3; 2; 1; 53;

    for i = 1, #one do
        local overlap = false
        for b = 1, #two do
            if one[i] == two[b] then
                overlap = true
            end
            if b == #two and overlap == false then
                total[#total + 1] = one[i]
            end
        end
    end
    for z = 1, #total do
        print(total[z])
    end
end
Подскажите пожалуйста, как заголовок окна imgui.Begin выровнять по центру? (Когда-то давно находил, а сейчас найти не могу =( )
Спасибо, попробую.
Lua:
style.WindowTitleAlign = imgui.ImVec2(0.50, 0.40) -- лево\право | верх\низ
-- в apply_custom_style
 
  • Нравится
Реакции: Tak

Double Tap Inside

Известный
Проверенный
1,916
1,261
Как сделать плавный скролинг на колесо мышки в ImGui? Такой как в Chrome или Firefox.
 

p0pc0rn

Участник
32
2
Почему оно не работает? % поставил, все равно не отвечает
Lua:
if text:find('1%.1') then
    lua_thread.create(function()
        wait(2000)
        sampSendChat('1 * 1 = 1')
    end)
end

Lua:
if imgui.Button(u8'JAIL', imgui.ImVec2(100,0)) then
                imgui.OpenPopup(u8"JAIL")
            end
            if imgui.BeginPopupModal(u8"JAIL", _, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoMove) then
                bsize = imgui.ImVec2(125, 0)
                if imgui.Button(u8'Своя причина', bsize) then
                    sampSetChatInputEnabled(true)
                    sampSetChatInputText('/jail '..spec_id..' ')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'ДМ', bsize) then
                    sd('/jail '..spec_id..' 10 ДМ')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'ДБ', bsize) then
                    sd('/jail '..spec_id..' 10 ДБ')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'ДМ ЗЗ', bsize) then
                    sd('/jail '..spec_id..' 10 ДМ ЗЗ')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'ПГ', bsize) then
                    sd('/jail '..spec_id..' 10 ПГ')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'СК', bsize) then
                    sd('/jail '..spec_id..' 10 СК')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'ТК', bsize) then
                    sd('/jail '..spec_id..' 5 ТК')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'Чит', bsize) then
                    sd('/jail '..spec_id..' 30 Чит')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'Коп Гетто', bsize) then
                    sd('/jail '..spec_id..' 10 Коп в Гетто')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'НРП Коп', bsize) then
                    sd('/jail '..spec_id..' 15 НонРП коп')
                    imgui.CloseCurrentPopup()
                end
                if imgui.Button(u8'Закрыть', bsize) then
                    imgui.CloseCurrentPopup()
                end
                imgui.EndPopup()
            end

Lua:
function samp.onBulletSync(playerid, data)
        if data.target.x == -1 or data.target.y == -1 or data.target.z == -1 then
            return true
        end
        BulletSync.lastId = BulletSync.lastId + 1
        if BulletSync.lastId < 1 or BulletSync.lastId > BulletSync.maxLines then
            BulletSync.lastId = 1
        end
        local id = BulletSync.lastId
        BulletSync[id].enable = true
        BulletSync[id].tType = data.targetType
        BulletSync[id].time = os.time() + 15
        BulletSync[id].o.x, BulletSync[id].o.y, BulletSync[id].o.z = data.origin.x, data.origin.y, data.origin.z
        BulletSync[id].t.x, BulletSync[id].t.y, BulletSync[id].t.z = data.target.x, data.target.y, data.target.z
end

-- while true do, рендерим
local oTime = os.time()
        if traic then
            for i = 1, BulletSync.maxLines do
                if BulletSync[i].enable == true and oTime <= BulletSync[i].time then
                    local o, t = BulletSync[i].o, BulletSync[i].t
                    if isPointOnScreen(o.x, o.y, o.z) and
                       isPointOnScreen(t.x, t.y, t.z) then
                        local sx, sy = convert3DCoordsToScreen(o.x, o.y, o.z)
                        local fx, fy = convert3DCoordsToScreen(t.x, t.y, t.z)
                        renderDrawLine(sx, sy, fx, fy, 1, BulletSync[i].tType == 0 and 0xFFFFFFFF or 0xFFFF0000 or 0xFF006400)
                        renderDrawPolygon(fx, fy-1, 3, 3, 4.0, 10, BulletSync[i].tType == 0 and 0xFFFFFFFF or 0xFFFF0000 or 0xFF006400)
                    end
                end
            end
        end

Мне бы не просто код трасеров на луа, а объяснить как оно работает) Это я и сам уже рыскал