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

Andrinall

Известный
701
518
local logbox = imgui.new.char[4097](u8(tostring(logtext)))

local logtext = ""
Если в коде так как ты скинул - то тут твой косяк.
Переменная logbox,а передаёшь ты в функцию logBox, то есть nil - из-за чего и краш.
Следи за регистром символов.

1676735780752.png


Lua:
local imgui = require 'mimgui'
local ffi = require 'ffi'

local logtext = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11" }
local logBox = new.char[4097](table.concat(logtext, "\n"))

local wnd = imgui.OnFrame(function() return true end, function()
    imgui.Begin("Test")

    imgui.InputTextMultiline("##logbox", logBox, ffi.sizeof(logBox), imgui.ImVec2(100, 200), imgui.InputTextFlags.ReadOnly)

    imgui.End()
end)
 

TastyBread123

Известный
631
302
Если в коде так как ты скинул - то тут твой косяк.
Переменная logbox,а передаёшь ты в функцию logBox, то есть nil - из-за чего и краш.
Следи за регистром символов.
понял, спасибо за поправку, помогло :)
Не заметил почему то сразу...
 
  • Нравится
Реакции: Andrinall

chapo

чопа сребдс // @moujeek
Модератор
8,938
11,705
Как можно проверить выполнится ли функция без ошибок без ее выполнения?
Например мне нужно проверить вернет ли этот код ошибку:
Lua:
imgui.GetStyle().Colors.I_LOVE_ERRORS = imgui.ImVec4(1, 0, 0, 1)
без выполнения этого кода. Конкретно это вернет ошибку и ничего не произойдет, однако если вставить туда например
Lua:
imgui.GetStyle().Colors.Text= imgui.ImVec4(1, 0, 0, 1)
то ошибки не будет, однако из-за того что код выполнится весь текст в имгуи окне будет красится в красный.

Более понятное объяснение:
например у меня есть 2 строки которые нужно "проверить на краш":
Lua:
imgui.GetStyle().Colors[imgui.Col.Text] = imgui.ImVec4(1, 0, 0, 1) -- ok
mgui.GetStyle().Colors[imgui.Col._____Text] = imgui.ImVec4(1, 0, 0, 1) -- ERROR
если вызывать их через pcall, то скрипт может определить вызовут ли эти строки ошибку, однако если строка не вызывает ошибку, то код выполняется (например вызов первый строки перекрасит текст в менюшке, а мне надо этого избежать)
 
Последнее редактирование:

windranger

Участник
30
4
Вместе имгуишной переменной создаешь обычную булевую (те переменные, у которых значение может быть только true или false)
И вместо чекбокса делаешь активацию на клавишу/команду и тд. А ну и в проверке перед кодом автоответчика убери .v
как создать простую булевую переменную? глупый, скорей всего, вопрос, но я не знаю, каким образом это реализовать
 

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
как создать простую булевую переменную? глупый, скорей всего, вопрос, но я не знаю, каким образом это реализовать
Lua:
local state = false -- По умолчанию выключено
Если тебе интерфейс не нужен, то вот на команду активация
Lua:
-- В начало кода
local state = false

-- В функцию main()
sampRegisterChatCommand("act", function()
    state = not state -- Переключение активации
    sampAddChatMessage("Автоответчик "..(state and "включён" or "выключен"), -1) -- Сообщение в чат, чтобы знать, включён или выключен автоответчик
end)

-- Ну и это там, где у тебя происходит сама ловля сообщений.
if state then
    -- Тут сам код ловли
end
 
  • Нравится
Реакции: whyega52

Gorskin

♥ Love Lua ♥
Проверенный
1,344
1,184
Как можно проверить выполнится ли функция без ошибок без ее выполнения?
Например мне нужно проверить вернет ли этот код ошибку:
Lua:
imgui.GetStyle().Colors.I_LOVE_ERRORS = imgui.ImVec4(1, 0, 0, 1)
без выполнения этого кода. Конкретно это вернет ошибку и ничего не произойдет, однако если вставить туда например
Lua:
imgui.GetStyle().Colors.Text= imgui.ImVec4(1, 0, 0, 1)
то ошибки не будет, однако из-за того что код выполнится весь текст в имгуи окне будет красится в красный.

Более понятное объяснение:
например у меня есть 2 строки которые нужно "проверить на краш":
Lua:
imgui.GetStyle().Colors[imgui.Col.Text] = imgui.ImVec4(1, 0, 0, 1) -- ok
mgui.GetStyle().Colors[imgui.Col._____Text] = imgui.ImVec4(1, 0, 0, 1) -- ERROR
если вызывать их через pcall, то скрипт может определить вызовут ли эти строки ошибку, однако если строка не вызывает ошибку, то код выполняется (например вызов первый строки перекрасит текст в менюшке, а мне надо этого избежать)
Как вариант создать список и сверять с содержимым? Допустим в словаре есть слово Text, Button но нет слова Child, значит строку с этим словом нужно выделить. Возможно этот метод костыль, но я ничего другого не вижу.
 
  • Вау
Реакции: whyega52

Andrinall

Известный
701
518
Как вариант создать список и сверять с содержимым? Допустим в словаре есть слово Text, Button но нет слова Child, значит строку с этим словом нужно выделить. Возможно этот метод костыль, но я ничего другого не вижу.
Если я правильно понял, то этот костыль будет примерно так выглядеть.

upd: Хотя нет, только на половину я понял, ну да ладно пусть лежит.
Lua:
local col = {
    Text=0,
    TextDisabled=0,
    WindowBg=0,
    ChildBg=0,
    PopupBg=0,
    Border=0,
    BorderShadow=0,
    FrameBg=0,
    FrameBgHovered=0,
    FrameBgActive=0,
    TitleBg=0,
    TitleBgActive=0,
    TitleBgCollapsed=0,
    MenuBarBg=0,
    ScrollbarBg=0,
    ScrollbarGrab=0,
    ScrollbarGrabHovered=0,
    ScrollbarGrabActive=0,
    CheckMark=0,
    SliderGrab=0,
    SliderGrabActive=0,
    Button=0,
    ButtonHovered=0,
    ButtonActive=0,
    Header=0,
    HeaderHovered=0,
    HeaderActive=0,
    Separator=0,
    SeparatorHovered=0,
    SeparatorActive=0,
    ResizeGrip=0,
    ResizeGripHovered=0,
    ResizeGripActive=0,
    Tab=0,
    TabHovered=0,
    TabActive=0,
    TabUnfocused=0,
    TabUnfocusedActive=0,
    PlotLines=0,
    PlotLinesHovered=0,
    PlotHistogram=0,
    PlotHistogramHovered=0,
    TextSelectedBg=0,
    DragDropTarget=0,
    NavHighlight=0,
    NavWindowingHighlight=0,
    NavWindowingDimBg=0,
    ModalWindowDimBg=0
}

imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil

    local style = imgui.GetStyle()
    style:SetColor("Text", imgui.ImVec4(1, 0.0, 0.0, 1))
    style:SetColor("____COLORS", imgui.ImVec4(0,0,0,1)) -- ничего не установит и не крашнет скрипт
end)

local wnd = imgui.OnFrame(function() return true end, function()
    imgui.Begin("Test")

    imgui.Text("Tested Text")

    imgui.End()
end)
wnd.HideCursor = true

function imgui.ImGuiStyle.__index:SetColor(name, value)
    if col[name] == nil then return false end
    self.Colors[imgui.Col[name]] = value
    return true
end
 

windranger

Участник
30
4
Lua:
local state = false -- По умолчанию выключено
Если тебе интерфейс не нужен, то вот на команду активация
Lua:
-- В начало кода
local state = false

-- В функцию main()
sampRegisterChatCommand("act", function()
    state = not state -- Переключение активации
    sampAddChatMessage("Автоответчик "..(state and "включён" or "выключен"), -1) -- Сообщение в чат, чтобы знать, включён или выключен автоответчик
end)

-- Ну и это там, где у тебя происходит сама ловля сообщений.
if state then
    -- Тут сам код ловли
end
Screenshot_64.1676798095.png

теперь не могу понять, почему автоответчик не хочет отключаться
вот отрывок из кода
Lua:
require "lib.moonloader"
local sampevents = require "lib.samp.events"
local onoff = false

function main()
    repeat wait(100) until isSampAvailable()
        sampRegisterChatCommand("am", act)
end

function act()
    onoff = not onoff
    sampAddChatMessage("Автоответчик "..(act and "включён" or "выключен"), -1)
end

function sampevents.onServerMessage(color, text)
    if act and text:find("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо") and not sampIsDialogActive() then
        lua_thread.create(function()
            local nickname, id = text:match("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо")
            wait(500)
            sampSendChat("/pm ".. id .." Приятного времяпровождения на сервере.")
        end)
    end
end
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,800
2,667
Screenshot_64.1676798095.png

теперь не могу понять, почему автоответчик не хочет отключаться
вот отрывок из кода
Lua:
require "lib.moonloader"
local sampevents = require "lib.samp.events"
local onoff = false

function main()
    repeat wait(100) until isSampAvailable()
        sampRegisterChatCommand("am", act)
end

function act()
    onoff = not onoff
    sampAddChatMessage("Автоответчик "..(act and "включён" or "выключен"), -1)
end

function sampevents.onServerMessage(color, text)
    if act and text:find("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо") and not sampIsDialogActive() then
        lua_thread.create(function()
            local nickname, id = text:match("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо")
            wait(500)
            sampSendChat("/pm ".. id .." Приятного времяпровождения на сервере.")
        end)
    end
end
Lua:
local sampevents = require "lib.samp.events"
local onoff = false

function main()
    repeat wait(100) until isSampAvailable()
        sampRegisterChatCommand("am", act)
end

function act()
    onoff = not onoff
    sampAddChatMessage("Автоответчик "..(onoff and "включён" or "выключен"), -1)
end

function sampevents.onServerMessage(color, text)
    if onoff and text:find("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо") and not sampIsDialogActive() then
        lua_thread.create(function()
            local nickname, id = text:match("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо")
            wait(500)
            sampSendChat("/pm ".. id .." Приятного времяпровождения на сервере.")
        end)
    end
end
 
D

deleted-user-139653

Гость
Как получить высоту полета относительно высоты поверхности?
 

windranger

Участник
30
4
Lua:
local sampevents = require "lib.samp.events"
local onoff = false

function main()
    repeat wait(100) until isSampAvailable()
        sampRegisterChatCommand("am", act)
end

function act()
    onoff = not onoff
    sampAddChatMessage("Автоответчик "..(onoff and "включён" or "выключен"), -1)
end

function sampevents.onServerMessage(color, text)
    if onoff and text:find("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо") and not sampIsDialogActive() then
        lua_thread.create(function()
            local nickname, id = text:match("%[Жалоба%] (.+)%[(%d+)%]: {FFFFFF}спасибо")
            wait(500)
            sampSendChat("/pm ".. id .." Приятного времяпровождения на сервере.")
        end)
    end
end
бля, спасибо за сохранённые нервы, которые были бы потрачены из-за невнимательности) лучший
 
  • Нравится
Реакции: whyega52

Pashyka

Участник
220
17
Парни, привет, вопрос открытый опять, после ввода команды он начинает флдить отыгровкой, а мне нужно чтобы отыгровка прошла один раз, return false вводил после потока ничего не изменилось


Lua:
function hook.onSendCommand(command)
    cmd, cmdtext = command:match("^/(%S+) (.*)$")
    if cmd == "fwarn" then
        --if player.rank < 9 then chatmsg("Команда /fwarn доступна с 9+ ранга.") return end
        local id, arg = cmdtext:match("(%d+) (.*)$")
        if not tonumber(id) or not arg or arg:gsub(" ", "") == '' then chatmsg("Используйте: /fwarn [ID] [Причина]") return end
        if not sampIsPlayerConnected(id) then chatmsg("Игрок не подключен или указан свой ID!") return end
        if ToggleButton.offwarn.v then
            lua_thread.create(function()
                sampSendChat(string.format("/me %s в руки планшет управления составом", (player.female and "взяла" or "взял")))
                wait(1600)
                sampSendChat(string.format("/me %s пункт 'Выговоры'", (player.female and "выбрала" or "выбрал")))
                wait(1600)
                sampSendChat(string.format("/me %s сотруднику '%s' выговор", (player.female and "выдала" or "выдал"), sampGetPlayerNickname(id):gsub("_", " ")))
                wait(1600)
                sampSendChat(string.format("/fwarn %d %s", tonumber(id), arg))
            end)
        else
            sampSendChat(string.format("/fwarn %d %s", tonumber(id), arg))
        end
    end
end