Вопросы по 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,790
2,615
Как я могу получить адрес сервера к, которому бот подключается(например сервер заполнен). sampGetCurrentServerAddress() выдает ошибку, если выполнить её не находясь на сервере.
Какой бот? Мунбот?
 

roman_vodola

Известный
170
19
Какой бот? Мунбот?
да обычный самописный луа бот. мне нужно закинуть айпи адрес на окно гта. это я делаю через ffi.C.SetWindowTextA только мне нужно получать айпи адресс сервера , чтобы вставить в окно процесса. во время коннекта выдает ошибку. думаю это потому, что sampGetCurrentServerAddress() работает по принципу: взять айпи адресс сервера ,к которому ты уже подключен, но поскольку я только нахожусь в процессе подключения он выдает исключение, ну а я думаю, что можно взять адресс сервера ,к которому ты подключаешься , ибо в чате пишет , что идет подключение к такому-то айпи адрессу.
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,790
2,615
Рукожопость моя подтверждается крч, хз в чем трабл

[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)
Насколько я понимаю, эта ошибка возникает тогда, когда ты пытаешься в getCharCoordinattes() засунуть несуществующий хендл, функцию надо передалать, может кто-нибудь сможет это сделать сейчас, но я только завтра

да обычный самописный луа бот. мне нужно закинуть айпи адрес на окно гта. это я делаю через ffi.C.SetWindowTextA только мне нужно получать айпи адресс сервера , чтобы вставить в окно процесса. во время коннекта выдает ошибку. думаю это потому, что sampGetCurrentServerAddress() работает по принципу: взять айпи адресс сервера ,к которому ты уже подключен, но поскольку я только нахожусь в процессе подключения он выдает исключение, ну а я думаю, что можно взять адресс сервера ,к которому ты подключаешься , ибо в чате пишет , что идет подключение к такому-то айпи адрессу.
Не совсем понял кнш зо ша бот, но можешь попробовать хукать исходящий rpc CLIENT_JOIN (то-ли 25, то ли 26 ид, не помню)
 

Julimba

Участник
108
10
Насколько я понимаю, эта ошибка возникает тогда, когда ты пытаешься в getCharCoordinattes() засунуть несуществующий хендл, функцию надо передалать, может кто-нибудь сможет это сделать сейчас, но я только завтра
+, пофиксил, спасибо что помог додуматься, только вот проблема, он хукает и моего персонажа, можно ли это как убрать?
 

chapo

чопа сребдс // @moujeek
Модератор
8,875
11,584
Рукожопость моя подтверждается крч, хз в чем трабл

[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)
на второй (только на второй) строке замени ped на PLAYER_PED
 

User500050

Участник
20
16
Мой скрипт не работает, когда я набираю /work на рабочем месте (он предназначен для получения значений textdraw и помещения их в чат. при вводе /work открывается textdraw с 3 случайными textdraws)
Lua:
local tids = {2050, 2051, 2052} -- At the beginning.
local sampev = require 'lib.samp.events'


function sampev.onShowTextDraw(id, data)
    for _, v in pairs(tids) do
        if id == v then
            sampAddChatMessage(data.text, -1)
        end
    end
end
А ты точно уверен что id этих случайных textdraw'ов равны что внутри tids?
Ты можешь узнать текста этих texdraw'ов используя
string.match(text, "шаблонный текст")
для того чтобы проверить, находится ли 'шаблонный текст' внутри text.

Пример.
На экране появляется textdraw с текстом:
Привет Nick_Name! У тебя сейчас 8 коинов.

Код чтобы вывести весь этот текст по шаблону:

Lua:
local sampev = require 'lib.samp.events'

function sampev.onShowTextDraw (id, data)
  local text = data.text
  if string.match(text, "У тебя сейчас %d+ коинов") then
    sampAddChatMessage(text, -1)
  end
end

Прочитай про string.match() в интернете чтобы понять что значат эти %d+
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,790
2,615
Мой скрипт не работает, когда я набираю /work на рабочем месте (он предназначен для получения значений textdraw и помещения их в чат. при вводе /work открывается textdraw с 3 случайными textdraws)
Lua:
local tids = {2050, 2051, 2052} -- At the beginning.
local sampev = require 'lib.samp.events'


function sampev.onShowTextDraw(id, data)
    for _, v in pairs(tids) do
        if id == v then
            sampAddChatMessage(data.text, -1)
        end
    end
end
не совсем по теме, но если у тебя таблица (в данном случае массив) не содержит в себе строковых ключей, то ты можешь использовать не pairs(), а ipairs(), которая предназначена специально для массивов и выполняется быстрее
Lua:
local t1 = {
    "hello",
    "what",
    415,
    {}
} -- ipairs()

local t2 = {
    text = "hello",
    answer = "what",
    num = 415,
    table = {}
} -- pairs()
 

sosnov

Известный
329
115
пишу автоответчик и столкнулся с проблемой, добавил функцию которая при виде:
"(ник чела) говорит: вы тут? вы бот? и тд"
отправляет в чат:
"дада тут, кнш где еще и тд"
но вот только проблема, этого не происходит,вот код:
Lua:
    onServerMessage = function(_, text)
    if act then
    if (text:match(' .-') or text:match('говорит:')) then
        if text:match("Вы тут?") or text:match("Вы тут") or text:match("Вы здесь") or text:match("тyт") or text:match("Вы за компьютером ?") or text:match("Вы за компьютером") or text:match("тут") or text:match("здесь") or text:match("Вы здесь?") or text:match("вы тут?") or text:match("вы тут") or text:match("вы здесь") or text:match("вы здесь?") or text:match("в ы з д е с ь?") or text:match("вы бот?")  or text:match("вы бот") or text:match("Вы бот?") or text:match("ответ в чат") or text:match("ответ в /b") or text:match("ответ в /n") or text:match("Вы на месте?") or text:match("Вы афк?") or text:match("вы тут? ответ в /n") or text:match("Вы тут? Ответ в /n") or text:match("вы тут? ответ в /b") or text:match("Вы тут? Ответ в /b") then
        if os.time() - t > 6 then
        t = os.time()
        lua_thread.create(function(a)
                if k < 1 then
                if not text:match('%d+(%p)%d+') then
                    mute(true)
                        wait(math.random(890, 1039))
                            freezeCharPositionAndDontLoadCollision(ped, true)
                        wait(math.random(3000, 4000))
                        sampSendChat(otveti[math.random(1, #otveti)])
                        freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                    k = k + 1
                elseif not text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                        sampSendChat(povtoriha[math.random(1, #povtoriha)])
                    k = 0
                    freezeCharPositionAndDontLoadCollision(ped, false)
                end
                if text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                    sampSendChat(matemka[math.random(1, #matemka)])
                    freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                end)
                end
            end
            end
        end
    end
и если что все указанные там переменные я указывал в начале кода, это не в них дело
 

sosnov

Известный
329
115
пишу автоответчик и столкнулся с проблемой, добавил функцию которая при виде:
"(ник чела) говорит: вы тут? вы бот? и тд"
отправляет в чат:
"дада тут, кнш где еще и тд"
но вот только проблема, этого не происходит,вот код:
Lua:
    onServerMessage = function(_, text)
    if act then
    if (text:match(' .-') or text:match('говорит:')) then
        if text:match("Вы тут?") or text:match("Вы тут") or text:match("Вы здесь") or text:match("тyт") or text:match("Вы за компьютером ?") or text:match("Вы за компьютером") or text:match("тут") or text:match("здесь") or text:match("Вы здесь?") or text:match("вы тут?") or text:match("вы тут") or text:match("вы здесь") or text:match("вы здесь?") or text:match("в ы з д е с ь?") or text:match("вы бот?")  or text:match("вы бот") or text:match("Вы бот?") or text:match("ответ в чат") or text:match("ответ в /b") or text:match("ответ в /n") or text:match("Вы на месте?") or text:match("Вы афк?") or text:match("вы тут? ответ в /n") or text:match("Вы тут? Ответ в /n") or text:match("вы тут? ответ в /b") or text:match("Вы тут? Ответ в /b") then
        if os.time() - t > 6 then
        t = os.time()
        lua_thread.create(function(a)
                if k < 1 then
                if not text:match('%d+(%p)%d+') then
                    mute(true)
                        wait(math.random(890, 1039))
                            freezeCharPositionAndDontLoadCollision(ped, true)
                        wait(math.random(3000, 4000))
                        sampSendChat(otveti[math.random(1, #otveti)])
                        freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                    k = k + 1
                elseif not text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                        sampSendChat(povtoriha[math.random(1, #povtoriha)])
                    k = 0
                    freezeCharPositionAndDontLoadCollision(ped, false)
                end
                if text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                    sampSendChat(matemka[math.random(1, #matemka)])
                    freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                end)
                end
            end
            end
        end
    end
и если что все указанные там переменные я указывал в начале кода, это не в них дело
ап

да блина помогите😰
 
Последнее редактирование:

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,790
2,615
Можно ли как-то избавиться от анонимных функций в сея коде?
Lua:
local commands = {
    {command = "!tg", callback = function(text) telegram:sendMessage(text) end},
    {command = "!tram", callback = function(act) runRoute(act) end}
}

registerHandler("onRunCommand", function(cmd)
    for _, data in ipairs(commands) do
        local pattern = ("%s (.+)"):format(data.command)
        if cmd:find(pattern) then
            data.callback(cmd:match(pattern))
            return false       
        end
    end
end)

пишу автоответчик и столкнулся с проблемой, добавил функцию которая при виде:
"(ник чела) говорит: вы тут? вы бот? и тд"
отправляет в чат:
"дада тут, кнш где еще и тд"
но вот только проблема, этого не происходит,вот код:
Lua:
    onServerMessage = function(_, text)
    if act then
    if (text:match(' .-') or text:match('говорит:')) then
        if text:match("Вы тут?") or text:match("Вы тут") or text:match("Вы здесь") or text:match("тyт") or text:match("Вы за компьютером ?") or text:match("Вы за компьютером") or text:match("тут") or text:match("здесь") or text:match("Вы здесь?") or text:match("вы тут?") or text:match("вы тут") or text:match("вы здесь") or text:match("вы здесь?") or text:match("в ы з д е с ь?") or text:match("вы бот?")  or text:match("вы бот") or text:match("Вы бот?") or text:match("ответ в чат") or text:match("ответ в /b") or text:match("ответ в /n") or text:match("Вы на месте?") or text:match("Вы афк?") or text:match("вы тут? ответ в /n") or text:match("Вы тут? Ответ в /n") or text:match("вы тут? ответ в /b") or text:match("Вы тут? Ответ в /b") then
        if os.time() - t > 6 then
        t = os.time()
        lua_thread.create(function(a)
                if k < 1 then
                if not text:match('%d+(%p)%d+') then
                    mute(true)
                        wait(math.random(890, 1039))
                            freezeCharPositionAndDontLoadCollision(ped, true)
                        wait(math.random(3000, 4000))
                        sampSendChat(otveti[math.random(1, #otveti)])
                        freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                    k = k + 1
                elseif not text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                        sampSendChat(povtoriha[math.random(1, #povtoriha)])
                    k = 0
                    freezeCharPositionAndDontLoadCollision(ped, false)
                end
                if text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                    sampSendChat(matemka[math.random(1, #matemka)])
                    freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                end)
                end
            end
            end
        end
    end
и если что все указанные там переменные я указывал в начале кода, это не в них дело
чет там по коду вообще жопа, скинь фулл код, можешь под хайд, завтра разберемся (сейчас накидал чуть, но не могу понять фулл суть без полного кода)
 
Последнее редактирование:

sosnov

Известный
329
115
Можно ли как-то избавиться от анонимных функций в сея коде?
Lua:
local commands = {
    {command = "!tg", callback = function(text) telegram:sendMessage(text) end},
    {command = "!tram", callback = function(act) runRoute(act) end}
}

registerHandler("onRunCommand", function(cmd)
    for _, data in ipairs(commands) do
        local pattern = ("%s (.+)"):format(data.command)
        if cmd:find(pattern) then
            data.callback(cmd:match(pattern))
            return false     
        end
    end
end)


чет там по коду вообще жопа, скинь фулл код, можешь под хайд, завтра разберемся (сейчас накидал чуть, но не могу понять фулл суть без полного кода)
 

Andrinall

Известный
702
518
Можно ли как-то избавиться от анонимных функций в сея коде?

Могу предложить недоговнокод с использованием loadstring
Чисто в теории с таким способом можно дать пользователю самостоятельно ставить обработчики на команды, дав некоторую документацию по использованию.

Lua:
local commands = {
  { command = "!tg", callback = "telegram:sendMessage(arg)" },
  { command = "!tram", callback = "runRoute(arg)" }
}

function loadCodeWithParams(strcode, params)
  local ctx = {}
  setmetatable(ctx, { __index = _G })
  local mt = getmetatable(ctx)
  for k, v in pairs(params) do mt.__index[k] = v end
  local fn = assert(loadstring(strcode))
  setfenv(fn, ctx)
  return fn
end

registerHandler("onRunCommand", function(cmd)
  for _, data in ipairs(commands) do
    local pattern = ("%s (.*)"):format(data.command)
    local arg = cmd:match(pattern)
    if arg then
      loadCodeWithParams(data.callback, { arg=arg })()
      return false
    end
  end
end)
 
Последнее редактирование:
  • Вау
Реакции: whyega52