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

Anti...

Активный
267
31
Есть вот такая функция от @chapo (использовал в фортнайт худе), я немножно переделал под себя, добавил 1 чекбокс, нажимается, работает, но когда ставлю второй чекбокс, ужене работает, нажимаю но ничего не происходит, голову ломаю, как тут поступить? (ImGUi)

Код:
function imgui.FunctionChild(title, description, bool, button, size, colors)
    local colors = {
        back = imgui.ImVec4(0.13, 0.16, 0.2, 1),
        line = imgui.ImVec4(1, 0, 0.3, 1),
        text = imgui.ImVec4(1, 1, 1, 1),
        textd = imgui.ImVec4(0.5, 0.5, 0.5, 1),
    }
    local c = imgui.GetCursorPos()
    local p = imgui.GetCursorScreenPos()
    local dl = imgui.GetWindowDrawList()

    dl:AddRectFilled(p, imgui.ImVec2(p.x + size.x, p.y + size.y), imgui.GetColorU32(colors.back), 5, 2 + 8)
    dl:AddRectFilled(p, imgui.ImVec2(p.x + 5.5, p.y + size.y), imgui.GetColorU32(colors.line), 5, 1 + 8)

    dl:AddText(imgui.ImVec2(p.x + 10, p.y + 10), imgui.GetColorU32(colors.text), title)
    dl:AddText(imgui.ImVec2(p.x + 10, p.y + 25), imgui.GetColorU32(colors.textd), description)

    imgui.SetCursorPos(imgui.ImVec2(c.x + size.x - 20 - 10, c.y + 10))
    if bool ~= nil then
        imgui.Checkbox('##'..title..'::'..description, bool)
    end
    imgui.SetCursorPos(imgui.ImVec2(c.x + size.x - 20 - 40, c.y + 10))
    if button ~= nil then
        imgui.Button(fa.ICON_FA_COG, imgui.ImVec2(25, 23), button)
    end
    imgui.SetCursorPos(imgui.ImVec2(c.x + 10, c.y + 20 + 25))
    imgui.BeginChild('child:controls:'..title..':'..description, imgui.ImVec2(size.x - 15, size.y - 25 - 25), false)
end

В OnDrawFrame
Код:
imgui.SetCursorPos(imgui.ImVec2(15, 50 + 15))
            imgui.FunctionChild(u8'WallHack', u8'Настройки WH', bool1, button1, imgui.ImVec2(200, 50), colors) imgui.EndChild()
            imgui.SetCursorPos(imgui.ImVec2(15, 110 + 15))
                imgui.FunctionChild(u8'Render', u8'Настройки рендера', bool2, button2, imgui.ImVec2(200, 50), colors) imgui.EndChild()
                imgui.SetCursorPos(imgui.ImVec2(15, 170 + 15))
                imgui.FunctionChild(u8'Лазер', u8'Настройки лазера', bool3, button3, imgui.ImVec2(200, 50), colors) imgui.EndChild()
1.png
 

хуега)

РП игрок
Модератор
2,568
2,270
Как можно обратиться к индексу в массиве, используя функцию мимгуи?
Lua:
local OUTCOMING_RPC = {
    {23, {"playerId", "int16"}, {"source", "int8"}, description = "Отправляется при нажатии на игрока в списке игроков.", nop = false},
}

for i = 1, #OUTCOMING_RPC do
    local info = getRPC(OUTCOMING_RPC[i])
    local title = info.name .. " [" .. info.id .. "]"
    if title:lower():find(str(config.search):lower()) then
        if imgui.Selectable(config.hints[0] and "##" .. info.name .. " [" .. info.id .. "]" or info.name .. " [" .. info.id .. "]", Nop_OutRPC.selected == i) then
            Nop_OutRPC.selected = i
        end
    
        if config.hints[0] then
            imgui.SameLine(config.hints and -0.000000001 or nil)
            imgui.TextQuestion(config.hints[0] and info.name .. " [" .. info.id .. "]" or "( ? )", u8(OUTCOMING_RPC[i].description))
        end

        if Nop_OutRPC.selected == i then
            imgui.ToggleButton(OUTCOMING_RPC[Nop_OutRPC.selected].nop and "NOP: " .. info.name .. " [ON]" or "NOP: " .. info.name .. " [OFF]", OUTCOMING_RPC[Nop_OutRPC.selected].nop)
        end
    end
end

function imgui.ToggleButton(str_id, value)
    local duration = 0.3
    local p = imgui.GetCursorScreenPos()
    local DL = imgui.GetWindowDrawList()
    local size = imgui.ImVec2(40, 20)
    local title = str_id:gsub("##.*$", "")
    local ts = imgui.CalcTextSize(title)
    local cols = {
        enable = imgui.GetStyle().Colors[imgui.Col.ButtonActive],
        disable = imgui.GetStyle().Colors[imgui.Col.TextDisabled]   
    }
    local radius = 6
    local o = {
        x = 4,
        y = p.y + (size.y / 2)
    }
    local A = imgui.ImVec2(p.x + radius + o.x, o.y)
    local B = imgui.ImVec2(p.x + size.x - radius - o.x, o.y)

    if AI_TOGGLE[str_id] == nil then
        AI_TOGGLE[str_id] = {
            clock = nil,
            color = value[0] and cols.enable or cols.disable,
            pos = value[0] and B or A
        }
    end
    local pool = AI_TOGGLE[str_id]
    
    imgui.BeginGroup()
        local pos = imgui.GetCursorPos()
        local result = imgui.InvisibleButton(str_id, imgui.ImVec2(size.x, size.y))
        if result then
            value[0] = not value[0]
            pool.clock = os.clock()
        end
        if #title > 0 then
            local spc = imgui.GetStyle().ItemSpacing
            imgui.SetCursorPos(imgui.ImVec2(pos.x + size.x + spc.x, pos.y + ((size.y - ts.y) / 2)))
            imgui.Text(title)
        end
    imgui.EndGroup()

     if pool.clock and os.clock() - pool.clock <= duration then
        pool.color = bringVec4To(
            imgui.ImVec4(pool.color),
            value[0] and cols.enable or cols.disable,
            pool.clock,
            duration
        )

        pool.pos = bringVec2To(
            imgui.ImVec2(pool.pos),
            value[0] and B or A,
            pool.clock,
            duration
        )
    else
        pool.color = value[0] and cols.enable or cols.disable
        pool.pos = value[0] and B or A
    end

    DL:AddRect(p, imgui.ImVec2(p.x + size.x, p.y + size.y), ToU32(pool.color), 10, 15, 1)
    DL:AddCircleFilled(pool.pos, radius, ToU32(pool.color))

    return result
end

Код:
[ML] (error) RakNet Changer: C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:962: attempt to index local 'value' (a boolean value)
stack traceback:
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:962: in function 'ToggleButton'
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:577: in function '_draw'
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\lib\mimgui\init.lua:107: in function <C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\lib\mimgui\init.lua:91>
[ML] (error) RakNet Changer: Script died due to an error. (24457A24)

[ATTACH type="full"]175997[/ATTACH]
 

Вложения

  • 1667535548600.png
    1667535548600.png
    19 KB · Просмотры: 9

percheklii

Известный
739
275
Как сделать таймер по тексту?
Допустим: if text:find( текст 1) or text:find (текст 2) then
запускается таймер
истикает время
пишет "откат прошел"
Помогите пожалуйста, чет никогда не могу найти адекватный пример
 

хуега)

РП игрок
Модератор
2,568
2,270
Как сделать таймер по тексту?
Допустим: if text:find( текст 1) or text:find (текст 2) then
запускается таймер
истикает время
пишет "откат прошел"
Помогите пожалуйста, чет никогда не могу найти адекватный пример
wait(--[[время мс]])
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,226
Как можно обратиться к индексу в массиве, используя функцию мимгуи?
Lua:
local OUTCOMING_RPC = {
    {23, {"playerId", "int16"}, {"source", "int8"}, description = "Отправляется при нажатии на игрока в списке игроков.", nop = false},
}

for i = 1, #OUTCOMING_RPC do
    local info = getRPC(OUTCOMING_RPC[i])
    local title = info.name .. " [" .. info.id .. "]"
    if title:lower():find(str(config.search):lower()) then
        if imgui.Selectable(config.hints[0] and "##" .. info.name .. " [" .. info.id .. "]" or info.name .. " [" .. info.id .. "]", Nop_OutRPC.selected == i) then
            Nop_OutRPC.selected = i
        end
   
        if config.hints[0] then
            imgui.SameLine(config.hints and -0.000000001 or nil)
            imgui.TextQuestion(config.hints[0] and info.name .. " [" .. info.id .. "]" or "( ? )", u8(OUTCOMING_RPC[i].description))
        end

        if Nop_OutRPC.selected == i then
            imgui.ToggleButton(OUTCOMING_RPC[Nop_OutRPC.selected].nop and "NOP: " .. info.name .. " [ON]" or "NOP: " .. info.name .. " [OFF]", OUTCOMING_RPC[Nop_OutRPC.selected].nop)
        end
    end
end

function imgui.ToggleButton(str_id, value)
    local duration = 0.3
    local p = imgui.GetCursorScreenPos()
    local DL = imgui.GetWindowDrawList()
    local size = imgui.ImVec2(40, 20)
    local title = str_id:gsub("##.*$", "")
    local ts = imgui.CalcTextSize(title)
    local cols = {
        enable = imgui.GetStyle().Colors[imgui.Col.ButtonActive],
        disable = imgui.GetStyle().Colors[imgui.Col.TextDisabled]  
    }
    local radius = 6
    local o = {
        x = 4,
        y = p.y + (size.y / 2)
    }
    local A = imgui.ImVec2(p.x + radius + o.x, o.y)
    local B = imgui.ImVec2(p.x + size.x - radius - o.x, o.y)

    if AI_TOGGLE[str_id] == nil then
        AI_TOGGLE[str_id] = {
            clock = nil,
            color = value[0] and cols.enable or cols.disable,
            pos = value[0] and B or A
        }
    end
    local pool = AI_TOGGLE[str_id]
   
    imgui.BeginGroup()
        local pos = imgui.GetCursorPos()
        local result = imgui.InvisibleButton(str_id, imgui.ImVec2(size.x, size.y))
        if result then
            value[0] = not value[0]
            pool.clock = os.clock()
        end
        if #title > 0 then
            local spc = imgui.GetStyle().ItemSpacing
            imgui.SetCursorPos(imgui.ImVec2(pos.x + size.x + spc.x, pos.y + ((size.y - ts.y) / 2)))
            imgui.Text(title)
        end
    imgui.EndGroup()

     if pool.clock and os.clock() - pool.clock <= duration then
        pool.color = bringVec4To(
            imgui.ImVec4(pool.color),
            value[0] and cols.enable or cols.disable,
            pool.clock,
            duration
        )

        pool.pos = bringVec2To(
            imgui.ImVec2(pool.pos),
            value[0] and B or A,
            pool.clock,
            duration
        )
    else
        pool.color = value[0] and cols.enable or cols.disable
        pool.pos = value[0] and B or A
    end

    DL:AddRect(p, imgui.ImVec2(p.x + size.x, p.y + size.y), ToU32(pool.color), 10, 15, 1)
    DL:AddCircleFilled(pool.pos, radius, ToU32(pool.color))

    return result
end

Код:
[ML] (error) RakNet Changer: C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:962: attempt to index local 'value' (a boolean value)
stack traceback:
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:962: in function 'ToggleButton'
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:577: in function '_draw'
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\lib\mimgui\init.lua:107: in function <C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\lib\mimgui\init.lua:91>
[ML] (error) RakNet Changer: Script died due to an error. (24457A24)

[ATTACH type="full"]175997[/ATTACH]
Lua:
    if imgui.ToggleButton('тут твое говно', imgui.new.bool(OUTCOMING_RPC[Nop_OutRPC.selected].nop)) then
        OUTCOMING_RPC[Nop_OutRPC.selected].nop = not OUTCOMING_RPC[Nop_OutRPC.selected].nop
    end
 
  • Нравится
Реакции: хуега)

Moorell

Участник
55
12
Вопрос: Можно ли использовать imgui.Combo в цыкле?
Мне очень нужно, чтобы массив прогонялся через цыкл, и для каждой линии в комбо присваивался свой номер(ранг), и мне нужно его менять.
Но когда выбираю другой пунк, он не меняется(что логично, т.к он обновляется в цыкле) основная суть мне надо вывести номер выбранного элемента.

Lua:
for i, v in ipairs(dateAccess) do
    if imgui.Combo("##" .. i, new.int(v.num), new['const char*'][4]("Стажер", "Сотрудник", "Начальник", "Куратор"), 4) then
        print("Выводит выбранный ранг")
    end
end
 

Basedbounty

Активный
181
74
вообщем фигня какая то с кодом, сам скрипт должен открывать диалоговое окно с выбором "погоды" но какого то фига когда я пишу команду мне пишет что такой команды не существуют, что делать?
Lua:
script_name("DialogovoeWINDOWS")
script_author("WEWORNY")


require "lib.moonloader"
local dialogchvet = DC143C
local dialogTabArr = ("Если вы выберете этот пункт, погода изменится на утро", "Если вы выберете этот пункт, погода изменится на вечер"
local dialogTabStr = ""

for _, str in ipairs(dialogTabArr) do
    dialogTabStr = dialogTabStr .. str .. "\n"
end
function main()
if not isSampLoaded() or not isSampfuncsLoaded() then return end
while not isSampAvailable() do wait(100) end
   sampRegisterChatCommand("swweworny", cmd_swweworny)

while true do wait(0)


    local result, button, list, input = sampHasDialogRespond(14)
    if result then
     if button == 1 then
     if list == 0 then
    sampAddChatMessage("Вы выбрали Погоду утро {FFFFFF}" .. list, dialogchvet)
    elseif list == 1 then
    sampAddChatMessage("Вы выбрали Погоду вечер {FFFFFF}" .. list, dialogchvet)
    end
else
      sampAddChatMessage("Вы закрыли диалоговое окно", dialogchvet)
     end
end
    
    function cmd_swweworny(arg)
    if tonumber(arg) == 4 then
    sampShowDialog(14, "Погода", dialogTabStr, "выбрать", "Закрыть", 4)
    end
end
 

хуега)

РП игрок
Модератор
2,568
2,270
вообщем фигня какая то с кодом, сам скрипт должен открывать диалоговое окно с выбором "погоды" но какого то фига когда я пишу команду мне пишет что такой команды не существуют, что делать?
Lua:
script_name("DialogovoeWINDOWS")
script_author("WEWORNY")


require "lib.moonloader"
local dialogchvet = DC143C
local dialogTabArr = ("Если вы выберете этот пункт, погода изменится на утро", "Если вы выберете этот пункт, погода изменится на вечер"
local dialogTabStr = ""

for _, str in ipairs(dialogTabArr) do
    dialogTabStr = dialogTabStr .. str .. "\n"
end
function main()
if not isSampLoaded() or not isSampfuncsLoaded() then return end
while not isSampAvailable() do wait(100) end
   sampRegisterChatCommand("swweworny", cmd_swweworny)

while true do wait(0)


    local result, button, list, input = sampHasDialogRespond(14)
    if result then
     if button == 1 then
     if list == 0 then
    sampAddChatMessage("Вы выбрали Погоду утро {FFFFFF}" .. list, dialogchvet)
    elseif list == 1 then
    sampAddChatMessage("Вы выбрали Погоду вечер {FFFFFF}" .. list, dialogchvet)
    end
else
      sampAddChatMessage("Вы закрыли диалоговое окно", dialogchvet)
     end
end
   
    function cmd_swweworny(arg)
    if tonumber(arg) == 4 then
    sampShowDialog(14, "Погода", dialogTabStr, "выбрать", "Закрыть", 4)
    end
end
мб я не шарю в искусстве, но тут какой-то пиздец
 

Mico

Активный
246
46
Насколько я знаю в любом языке можно создать всё-что угодно. Может кто поможет, как сделать такое. Есть допустим 2 "переменные" из диалога. Скрипт пишет /commanda nick и так несколько человек, и у каждого в файл выводится определенная информация.

Хочу сделать так, если переменная time_h <= 1 and time_m <= 30, то человек записывается где-то ниже. Потом так и с другими, кто будет попадать под это всё. А после надо, чтобы отобразило количество людей, у которых time_h <= 1 and time_m <= 30

Надеюсь понятно объяснил :D
 

Veit

Известный
83
19
Использую в своем скрипте функцию бега по координатам:
Lua:
function runToPoint(tox, toy)
    local x, y, z = getCharCoordinates(PLAYER_PED)
    local angle = getHeadingFromVector2d(tox - x, toy - y)
    local xAngle = math.random(-50, 50)/100
    setCameraPositionUnfixed(xAngle, math.rad(angle - 90))
    stopRun = false
    while getDistanceBetweenCoords2d(x, y, tox, toy) > 0.8 do
        setGameKeyState(1, -255)
        --setGameKeyState(16, 1)
        wait(1)
        x, y, z = getCharCoordinates(PLAYER_PED)
        angle = getHeadingFromVector2d(tox - x, toy - y)
        setCameraPositionUnfixed(xAngle, math.rad(angle - 90))
        if stopRun then
            stopRun = false
            break
        end
    end
end

Но она слишком уж топорная и палевная, как можно сделать её более "человекоподобной", чтобы не вызывать подозрения у каждого первого?
 

хуега)

РП игрок
Модератор
2,568
2,270
Использую в своем скрипте функцию бега по координатам:
Lua:
function runToPoint(tox, toy)
    local x, y, z = getCharCoordinates(PLAYER_PED)
    local angle = getHeadingFromVector2d(tox - x, toy - y)
    local xAngle = math.random(-50, 50)/100
    setCameraPositionUnfixed(xAngle, math.rad(angle - 90))
    stopRun = false
    while getDistanceBetweenCoords2d(x, y, tox, toy) > 0.8 do
        setGameKeyState(1, -255)
        --setGameKeyState(16, 1)
        wait(1)
        x, y, z = getCharCoordinates(PLAYER_PED)
        angle = getHeadingFromVector2d(tox - x, toy - y)
        setCameraPositionUnfixed(xAngle, math.rad(angle - 90))
        if stopRun then
            stopRun = false
            break
        end
    end
end

Но она слишком уж топорная и палевная, как можно сделать её более "человекоподобной", чтобы не вызывать подозрения у каждого первого?
Шо именно? Повороты?
 

#SameLine

Активный
418
37
Как нормально сохранить текст в imgui.InputTextMultiline
допустим ввел в строку "111111" сохраняет
но если введу:
"1111" и снизу
"12312312" то cfg слетает