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

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,783
2,610
как я могу сделать автоматическое обновление через LUAC?
.luac - тот-же .lua, отличается только то, как программа хранится. Если более подробно, то .lua - файл, который будет обрабатываться интерпретатором и постепенно преобразовывается, а .luac представляет собой сразу байт-код.
Могу ошибаться, так как сам только недавно начал читать про это.

Lua:
while true do
        wait(0)
        if main_window_state.v == false then
            imgui.Process = false
        end
        if toggle_status_1.v and isGameWindowForeground() and not isPauseMenuActive() and not isGamePaused() then
        res, handle = getCharPlayerIsTargeting(playerHandle)
            if res then
                resid, id = sampGetPlayerIdByCharHandle(handle)
                color_nick = sampGetPlayerColor(id)
                name = sampGetPlayerNickname(id)
            end
            while res and toggle_status_1.v do
            for i = 1, #testik do
                if color_nick == testik[i] then
                    sampAddChatMessage(tag.. 'Ты указал на вояку, его жетон: ' ..buffer2.v, -1)
                end
            end
            for p = 1, #players do
                if color_nick == players[p] then
                    sampAddChatMessage(tag.. 'Ты указал на обычного игрока, его жетон: ' ..buffer4.v, -1)
                end
            end
            for j = 1, #opg do
                if color_nick == opg[j] then
                    sampAddChatMessage(tag.. 'Ты указал на опгшника, его жетон: ' ..buffer1.v, -1)
                end
            end
            for s = 1, #getto do
                if color_nick == getto[s] then
                    sampAddChatMessage(tag.. 'Ты указал на гетовца, его жетон: ' ..buffer2.v, -1)
                end
            end
                while true do
                wait(0)
                res, handle = getCharPlayerIsTargeting(playerHandle)
                if not res then break end
                end
            end
        end
    end
end

Я правильно вдуплил?
upd. херово я думаю крч, так же не работает, ну чет я уже хз
не совсем понял твою систему, но попробуй так:
Lua:
local ghetto = {'822070323', '808687974', '818689023', '812017407'}
local gosnik = {'820443905', '812030463', '812663316', '805309695', '822038272', '818675763', '{000cff}', '808688127'} -- нету БА
local opg = {'805358847', '812017254'}
local players = {'16777216', '4291572531', '4281558732', '822083583'}
local testik = {'812663316'}

while true do -- main
    wait(0)
    if not main_window_state.v then
        imgui.Process = false
    end
    if toggle_status_1.v and isGameWindowForeground() and not isPauseMenuActive() and not isGamePaused() then
        local res, handle = getCharPlayerIsTargeting(playerHandle)
        if res then
            local id = select(2, sampGetPlayerIdByCharHandle(handle))
            local color_nick = sampGetPlayerColor(id)
            local name = sampGetPlayerNickname(id)

            for _, color in ipairs(testik) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на вояку, его жетон: ' ..buffer2.v, -1)
                end
            end
            
            for _, color in ipairs(players) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на обычного игрока, его жетон: ' ..buffer4.v, -1)
                end
            end
            for _, color in ipairs(opg) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на опгшника, его жетон: ' ..buffer1.v, -1)
                end
            end
            for _, color in ipairs(ghetto) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на гетовца, его жетон: ' ..buffer2.v, -1)
                end
            end
        end       
    end
end
 
Последнее редактирование:
  • Влюблен
Реакции: Julimba

Julimba

Участник
108
10
.luac - тот-же .lua, отличается только то, как программа хранится. Если более подробно, то .lua - файл, который будет обрабатываться интерпретатором и постепенно преобразовывается, а .luac представляет собой сразу байт-код.
Могу ошибаться, так как сам только недавно начал читать про это.


не совсем понял твою систему, но попробуй так:
Lua:
local ghetto = {'822070323', '808687974', '818689023', '812017407'}
local gosnik = {'820443905', '812030463', '812663316', '805309695', '822038272', '818675763', '{000cff}', '808688127'} -- нету БА
local opg = {'805358847', '812017254'}
local players = {'16777216', '4291572531', '4281558732', '822083583'}
local testik = {'812663316'}

while true do -- main
    wait(0)
    if not main_window_state.v then
        imgui.Process = false
    end
    if toggle_status_1.v and isGameWindowForeground() and not isPauseMenuActive() and not isGamePaused() then
        local res, handle = getCharPlayerIsTargeting(playerHandle)
        if res then
            local id = select(2, sampGetPlayerIdByCharHandle(handle))
            local color_nick = sampGetPlayerColor(id)
            local name = sampGetPlayerNickname(id)

            for _, color in ipairs(testik) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на вояку, его жетон: ' ..buffer2.v, -1)
                end
            end
           
            for _, color in ipairs(players) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на обычного игрока, его жетон: ' ..buffer4.v, -1)
                end
            end
            for _, color in ipairs(opg) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на опгшника, его жетон: ' ..buffer1.v, -1)
                end
            end
            for _, color in ipairs(ghetto) do
                if color_nick == color then
                    sampAddChatMessage(tag.. 'Ты указал на гетовца, его жетон: ' ..buffer2.v, -1)
                end
            end
        end      
    end
end
К сожалению такая же тема и ничего не происходит при наведении таргета
 

Dmitriy Makarov

25.05.2021
Проверенный
2,500
1,131
К сожалению такая же тема и ничего не происходит при наведении таргета
Вынеси цвета с кавычек.
А тот, который HEX "{000cff}" – убери оттуда. Либо же достань его Decimal код, как и остальные.
 
  • Влюблен
Реакции: Julimba

Julimba

Участник
108
10
Вынеси цвета с кавычек.
А тот, который HEX "{000cff}" – убери оттуда. Либо же достань его Decimal код, как и остальные.
А он никак не участвует в цепочке этой, да и если убрать его, то ничего не меняется.
upd. я рукожоп и все работает, огромное спасибо парни за помощь.
 
  • Нравится
Реакции: whyega52

sosnov

Известный
329
115
сейчас работаю с пакетами бота, точнее с его вводом пароля, можно ли как то сделать так чтоб он использовал разные варианты регистрации? к примеру:

Lua:
function onBotIncomingRPC(bot, rpcId, bs)
if --пакет какой то
--код какого то пакета
end
or
if -- этот же пакет
--код этого же пакета только под другую систему регистрации
end
end

что то такое, мне бы пример кода желательно, а если и тут как я привёл всё норм, то так и скажите
 

Julimba

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


Lua:
if imgui.ToggleButton(u8"По таргету", toggle_status_1) then
    mainIni.config.target = toggle_status_1.v
    inicfg.save(mainIni, directIni)
end
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,783
2,610
сейчас работаю с пакетами бота, точнее с его вводом пароля, можно ли как то сделать так чтоб он использовал разные варианты регистрации? к примеру:

Lua:
function onBotIncomingRPC(bot, rpcId, bs)
if --пакет какой то
--код какого то пакета
end
or
if -- этот же пакет
--код этого же пакета только под другую систему регистрации
end
end

что то такое, мне бы пример кода желательно, а если и тут как я привёл всё норм, то так и скажите
Lua:
function onBotIncomingRPC(bot, rpcId, bs)
    if rpcId == 63 then -- на примере диалогов
        -- тут читаешь заголовок диалога
        if title:find("Регистрация") then
            -- тут для такого диалога
        elseif title:find("РЕГИСТРАЦИЯ")
            -- тут для другого
        end
    end
end
А вообще, если ты знаешь, на каких серверах будут запускать твой скрипт - напиши, скажу как можно реализовать +- нормально

qq, тупой вопрос конечно, крч у меня есть тоглы батоны и их положение true/false заносится в ini , внимание вопрос, как сделать чтобы они перезаходе/перезагрузки скрипта они оставались в сохраненном ранее положение в ini


Lua:
if imgui.ToggleButton(u8"По таргету",) then
    mainIni.config.target = toggle_status_1.v
    inicfg.save(mainIni, directIni)
end
Lua:
-- в начале скрипта заменяешь объявление переменной toggle_status_1 на такое

local toggle_status_1 = imgui.ImBool(mainIni.config.target)
 
  • Влюблен
  • Нравится
Реакции: Julimba и sosnov

sosnov

Известный
329
115
А вообще, если ты знаешь, на каких серверах будут запускать твой скрипт - напиши, скажу как можно реализовать +- нормально
желательно на многих нубо арз, рдс и хмс
но тупые мододелы нубо аризон скачивают всё непойми с каких сайтов свои долбанные моды и у них то ид отличается,то ошибки в словах, они короче ваще дурочки.
Lua:
function onBotIncomingRPC(bot, rpcId, bs)
    if rpcId == 63 then -- на примере диалогов
        -- тут читаешь заголовок диалога
        if title:find("Регистрация") then
            -- тут для такого диалога
        elseif title:find("РЕГИСТРАЦИЯ")
            -- тут для другого
        end
    end
end
А вообще, если ты знаешь, на каких серверах будут запускать твой скрипт - напиши, скажу как можно реализовать +- нормально


Lua:
-- в начале скрипта заменяешь объявление переменной toggle_status_1 на такое

local toggle_status_1 = imgui.ImBool(mainIni.config.target)
а вообще елсе иф типо как "или" используется? я правильно понимаю?
 

Smeruxa

Известный
1,364
723
желательно на многих нубо арз, рдс и хмс
но тупые мододелы нубо аризон скачивают всё непойми с каких сайтов свои долбанные моды и у них то ид отличается,то ошибки в словах, они короче ваще дурочки.

а вообще елсе иф типо как или используется? я правильно понимаю?
elseif - штука, которая используется, чтобы выполнилось строго одного из данных условий
Пример без elseif:
Lua:
a = 30
if a > 5 then
    print('123')
end
if a > 10 then
    print('321')
end

-- выполнится два условия
-- output: 
-- 123
-- 321
Пример с elseif
Lua:
a = 30
if a > 5 then
    print('123')
elseif a > 10 then
    print('321')
end

-- выполнится только первое условие
-- output: 123
 
  • Нравится
Реакции: YarikVL и sosnov

Julimba

Участник
108
10
qq, в чем моя очередная ошибка? Задача скрипта выдать id игроков, которые находятся в указанном радиусе.
Скрипт так же запускается, но не выполняет задачу.

Lua:
local radius = 7

-- Бесконечный цикл в мейне
if toggle_status.v and isGameWindowForeground() and not isPauseMenuActive() and not isGamePaused() then
        wait(1000)
        local x, y, z = getCharCoordinates(PLAYER_PED)
        local _, ped = findAllRandomCharsInSphere(x, y, z, radius, true, true)
        if _ then
            local _, pid = sampGetPlayerIdByCharHandle(ped)
            if _ then
                sampAddChatMessage(tag.. 'Вот такой вот результат:' ..pid, -1)
                wait(500)
            end
        end
    end
end
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,783
2,610
qq, в чем моя очередная ошибка? Задача скрипта выдать id игроков, которые находятся в указанном радиусе.
Скрипт так же запускается, но не выполняет задачу.

Lua:
local radius = 7

-- Бесконечный цикл в мейне
if toggle_status.v and isGameWindowForeground() and not isPauseMenuActive() and not isGamePaused() then
        wait(1000)
        local x, y, z = getCharCoordinates(PLAYER_PED)
        local _, ped = findAllRandomCharsInSphere(x, y, z, radius, true, true)
        if _ then
            local _, pid = sampGetPlayerIdByCharHandle(ped)
            if _ then
                sampAddChatMessage(tag.. 'Вот такой вот результат:' ..pid, -1)
                wait(500)
            end
        end
    end
end
Чему равна переменная radius?
 

chapo

чопа сребдс // @moujeek
Модератор
8,868
11,576
qq, в чем моя очередная ошибка? Задача скрипта выдать id игроков, которые находятся в указанном радиусе.
Скрипт так же запускается, но не выполняет задачу.

Lua:
local radius = 7

-- Бесконечный цикл в мейне
if toggle_status.v and isGameWindowForeground() and not isPauseMenuActive() and not isGamePaused() then
        wait(1000)
        local x, y, z = getCharCoordinates(PLAYER_PED)
        local _, ped = findAllRandomCharsInSphere(x, y, z, radius, true, true)
        if _ then
            local _, pid = sampGetPlayerIdByCharHandle(ped)
            if _ then
                sampAddChatMessage(tag.. 'Вот такой вот результат:' ..pid, -1)
                wait(500)
            end
        end
    end
end
Lua:
function getAllPlayersInRadius(radius)
    local list, x, y, z = {}, getCharCoordinates(ped)
    for _, ped in ipairs(getAllChars()) do
        if getDistanceBetweenCoords3d(x, y, z, getCharCoordinates(ped)) <= radius then
            local result, id = sampGetPlayerIdByCharHandle(ped)
            if result then
                table.insert(list, { id = id, handle = ped})
            end
        end
    end
    return list
end

-- code
for _, player in ipairs(getAllPlayersInRadius(5)) do
    sampAddChatMessage(('ID: %s, name: %s'):format(player.id, sampGetPlayerNickname(player.id)), -1)
    wait(500)
end
 
  • Влюблен
Реакции: Julimba

roman_vodola

Известный
170
19
Как я могу получить адрес сервера к, которому бот подключается(например сервер заполнен). sampGetCurrentServerAddress() выдает ошибку, если выполнить её не находясь на сервере.
 

Julimba

Участник
108
10
Lua:
function getAllPlayersInRadius(radius)
    local list, x, y, z = {}, getCharCoordinates(ped)
    for _, ped in ipairs(getAllChars()) do
        if getDistanceBetweenCoords3d(x, y, z, getCharCoordinates(ped)) <= radius then
            local result, id = sampGetPlayerIdByCharHandle(ped)
            if result then
                table.insert(list, { id = id, handle = ped})
            end
        end
    end
    return list
end

-- code
for _, player in ipairs(getAllPlayersInRadius(5)) do
    sampAddChatMessage(('ID: %s, name: %s'):format(player.id, sampGetPlayerNickname(player.id)), -1)
    wait(500)
end
Рукожопость моя подтверждается крч, хз в чем трабл

[ML] (error) AFKhelper.lua: opcode '00A0' call caused an unhandled exception
stack traceback:
[C]: in function 'getCharCoordinates'
D:\Games\GTA SA\Sasok\moonloader\AFKhelper.lua:55: in function 'getAllPlayersInRadius'
D:\Games\GTA SA\Sasok\moonloader\AFKhelper.lua:83: in function <D:\Games\GTA SA\Sasok\moonloader\AFKhelper.lua:68>
[ML] (error) AFKhelper.lua: Script died due to an error. (0633B0B4)