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

SAMP.ASI

Известный
223
53
[16:31:34.172477] (error) obossal: D:\GAMES\samp\1036\moonloader\test.lua:41: attempt to yield across C-call boundary
stack traceback:
[C]: in function 'wait'
D:\GAMES\samp\1036\moonloader\obossal.lua:41: in function <D:\GAMES\samp\1036\moonloader\test.lua:38>

Lua:
function heal(arg)
if arg ~= nil then
sampSendChat('/me внимательно осмотрел пациента')
wait(10)
sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена 200')
wait(10)
sampSendChat('/do Через плечо надета мед. сумка')
wait(10)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(10)
sampSendChat('/me передал лекарство пациенту')
wait(10)
sampSendChat(string.format('/medhelp %s 200', tostring(arg)))
end
end
Что я делаю не так? Как сделать задержку?
 

for (;;)

Участник
71
31
[16:31:34.172477] (error) obossal: D:\GAMES\samp\1036\moonloader\test.lua:41: attempt to yield across C-call boundary
stack traceback:
[C]: in function 'wait'
D:\GAMES\samp\1036\moonloader\obossal.lua:41: in function <D:\GAMES\samp\1036\moonloader\test.lua:38>

Lua:
function heal(arg)
if arg ~= nil then
sampSendChat('/me внимательно осмотрел пациента')
wait(10)
sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена 200')
wait(10)
sampSendChat('/do Через плечо надета мед. сумка')
wait(10)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(10)
sampSendChat('/me передал лекарство пациенту')
wait(10)
sampSendChat(string.format('/medhelp %s 200', tostring(arg)))
end
end
Что я делаю не так? Как сделать задержку?
Lua:
function heal(arg)
if arg ~= nil then
    lua_thread.create(function()
sampSendChat('/me внимательно осмотрел пациента')
wait(10)
sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена 200')
wait(10)
sampSendChat('/do Через плечо надета мед. сумка')
wait(10)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(10)
sampSendChat('/me передал лекарство пациенту')
wait(10)
sampSendChat(string.format('/medhelp %s 200', tostring(arg))) end)
end
end
 
  • Нравится
Реакции: SAMP.ASI

SAMP.ASI

Известный
223
53
Lua:
function heal(arg)
if arg ~= nil then
    lua_thread.create(function()
sampSendChat('/me внимательно осмотрел пациента')
wait(10)
sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена 200')
wait(10)
sampSendChat('/do Через плечо надета мед. сумка')
wait(10)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(10)
sampSendChat('/me передал лекарство пациенту')
wait(10)
sampSendChat(string.format('/medhelp %s 200', tostring(arg))) end)
end
end
Спасибо, как еще сделать два аргумента? Чтоб было /test 1 100
sampSendChat(string.format('/medhelp %s %s', tostring(arg1), tostring(arg2))) end)
 

SAMP.ASI

Известный
223
53
Lua:
function heal(args)
    arg1, arg2 = args:match("(%d+)%s(%d+)")
    ...
end
И последний вопрос.

sampSendChat(string.format('medhelp %s %s', tostring(arg1), tostring(arg2))) end) - работает

sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена %s', tostring(arg1)) - null значение

Lua:
function heal(arg)
if arg ~= nil then
arg1, arg2 = arg:match("(%d+)%s(%d+)")
lua_thread.create(function()
sampSendChat('/me внимательно осмотрел пациента')
wait(400)
sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена %s', tostring(arg1))
wait(400)
sampSendChat('/do Через плечо надета мед. сумка')
wait(400)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(400)
sampSendChat('/me передал лекарство пациенту')
wait(400)
sampSendChat(string.format('medhelp %s %s', tostring(arg1), tostring(arg2))) end)
end
end
 

for (;;)

Участник
71
31
И последний вопрос.

sampSendChat(string.format('medhelp %s %s', tostring(arg1), tostring(arg2))) end) - работает

sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена %s', tostring(arg1)) - null значение

Lua:
function heal(arg)
if arg ~= nil then
arg1, arg2 = arg:match("(%d+)%s(%d+)")
lua_thread.create(function()
sampSendChat('/me внимательно осмотрел пациента')
wait(400)
sampSendChat('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена %s', tostring(arg1))
wait(400)
sampSendChat('/do Через плечо надета мед. сумка')
wait(400)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(400)
sampSendChat('/me передал лекарство пациенту')
wait(400)
sampSendChat(string.format('medhelp %s %s', tostring(arg1), tostring(arg2))) end)
end
end
Lua:
function heal(arg)
if arg ~= nil then
arg1, arg2 = arg:match("(%d+)%s(%d+)")
lua_thread.create(function()
sampSendChat('/me внимательно осмотрел пациента')
wait(400)
sampSendChat(string.format('/todo Поставив пациенту диагноз*Я выпишу вам лекарство. Его цена %s', tostring(arg1)))
wait(400)
sampSendChat('/do Через плечо надета мед. сумка')
wait(400)
sampSendChat('/me Залез рукой в мед. сумку и достал лекарство')
wait(400)
sampSendChat('/me передал лекарство пациенту')
wait(400)
sampSendChat(string.format('medhelp %s %s', tostring(arg1), tostring(arg2))) end)
end
end
 
  • Нравится
Реакции: SAMP.ASI

ШPEK

Известный
1,474
525
Как сделать получение переменной из ini файла, и создание ini с таблицей, если его не существует.
 

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Как сделать получение переменной из ini файла, и создание ini с таблицей, если его не существует.
Lua:
local inicfg = require 'inicfg'

-- производить загрузку кофигов можно и вне 'main'
local mainIni = inicfg.load({
  settings =
  {
   title = "text",
   text_color = "0xAABBCC"
  },
  location =
  {
   width = 100,
   height = 200,
   pos_x = 20,
   pos_y = 50
  }
}) -- загрузим основной конфиг. путь к файлу не указан, а значит будет загружен файл по пути ./moonloader/config/example.lua.ini

function main()
  -- таблица со значениями по умолчаниями не указана, поэтому если файл не удастся прочитать, будет возвращён nil
  local anotherIni = inicfg.load(nil, "example_another_config")
  -- если файл был успешно загружен
  if anotherIni ~= nil then
   -- выводим прочитанные значения
   print("Old value 1 = " .. anotherIni.main.value1)
   print("Old value 2 = " .. anotherIni.main.value2)
   -- просто сгенерируем 2 случайных значения
   local newV1, newV2 = math.random(100, 1000), math.random(100, 1000)
   -- теперь создадим таблицу с новыми значениями
   local newData = {
     main = {
       value1 = newV1,
       value2 = newV2,
       -- и добавим к ним сумму этих двух значений
       sum = newV1 + newV2
     }
   }
   -- можно сохранять
   if inicfg.save(newData, "example_another_config") then
     print("Success.")
   end
  end

  -- выведем основной конфиг
  print(mainIni.settings.title .. ", color = " .. mainIni.settings.text_color)
  print("Position: ", mainIni.location.pos_x, mainIni.location.pos_y, "Size: ", mainIni.location.width, mainIni.location.height)
  -- отредактируем и сохраним его
  mainIni.settings.title = "Hello"
  mainIni.location.pos_x = 100
  mainIni.location.pos_y = 75
  inicfg.save(mainIni)
end
 

BND / PLP

Новичок
84
4
есть ли функция которая проверяет видимость ника на экране?
 
Последнее редактирование:

ШPEK

Известный
1,474
525
Lua:
require 'inicfg'
require 'lib.moonloader'

local inicfg = inicfg.load({
tags =
{
tag1 = "tag2",
tag2 = "tag1"
}
})

function main()
inicfg.save(inicfg, "tags")
inicfg.load(nil, "tags")
sampAddChatMessage(inicfg.tags.tag1.." "..inicfg.tags.tag2, -1)
end
Почему не работает?
[ML] (system) filescfd.lua: Script terminated. (186FD58C)
[ML] (error) D:\gta\moonloader\filescfd.lua:4: attempt to index global 'inicfg' (a nil value)
stack traceback:
D:\gta\moonloader\filescfd.lua:4: in main chunk
 

f0rtrix

Известный
208
15
Привет, скиньте пример imgui.InputText, где вводится, допустим nickname игрока, затем если туда введена информация, то создается условие сохранения этих данных. У меня примерно такая история
Lua:
local inicfg = require 'inicfg'
--
local enickname = imgui.ImBuffer(tostring(mainIni.nick.nickname), 256)
local erange = imgui.ImBuffer(tostring(mainIni.rang.range), 256)
local ework = imgui.ImBuffer(tostring(mainIni.worke.work), 256)
local enumb = imgui.ImBuffer(tostring(mainIni.number.numb), 256)
local etag = imgui.ImBuffer(tostring(mainIni.teg.tag), 256)
-- Написано так через жопу ибо если все писать, допустим в "nick", то выдавало бы ошибку
local mainIni = inicfg.load({
    nick =
    {
        nickname = ""
    },
    worke =
    {
        work = ""
    },
    rang =
    {
        range = ""
    },
    number =
    {
        numb = ""
    },
    teg
    {
        tag = ""
    }
}, "NameCfg")
-- в main
        function onScriptTerminate(script, quitGame)
            if script == thisScript() then
                if not doesDirectoryExist("moonloader\\config") then
                    createDirectory("moonloader\\config")
                end
                inicfg.save(mainIni, "Government_Helper")
                patches('SAMP_PATCH_SCOREBOARDTOGGLEON', true)
                patches('SAMP_PATCH_SCOREBOARDTOGGLEONKEYLOCK', true)
            end
        end
-- в function imgui.OnDrawFrame():
    imgui.InputText(u8"##nickname", nickname)
Ну и в итоге ничего не работает:
attempt to index global 'mainIni' (a nil value)
stack traceback:
D:\Games\GTA_San_Andreas-0.2\moonloader\gHelper.lua:22: in main chunk
ps: немного кода беру у @DonHomka
pss: надеюсь ты не против (ибо я ваще не шарю)
 
Последнее редактирование:

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
есть ли функция которая проверяют видимость ника на экране?
функции нету. в структуре stRemotePlayerData есть:
int iShowNameTag;

ошибку надеюсь ты понял.

local enickname = imgui.ImBuffer(tostring(mainIni.nick.nickname), 256) local erange = imgui.ImBuffer(tostring(mainIni.rang.range), 256) local ework = imgui.ImBuffer(tostring(mainIni.worke.work), 256) local enumb = imgui.ImBuffer(tostring(mainIni.number.numb), 256) local etag = imgui.ImBuffer(tostring(mainIni.teg.tag), 256) -- Написано так через жопу ибо если все писать, допустим в "nick", то выдавало бы ошибку
этот код после inicfg.load

Lua:
require 'inicfg'
require 'lib.moonloader'

local inicfg = inicfg.load({
tags =
{
tag1 = "tag2",
tag2 = "tag1"
}
})

function main()
inicfg.save(inicfg, "tags")
inicfg.load(nil, "tags")
sampAddChatMessage(inicfg.tags.tag1.." "..inicfg.tags.tag2, -1)
end
Почему не работает?
[ML] (system) filescfd.lua: Script terminated. (186FD58C)
[ML] (error) D:\gta\moonloader\filescfd.lua:4: attempt to index global 'inicfg' (a nil value)
stack traceback:
D:\gta\moonloader\filescfd.lua:4: in main chunk
inicfg = require 'inicfg'
назови название таблицы файла по-другому.
 
Последнее редактирование: