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

Лебiгович

Известный
877
239
Не реагирует на нажатие после старта и поднимает только 0 пикап
вроде исправил

Lua:
require "lib.moonloader"
local delay = 1500
local isParsing = false

function main()
    while not isSampAvailable() do wait(0) end
    while true do
        wait(0)
        if wasKeyPressed(VK_DECIMAL) then
            isParsing = not isParsing
            if isParsing then
                print("Parser started")
                while isParsing do
                    for i = 0, 300 do
                        if not isParsing then break end -- Проверка перед каждой итерацией, чтобы корректно остановить парсер
                        wait(delay)
                        sampSendPickedUpPickup(i)
                    end
                end
                print("Parser stopped")
            else
                print("Parser stopped")
            end
        end
    end
end
 

Yans

Активный
190
32
вроде исправил

Lua:
require "lib.moonloader"
local delay = 1500
local isParsing = false

function main()
    while not isSampAvailable() do wait(0) end
    while true do
        wait(0)
        if wasKeyPressed(VK_DECIMAL) then
            isParsing = not isParsing
            if isParsing then
                print("Parser started")
                while isParsing do
                    for i = 0, 300 do
                        if not isParsing then break end -- Проверка перед каждой итерацией, чтобы корректно остановить парсер
                        wait(delay)
                        sampSendPickedUpPickup(i)
                    end
                end
                print("Parser stopped")
            else
                print("Parser stopped")
            end
        end
    end
end
Точно также, чуть исправил, парсит пикапы, но флудит в консоль SF и не останавливается

Парсер:
require "lib.moonloader"
local delay = 1500
local isParsing = false

function main()
    while not isSampAvailable() do wait(0) end
    while true do
        wait(0)
        if wasKeyPressed(VK_DECIMAL) then
            isParsing = not isParsing
            if isParsing then
                print("Parser started")
                while isParsing do
                    for i = 0, 300 do
                        if not isParsing then break end -- Проверка перед каждой итерацией, чтобы корректно остановить парсер
                        wait(delay)
                        sampSendPickedUpPickup(i)
                    end
                end
            end
        else
            print("Parser stopped")
        end
    end
end
 

Julimba

Участник
108
10
qq, обновляю булл переменную тоглбатона через ини, можно как то сделать, чтобы оно сразу и визуально менялось на активный тоглбатон, а не после перезагрузки скрипта?
 

triazov

Активный
250
57
qq, обновляю булл переменную тоглбатона через ини, можно как то сделать, чтобы оно сразу и визуально менялось на активный тоглбатон, а не после перезагрузки скрипта?
Сформулируй получше я ничего не понял
 

Julimba

Участник
108
10
Lua:
-- Main
hotkey.RegisterCallback('Stop', Key, function() -- mimhotkey
    bool = not bool
    if bool then
        cfg.bools.ST = true
    else
        cfg.bools.ST = false
    end
end)

local Stops = imgui.new.bool(cfg.bools.ST) -- бульная переменная тогла

-- Фрейм c тоглом
если я через мимхоткей поменяю переменную тогла на true, то она поменяется, но в фрейме тогл останется неактивным до момента перезагрузки скрипта, можно как то сделать, чтобы без перезагрузки менялось состояние тогла в фрейме
Сформулируй получше я ничего не понял
 

why ega

РП игрок
Модератор
2,550
2,242
Lua:
-- Main
hotkey.RegisterCallback('Stop', Key, function() -- mimhotkey
    bool = not bool
    if bool then
        cfg.bools.ST = true
    else
        cfg.bools.ST = false
    end
end)

local Stops = imgui.new.bool(cfg.bools.ST) -- бульная переменная тогла

-- Фрейм c тоглом
если я через мимхоткей поменяю переменную тогла на true, то она поменяется, но в фрейме тогл останется неактивным до момента перезагрузки скрипта, можно как то сделать, чтобы без перезагрузки менялось состояние тогла в фрейме
изменяй не только значение в конфиге, но и Stops.v
 
  • Влюблен
  • Эм
Реакции: Julimba и Akionka

tsunamiqq

Участник
429
16
Lua:
-- Библиотеки
local inicfg = require('inicfg')
local directIni = 'Script.ini'
local mainIni = inicfg.load(nil, directIni)
mainIni.settings = mainIni.settings or {}
mainIni.settings.radioButtonColorRed = mainIni.settings.radioButtonColorRed or false
mainIni.settings.selectedTheme = mainIni.settings.selectedTheme or 0
inicfg.save(mainIni, directIni)

-- В окне
local COLOR_SELECT = imgui.ImVec4(1, 0, 0, 1) -- Задай начальный цвет
if imgui.ColoredRadioButtonBool('##colorRed', settings.radioButtonColorRed[0], COLOR_SELECT) then
    Theme(settings.selectedTheme[0], COLOR_SELECT)
    mainIni.settings.radioButtonColorRed = not mainIni.settings.radioButtonColorRed
    settings.radioButtonColorRed[0] = mainIni.settings.radioButtonColorRed
end

-- Вне окна
function Theme(id, color, chroma_multiplier, accurate_shades)
    -- ... твой текущий код для изменения стиля и цветов ...

    if id == 0 then -- colors
        -- ... твой текущий код для установки цветов ...

        COLOR_SELECT = color
    end
end

-- Вне окна
function imgui.ColoredRadioButtonBool(label, state, color)
    imgui.PushStyleColor(imgui.Col.CheckMark, color)
    imgui.PushStyleColor(imgui.Col.FrameBg, color)
    imgui.PushStyleColor(imgui.Col.FrameBgActive, color)
    imgui.PushStyleColor(imgui.Col.FrameBgHovered, color)
    local radioButton = imgui.RadioButtonBool(label, state)
    imgui.PopStyleColor(4)
    return radioButton
end

-- Вне окна
function imgui.Combo(label, current_item, items)
    local changed, item = imgui.Combo(label, current_item[0], items)
    if changed then
        current_item[0] = item
    end
    return changed
end

-- Вне окна
local settings = {
    radioButtonColorRed = new.int(mainIni.settings.radioButtonColorRed),
    selectedTheme = new.int(mainIni.settings.selectedTheme)
}

попробуй
Цвет на RadioButton работает, а сохранение нет
 

Zaharushka

Участник
41
8
Как сделать так чтобы парсер останавливался при повторном нажатии?

Парсер:
require "lib.moonloader"
local delay = 1500

function main()
    while not isSampAvailable() do wait (0) end
    while true do
        wait (0)
        if wasKeyPressed(VK_DECIMAL) then
            for i = 0, 300 do wait(delay)
                sampSendPickedUpPickup(i)
            end
        end
    end
end
Пробуй
Lua:
require "lib.moonloader"

function msg(t)
    return sampAddChatMessage('{cecece} '..t, -1)
end

function main()
    repeat wait(0) until isSampAvailable()
    while true do wait(0)
        if wasKeyPressed(VK_DECIMAL) then
            wait(15); msg("Go")
            for i = 0, 300 do
                if TimeCount(stop) then
                    msg("Stop")
                    break
                end
                msg("PICKUP: {696969}"..i)
                sampSendPickedUpPickup(i)
            end
        end
    end
end

function TimeCount(stop)
    local maxNum = 1 -- 1 сек
    local startTime = os.clock()
    repeat
        local currentTime = os.clock()
        local elapsedTime = currentTime - startTime
        if wasKeyPressed(VK_DECIMAL) then
            return true -- Возвращаем true, чтобы прервать цикл в main()
        else
            wait(0)
        end
    until elapsedTime >= (maxNum * 1.5) -- тип что бы было 1500
end
 
  • Влюблен
Реакции: Yans

Julimba

Участник
108
10
qq, это можно как то более грамотно написать? Чтобы не так больно было смотреть

Lua:
hotkey.RegisterCallback('KList', KList, function()
    KL = not KL
    if KL and not cfg.bools.KL then
        cfg.bools.KL = true
        save()
    else
        cfg.bools.KL = false
        save()
    end
end)
 
  • Bug
Реакции: Dmitry Code

tsunamiqq

Участник
429
16
Как сделать сохранение темы?
Попытался сделать таким способом, не получилось.

Lua:
--Библиотеки

--Вне окна
local inicfg = require('inicfg')
local directIni = 'Script.ini'
local mainIni = inicfg.load(inicfg.load({
    settings = {
        radioButtonColorRed = false
        selectedTheme = selectedTheme or 0
    }
}, directIni))
inicfg.save(mainIni, directIni)
--Вне окна
local settings = {
    radioButtonColorRed = new.int(mainIni.settings.radioButtonColorRed),
    selectedTheme = new.int(mainIni.settings.selectedTheme)
}

--В окне
local COLOR_SELECT = imgui.ImVec4(1, 0, 0, 1)
if imgui.ColoredRadioButtonBool('##colorRed', settings.radioButtonColorRed[0], COLOR_SELECT) then
    Theme(settings.selectedTheme[0], COLOR_SELECT)
    mainIni.settings.radioButtonColorRed = not mainIni.settings.radioButtonColorRed
    settings.radioButtonColorRed[0] = mainIni.settings.radioButtonColorRed
end

--Вне окна
function imgui.ColoredRadioButtonBool(label, state, color)
    imgui.PushStyleColor(imgui.Col.CheckMark, color)
    imgui.PushStyleColor(imgui.Col.FrameBg, color)
    imgui.PushStyleColor(imgui.Col.FrameBgActive, color)
    imgui.PushStyleColor(imgui.Col.FrameBgHovered, color)
    local radioButton = imgui.RadioButtonBool(label, state)
    imgui.PopStyleColor(4)
    return radioButton
end

--Вне окна
function Theme(id, color, chroma_multiplier, accurate_shades)
    local vec2, vec4 = imgui.ImVec2, imgui.ImVec4
    imgui.SwitchContext()
    local style = imgui.GetStyle()
    local colors = style.Colors
    local flags = imgui.Col
 
    do -- style
        --==[ STYLE ]==--
        imgui.GetStyle().WindowPadding = imgui.ImVec2(5, 5)
        imgui.GetStyle().FramePadding = imgui.ImVec2(5, 5)
        imgui.GetStyle().ItemSpacing = imgui.ImVec2(5, 5)
        imgui.GetStyle().ItemInnerSpacing = imgui.ImVec2(2, 2)
        imgui.GetStyle().TouchExtraPadding = imgui.ImVec2(0, 0)
        imgui.GetStyle().IndentSpacing = 0
        imgui.GetStyle().ScrollbarSize = 10
        imgui.GetStyle().GrabMinSize = 10
        --==[ ROUNDING ]==--
        imgui.GetStyle().WindowRounding = 8
        imgui.GetStyle().ChildRounding = 8
        imgui.GetStyle().FrameRounding = 5
        imgui.GetStyle().PopupRounding = 8
        imgui.GetStyle().ScrollbarRounding = 8
        imgui.GetStyle().GrabRounding = 8
        imgui.GetStyle().TabRounding = 8
        --==[ ALIGN ]==--
        imgui.GetStyle().WindowTitleAlign = imgui.ImVec2(0.5, 0.5)
        imgui.GetStyle().ButtonTextAlign = imgui.ImVec2(0.5, 0.5)
        imgui.GetStyle().SelectableTextAlign = imgui.ImVec2(0.5, 0.5)
    end
    local palette = monet.buildColors(id, color, chroma_multiplier, accurate_shades)
    if id == 0 then -- colors
        colors[imgui.Col.WindowBg] = imgui.ImVec4(0.14, 0.12, 0.16, 1.00)
        colors[imgui.Col.ChildBg] = imgui.ImVec4(0.30, 0.20, 0.39, 0.00)
        colors[imgui.Col.PopupBg] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.Border] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.BorderShadow] = imgui.ImVec4(0.00, 0.00, 0.00, 0.00)
        colors[imgui.Col.FrameBg] = imgui.ImVec4(0.28, 0.27, 0.27, 0.28)
        colors[imgui.Col.FrameBgHovered] = imgui.ImVec4(0.41, 0.19, 0.63, 0.68)
        colors[imgui.Col.FrameBgActive] = imgui.ImVec4(0.41, 0.19, 0.63, 1.00)
        colors[imgui.Col.TitleBg] = imgui.ImVec4(0.41, 0.19, 0.63, 0.45)
        colors[imgui.Col.TitleBgCollapsed] = imgui.ImVec4(0.41, 0.19, 0.63, 0.35)
        colors[imgui.Col.TitleBgActive] = imgui.ImVec4(0.41, 0.19, 0.63, 0.78)
        colors[imgui.Col.MenuBarBg] = imgui.ImVec4(0.30, 0.20, 0.39, 0.57)
        colors[imgui.Col.ScrollbarBg] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.ScrollbarGrab] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.ScrollbarGrabHovered] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.ScrollbarGrabActive] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.CheckMark] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.SliderGrab] = imgui.ImVec4(0.41, 0.19, 0.63, 0.24)
        colors[imgui.Col.SliderGrabActive] = imgui.ImVec4(0.41, 0.19, 0.63, 1.00)
        colors[imgui.Col.Button] = imgui.ImVec4(0.84, 0.01, 0.06, 0.84)
        colors[imgui.Col.ButtonHovered] = imgui.ImVec4(1, 0, 0.07, 1)
        colors[imgui.Col.ButtonActive] = imgui.ImVec4(0.84, 0.01, 0.06, 0.8)
        colors[imgui.Col.Header] = imgui.ImVec4(0.41, 0.19, 0.63, 0.76)
        colors[imgui.Col.HeaderHovered] = imgui.ImVec4(0.41, 0.19, 0.63, 0.86)
        colors[imgui.Col.HeaderActive] = imgui.ImVec4(0.41, 0.19, 0.63, 1.00)
        colors[imgui.Col.ResizeGrip] = imgui.ImVec4(0.41, 0.19, 0.63, 0.20)
        colors[imgui.Col.ResizeGripHovered] = imgui.ImVec4(0.41, 0.19, 0.63, 0.78)
        colors[imgui.Col.ResizeGripActive] = imgui.ImVec4(0.41, 0.19, 0.63, 1.00)
        colors[imgui.Col.PlotLines] = imgui.ImVec4(0.89, 0.85, 0.92, 0.63)
        colors[imgui.Col.PlotLinesHovered] = imgui.ImVec4(0.41, 0.19, 0.63, 1.00)
        colors[imgui.Col.PlotHistogram] = imgui.ImVec4(0.89, 0.85, 0.92, 0.63)
        colors[imgui.Col.PlotHistogramHovered] = imgui.ImVec4(0.41, 0.19, 0.63, 1.00)
        colors[imgui.Col.TextSelectedBg] = imgui.ImVec4(0.41, 0.19, 0.63, 0.43)
     
        COLOR_SELECT = color
    end
    if id == 1 then -- colors
 
        colors[flags.Text] = to_vec4(palette.neutral1.color_100)
        colors[flags.WindowBg] = to_vec4(palette.accent1.color_800)
        colors[flags.ChildBg] = to_vec4(palette.accent1.color_800)
        colors[flags.PopupBg] = to_vec4(palette.accent2.color_700)
        colors[flags.Border] = to_vec4(palette.neutral1.color_600)
        colors[flags.BorderShadow] = to_vec4(palette.neutral2.color_800)
        colors[flags.FrameBg] = to_vec4(palette.accent1.color_600)
        colors[flags.FrameBgHovered] = to_vec4(palette.accent1.color_600)
        colors[flags.FrameBgActive] = to_vec4(palette.accent1.color_500)
        colors[flags.TitleBgActive] = to_vec4(palette.accent1.color_700)
        colors[flags.ScrollbarBg] = to_vec4(palette.accent1.color_700)
        colors[flags.ScrollbarGrab] = to_vec4(palette.accent2.color_500)
        colors[flags.ScrollbarGrabHovered] = to_vec4(palette.accent2.color_400)
        colors[flags.ScrollbarGrabActive] = to_vec4(palette.accent2.color_300)
        colors[flags.CheckMark] = to_vec4(palette.neutral1.color_100)
        colors[flags.SliderGrab] = to_vec4(palette.accent2.color_400)
        colors[flags.SliderGrabActive] = to_vec4(palette.accent2.color_300)
        colors[flags.Button] = to_vec4(palette.accent1.color_600)
        colors[flags.ButtonHovered] = to_vec4(palette.accent1.color_500)
        colors[flags.ButtonActive] = to_vec4(palette.accent1.color_600)
        colors[flags.Header] = to_vec4(palette.accent1.color_700)
        colors[flags.HeaderHovered] = to_vec4(palette.accent1.color_600)
        colors[flags.HeaderActive] = to_vec4(palette.accent1.color_500)
        colors[flags.Separator] = to_vec4(palette.accent2.color_100)
        colors[flags.SeparatorHovered] = to_vec4(palette.accent2.color_200)
        colors[flags.SeparatorActive] = to_vec4(palette.accent2.color_100)
        colors[flags.ResizeGrip] = to_vec4(palette.accent2.color_800)
        colors[flags.ResizeGripHovered] = to_vec4(palette.accent2.color_700)
        colors[flags.ResizeGripActive] = to_vec4(palette.accent2.color_600)
        colors[flags.Tab] = to_vec4(palette.accent1.color_600)
        colors[flags.TabHovered] = to_vec4(palette.accent1.color_500)
        colors[flags.TabActive] = to_vec4(palette.accent1.color_400)
        colors[flags.PlotLines] = to_vec4(palette.accent3.color_200)
        colors[flags.PlotLinesHovered] = to_vec4(palette.accent3.color_100)
        colors[flags.PlotHistogram] = to_vec4(palette.accent3.color_200)
        colors[flags.PlotHistogramHovered] = to_vec4(palette.accent3.color_100)
        colors[flags.DragDropTarget] = to_vec4(palette.accent3.color_600)
      
        COLOR_SELECT = color
     end
 end
 

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
qq, это можно как то более грамотно написать? Чтобы не так больно было смотреть

Lua:
hotkey.RegisterCallback('KList', KList, function()
    KL = not KL
    if KL and not cfg.bools.KL then
        cfg.bools.KL = true
        save()
    else
        cfg.bools.KL = false
        save()
    end
end)
Lua:
hotkey.RegisterCallback('KList', KList, function()
    cfg.bools.KL = not cfg.bools.KL
    save()
end)
 
  • Нравится
Реакции: Julimba

tsunamiqq

Участник
429
16
Как этот текст - [VIP ADV] {FFFFFF}Corrado_Soprano[322]: Куплю Брабус 700 ало 2522238 | сделать в text:find
Я уже разные способы перепробовал, вот один из них
if text:find('[VIP ADV] %{......%}%w+_%w+%[%d+%]: .+') then return false end
 

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
Как этот текст - [VIP ADV] {FFFFFF}Corrado_Soprano[322]: Куплю Брабус 700 ало 2522238 | сделать в text:find
Я уже разные способы перепробовал, вот один из них
if text:find('[VIP ADV] %{......%}%w+_%w+%[%d+%]: .+') then return false end
%[VIP ADV%] %{......%}.+%[%d+%]: .+
 
  • Нравится
Реакции: tsunamiqq

Карен

Участник
112
17
Пацаны дарова, как узнать на какое авто показывает чекпоинт?
1693512062836.png

Допустим чекпоинт показывает на Dodo, как узнать его handle?
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,777
11,225
Пацаны дарова, как узнать на какое авто показывает чекпоинт?Посмотреть вложение 213911
Допустим чекпоинт показывает на Dodo, как узнать его handle?
Lua:
---@param x number
---@param y number
---@param z number
---@return boolean Success
---@return { handle: any, dist: number }
local function getNearestVehicleFromPoint(x, y, z)
    local result = { handle = nil, dist = math.huge };
    for _, veh in pairs(getAllVehicles()) do
        local dist = getDistanceBetweenCoords3d(x, y, z, getCarCoordinates(veh));
        if (dist < result.dist) then
            result = {
                handle = veh,
                dist = dist
            };
        end
    end
    return result.handle ~= nil, result;
end