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

DarkTX

Известный
96
15
Как прочитать несколько строк, идущих подряд? Например список /members или /admins.
Lua:
Администрация online:
Blast_Hack [228] - 10 уровень
Goo_Gl [123]- 6 уровень
Must_Have [321]- 1 уровень
То есть ник, ID и уровень в массив записать, к примеру:
Lua:
local admins = {} -- и как-то чтобы все три значения были в этой таблице, для каждого админа
 

pwned

Участник
142
5
Как сделать массивы так
Чтобы потом в imgui я смог выбрать один пункт и отправить игроку
пример массива

Lua:
local AER_Questions = {
  [1] = "Минимальная цена на продажу/покупку дома",
  [2] = "Минимальная цена на продажу/покупку купона рулетки",
  [3] = "Продам нарко. 20$ грамм",
  [4] = "Куплю рулетку цена 150к",
  [5] = "Продам серебрянные часы и скин 85 цена договорная",
  [6] = "В South Cluckin Bell навигатор 8-13 можно поесть крыс тараканов, жуков",
  [7] = "Ищу девушку для СО. О себе: красивый, талантливый, веселый",
  [8] = "Ищу спонсора для проведения телеигры",
  [9] = "Продам bullet цена 1.1кк",
  [10] = "Куплю эко в гетто",
  [11] = "Продам 'Синяя новогодняя шапка' и золотые часы",
  [12] = "продам симку 'MAMKEQ' 115к"
}
 

Petr_Sergeevich

Известный
Проверенный
707
296
Как сделать массивы так
Чтобы потом в imgui я смог выбрать один пункт и отправить игроку
пример массива

Lua:
local AER_Questions = {
  [1] = "Минимальная цена на продажу/покупку дома",
  [2] = "Минимальная цена на продажу/покупку купона рулетки",
  [3] = "Продам нарко. 20$ грамм",
  [4] = "Куплю рулетку цена 150к",
  [5] = "Продам серебрянные часы и скин 85 цена договорная",
  [6] = "В South Cluckin Bell навигатор 8-13 можно поесть крыс тараканов, жуков",
  [7] = "Ищу девушку для СО. О себе: красивый, талантливый, веселый",
  [8] = "Ищу спонсора для проведения телеигры",
  [9] = "Продам bullet цена 1.1кк",
  [10] = "Куплю эко в гетто",
  [11] = "Продам 'Синяя новогодняя шапка' и золотые часы",
  [12] = "продам симку 'MAMKEQ' 115к"
}
А в чём вопрос, собственно? Ты уже всё написал

Как прочитать несколько строк, идущих подряд? Например список /members или /admins.
Lua:
Администрация online:
Blast_Hack [228] - 10 уровень
Goo_Gl [123]- 6 уровень
Must_Have [321]- 1 уровень
То есть ник, ID и уровень в массив записать, к примеру:
Lua:
local admins = {} -- и как-то чтобы все три значения были в этой таблице, для каждого админа
Lua:
for line in text:gmatch("[^\r\n]+") do
    local nickname, id, score = line:match("(.+) %[(%d+)%] %- (%d+) уровень")
    table.insert(admins, { nickname, id, score })
end

Есть массивы
Lua:
local AER_Questions = {
  [1] = "Минимальная цена на продажу/покупку дома",
  [2] = "Минимальная цена на продажу/покупку купона рулетки",
  [3] = "Продам нарко. 20$ грамм",
  [4] = "Куплю рулетку цена 150к",
  [5] = "Продам серебрянные часы и скин 85 цена договорная",
  [6] = "В South Cluckin Bell навигатор 8-13 можно поесть крыс тараканов, жуков",
  [7] = "Ищу девушку для СО. О себе: красивый, талантливый, веселый",
  [8] = "Ищу спонсора для проведения телеигры",
  [9] = "Продам bullet цена 1.1кк",
  [10] = "Куплю эко в гетто",
  [11] = "Продам 'Синяя новогодняя шапка' и золотые часы",
  [12] = "продам симку 'MAMKEQ' 115к"
}
local AER_Answers = {
  [1] = "100.000$",
  [2] = "70.000$",
  [3] = "LS-N | Продажа чая/сахара/порошка",
  [4] = "LS-N | Куплю купон на рулетку «Royal». Бюджет: 150.000$.",
  [5] = "LS-N | Продам аксессуар «Серебрянные часы» и одежду с биркой «85». Цена: договорная.",
  [6] = "LS-N | Анти-реклама",
  [7] = "LS-N | Поиск для знакомства",
  [8] = "LS-N | Поиск спонсоров запрещен",
  [9] = "LS-N | Продам автомобиль марки «Bullet». Цена: 1.100.000$.",
  [10] = "LS-N | Куплю дом эконом класса в 'Опасном районе'. Цена: договорная.",
  [11] = "LS-N | Продам аксессуары «Синяя новогодняя шапка» и «Золотые часы». Цена: договорная.",
  [12] = "LS-N | Некорректный формат сим-карты"
}

local Chart_Questions = {
  [1] = "С какой должности разрешено брать фургон?",
  [2] = "Интервал между отпусками",
  [3] = "С какой должности можно проводить эфиры?",
  [4] = "С какой должности можно общаться на общей волне?",
  [5] = "Что будет за ношение оружия в открытом виде?",
  [6] = "Что будет за мат в общественных местах",
  [7] = "Что будет за превышение своих полномочий?",
  [8] = "Когда и где проводятся собрания?",
  [9] = "Когда проходят повышения старшего состава?",
  [10] = "Что будет за сон в строю?",
  [11] = "Что будет, если уволиться с должности начинающего работника?",
  [12] = "С какой должности можно брать вертолёт?"
}
local Сhart_Answers = {
  [1] = "Помощник редакции [2], с разрешения старшего состава",
  [2] = "Интервал между отпусками составляет 5 дней",
  [3] = "Эфир без приза разрешено проводить с должности «Репортер», с призом - «Оператор»",
  [4] = "На общей волне можно общаться с должности «Светотехник». Исключения: сообщать о опечатках в объявлениях можно с должности «Помощник редакции».",
  [5] = "Увольнение + ЧС СМИ",
  [6] = "Наказание: Выговор",
  [7] = "Наказание: Увольнения",
  [8] = "Собрания проводятся в Белом Доме 1 раз в неделю (Четверг)",
  [9] = "Повышения старшего состава проходят каждый Вторник, Четверг, Субботу.",
  [10] = "Наказание: Выговор за сон в строю",
  [11] = "ЧС СМИ",
  [12] = "В рабочих целях с редактора, в личных с директора"
}

Lua:
function aer()
    lua_thread.create(function()
        sampSendChat(AER_Questions[aer_question_number])
        wait(200)
        sampAddChatMessage('Правильный ответ: {49AB23}'..AER_Answers[aer_question_number], -1)
        if aer_question_number == 12 then aer_question_number = 0 end
        aer_question_number = aer_question_number+1
    end)
end
Как можно улучшить этот кусок кода
По-моему, всё нормас) Ещё можно записывать AER_Questions[aer_question_number] в переменную, чтобы не обращаться к таблице дважды
 
  • Нравится
Реакции: DarkTX

#kweeZ

Известный
577
122
Можно ли как-то закрывать текущее окно диалога не через sampCloseCurrentDialogWithButton?
 

trefa

Известный
Всефорумный модератор
2,097
1,233
Почему скрипт помирает?
Lua:
local inicfg = require 'inicfg'
local color = {
    text =
    {
        Color = '0xFFFFFF',
    }
}

if not doesFileExist('moonloader/config/AccelPhoneBook.ini') then
    inicfg.save(color, 'AccelPhoneBook.ini')
end

color = inicfg.load(color)
inicfg.save(color, 'AccelPhoneBook.ini')

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('apbcol', function()
        sampShowDialog(2931, '{00F597}AccelPhoneBook', '{FFFFFF}Укажите требуемый Вам цвет', 'Установить', 'Закрыть', 1)
        while true do wait(0)
            local result, button, list, input = sampHasDialogRespond(4567)
            if button == 1 then
                if string.sub('0x', 2) then
                color.text.Color = input
                inicfg.save(color.text.Color)
                else sampAddChatMessage('{00F597}AccelPhoneBook -{FFFFFF}Вы неправильно ввели кодировку цвета или данного цвета не существует', 0x00F597)
                end
            end
        end
    end)
end
В командах нельзя задержку использовать. Да и в конце нету цикла/беск. задержки
 

trefa

Известный
Всефорумный модератор
2,097
1,233
Код:
[ML] (error) AccelPhoneBook.lua: cannot resume non-suspended coroutine
stack traceback:
    [C]: in function 'save'
    E:\GTA San Andreas\moonloader\AccelPhoneBook.lua:26: in function <E:\GTA San Andreas\moonloader\AccelPhoneBook.lua:20>
[ML] (error) AccelPhoneBook.lua: Script died due to an error. (231E51C4)
Lua:
local inicfg = require 'inicfg'
local color = {
    text =
    {
        Color = '0xFFFFFF',
    }
}

if not doesFileExist('moonloader/config/AccelPhoneBook.ini') then
    inicfg.save(color, 'AccelPhoneBook.ini')
end

color = inicfg.load(color)
inicfg.save(color, 'AccelPhoneBook.ini')

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('apbcol', function()
    sampShowDialog(2931, '{00F597}AccelPhoneBook', '{FFFFFF}Укажите требуемый Вам цвет', 'Установить', 'Закрыть', 1)
    lua_thread.create(function()
            while true do wait(0)
                local result, button, list, input = sampHasDialogRespond(4567)
                if button == 1 then
                    if string.sub('0x', 2) then
                    color.text.Color = input
                    inicfg.save(color.text.Color)
                    else sampAddChatMessage('{00F597}AccelPhoneBook -{FFFFFF}Вы неправильно ввели кодировку цвета или данного цвета не существует', 0x00F597)
                    end
                end
            end
        end)
    end)
    wait(-1)
end
Lua:
inicfg.save(color.text.Color, 'AccelPhoneBook.ini')
 
  • Нравится
Реакции: TheRuthArbiter

Quasper

Известный
834
354
Можно ли как-то закрывать текущее окно диалога не через sampCloseCurrentDialogWithButton?
Lua:
local memory = require 'memory'
function enableDialog(bool)
        memory.setint32(sampGetDialogInfoPtr()+40, bool and 1 or 0, true)
        sampToggleCursor(bool)
end

после того как откроется нужный тебе диалог юзай enableDialog(false) и функция просто скроет твой диалог(так же если опять же передать в функцию true то откроет свернутый диалог)
 
  • Нравится
Реакции: #kweeZ

#kweeZ

Известный
577
122
Lua:
local memory = require 'memory'
function enableDialog(bool)
        memory.setint32(sampGetDialogInfoPtr()+40, bool and 1 or 0, true)
        sampToggleCursor(bool)
end

после того как откроется нужный тебе диалог юзай enableDialog(false) и функция просто скроет твой диалог(так же если опять же передать в функцию true то откроет свернутый диалог)
Это конечно годно, но не то :)
 

pwned

Участник
142
5
Как сделать вот такую же хрень с выбором ответа?

rBv8Qsl.jpg
 

Quasper

Известный
834
354
может знает кто почему sampGetListboxItemText(id) возвращает не всю строку
В диалоге такая инфа "Никнейм[id] выговоры ранг"
Возвращает только Никнейм[id]

Как сделать вот такую же хрень с выбором ответа?

rBv8Qsl.jpg
imgui.listBox вроде как
 

#kweeZ

Известный
577
122
Почему время не отсчитывается?

Код:
    if enable then
    lua_thread.create(function()
    local time = os.clock() * 1000 + 1200000
        local rtime = math.floor((time - os.clock() * 1000 ) / 1000)
        local seconds = rtime % 60
        local minutes = math.floor(rtime / 60)
          imgui.Text(u8"Таймер: " ..minutes.. ":" ..seconds)
    end)
end

может знает кто почему sampGetListboxItemText(id) возвращает не всю строку
В диалоге такая инфа "Никнейм[id] выговоры ранг"
Возвращает только Никнейм[id]


imgui.listBox вроде как
Недавно говорили, что вроде баг с этой хней, но это не точно
В чём проблема искать текст через onShowDialog(text) ?
 

Jason2222

Известный
180
3
Ребята, объясните, пожалуйста, как это работает..
Lua:
function info()
    local weather = getWeather(urlset)
end

function getWeather(url)
    async_http_request("GET", url, nil,
    function (response)
        local result = response.text
    end)
    return result
end
Не работает.
P.S. Если просто выводить result - работает.

return в функции используй лучше

Немного не понял.