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

CAPTA!N

Новичок
220
49
Lua:
Functions =
{
    {name = 'Inv', data = {}},
    {name = 'AirBrk', data = {}},
    {name = 'FastWalk', data = {}},
    {name = 'NoFall', data = {}}
}
.
.
.
for k,v in pairs(Functions) do
        Functions[k].data = {activated = false, extra = nil}
        FuncsOptimize[v.name] = k
    end
Не пойму как for перебирает каждое значение массива, почему k,v? И почему дальше в массив Functions массив записывается как то странно (Functions[k].data)?
 

itsLegend

Фонд борьбы за жуков 🐞
Администратор
2,695
1,448
Не пойму как for перебирает каждое значение массива, почему k,v?
Можешь юзать key,value вместо k,v - дело личное. Можешь вместо pairs использовать ipairs и тогда будет возвращаться индекс(номер) элемента и значение, он также подходит и для этого примера, а вот к примеру этот массив ниже не сможет обрабатываться с помощью ipairs, но зато сможет с помощью pairs:
Lua:
Functions =
{
    func1 = {name = 'Inv', data = {}},
    func2 = {name = 'AirBrk', data = {}},
    func3 = {name = 'FastWalk', data = {}},
    func4 = {name = 'NoFall', data = {}}
}

for k,v in pairs(Functions) do
        Functions[k].data = {activated = false, extra = nil}
        -- print(k)
    end
Почитать тоже можно на досуге, нежели так тяжело? Это не очень тяжелая информация для переваривания.

И почему дальше в массив Functions массив записывается как то странно (Functions[k].data)?
Относительно странно чего? Вроде бы логично всё. В массив под индексом k записывается значение, а именно - таблица с полями activated и extra.
 
  • Нравится
Реакции: darkjer

CAPTA!N

Новичок
220
49
Можешь юзать key,value вместо k,v - дело личное. Можешь вместо pairs использовать ipairs и тогда будет возвращаться индекс(номер) элемента и значение, он также подходит и для этого примера, а вот к примеру этот массив ниже не сможет обрабатываться с помощью ipairs, но зато сможет с помощью pairs:
Lua:
Functions =
{
    func1 = {name = 'Inv', data = {}},
    func2 = {name = 'AirBrk', data = {}},
    func3 = {name = 'FastWalk', data = {}},
    func4 = {name = 'NoFall', data = {}}
}

for k,v in pairs(Functions) do
        Functions[k].data = {activated = false, extra = nil}
        -- print(k)
    end
Почитать тоже можно на досуге, нежели так тяжело? Это не очень тяжелая информация для переваривания.
Для меня эта инфа достаточно тяжелая, но интересная. Каждый день читаю, пытаюсь вникнуть. Для меня просто логически не понятно как оно все там работает
Относительно странно чего? Вроде бы логично всё. В массив под индексом k записывается значение, а именно - таблица с полями activated и extra.
.data - что оно делает?
 

Devlish

Новичок
13
15
Подскажите что означает ошибка "attempt to yield across C-call boundary" и как от нее избавиться.
Код уже переписал, но хочется узнать. Пробовал зарегать свою команду функцией sampRegisterChatCommand("cmd", func) и внутри func создал цикл. В результате скрипт вылетал с этой ошибкой и указанием на wait(0) в цикле этой функции.
 

4el0ve4ik

Известный
Всефорумный модератор
1,548
1,338
Подскажите что означает ошибка "attempt to yield across C-call boundary" и как от нее избавиться.
Код уже переписал, но хочется узнать. Пробовал зарегать свою команду функцией sampRegisterChatCommand("cmd", func) и внутри func создал цикл. В результате скрипт вылетал с этой ошибкой и указанием на wait(0) в цикле этой функции.
wait нельзя использовать в функциях кроме main() и тех что вызываются в ней, используй
Код:
function main()
  if doStuff then
    -- do something
    doStuff = false
  end
end

function command(arg)
  doStuff = true
end
 
  • Нравится
Реакции: applethecandy и Devlish

applethecandy

Now it's PHP time
Проверенный
253
328
Код:
ResultProcessLineOfSight, CollisionTable = processLineOfSight(PX, PY, PZ, NBX, NBY, NBZ, true, true, true, true, true, false, false)
  BarrierX = CollisionTable[float pos[1]]
Вроде сделал правильно - ввёл название переменной, ввёл название таблицы, ввёл имя поля, ввёл номер в поле (взял с вики и учебников по таблицам), но мне выдаёт ошибку ._.
Если я забью флот в скобки, он превратится в строку, из переменной, и будет ещё хуже, или я не прав?
Помогите разобраться, пожалуйста
Код:
']' expected near 'pos'
слово float перед pos вообще удали. Из-за него и ошибка, оно там не нужно.
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
@Снежок пример использования processLineOfSight можешь посмотреть в скрипте ClickWarp, который был опубликован вместе c релизом.
 
Последнее редактирование модератором:
  • Нравится
Реакции: ishi

FYP

Известный
Автор темы
Администратор
1,758
5,722
CLEO:
0b34: samp "add" @add

:add
0B35: samp 0@ = get_last_command_params
if 0AD4: 0@ = scan_string 0@ format "%d %d" 1@ 2@
then
005A: 1@ += 2@ // (int)
0af9: "%d" 1@
end
0B12: 21@ = 21@ XOR 1
Samp.CmdRet()

Как сделать аналог на Lua? Вообще как обработать 2 параметра в одной функции?
Lua:
function cmd_asdfasdfa(param)
local p1, p2 = string.match(param, "(%d+)%s+(%d+)")
print(p1, p2)
end
http://linuxru.org/blog-xxblx/343
 
  • Нравится
Реакции: Сэнд

FYP

Известный
Автор темы
Администратор
1,758
5,722
спасибо, а вообще как сделать, чтобы функция работала с двумя параметрами?
видел только пример с одним параметром
Lua:
function cmdSetWeather(param)
  local weather = tonumber(param)
  if weather ~= nil and weather >= 0 and weather <= 45 then
    forceWeatherNow(weather)
  end
end
ну так и делать, с помощью string.match. вон же код
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
Я просто неудачный пример привёл. Допустим 2 независимых друг от друга параметра в одной команде, как их совместить?
ох... ладно...

Lua:
function main()
while not isSampAvailable() do wait(100) end
sampRegisterChatCommand("hparmor", cmd_hparmor)
wait(-1)
end

function cmd_hparmor(param)
local health, armor = string.match(param, "(%d+)%s+(%d+)")
setCharHealth(playerPed, health)
addArmourToChar(playerPed, -100)
addArmourToChar(playerPed, armor)
printStringNow(string.format("Health set to %d, armor to %d", health, armor), 3000)
end
пример вызова команды: /hparmor 50 70
будет выдано 50 здоровья и 70 брони.
так понятно?
 
  • Нравится
Реакции: Garrus и Сэнд

applethecandy

Now it's PHP time
Проверенный
253
328
ох... ладно...

Lua:
function main()
while not isSampAvailable() do wait(100) end
sampRegisterChatCommand("hparmor", cmd_hparmor)
wait(-1)
end

function cmd_hparmor(param)
local health, armor = string.match(param, "(%d+)%s+(%d+)")
setCharHealth(playerPed, health)
addArmourToChar(playerPed, -100)
addArmourToChar(playerPed, armor)
printStringNow(string.format("Health set to %d, armor to %d", health, armor), 3000)
end
пример вызова команды: /hparmor 50 70
будет выдано 50 здоровья и 70 брони.
так понятно?
А нельзя, допустим, function noName(param1, param2)?