Вопросы по 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
Иными словами, если активация не произошла сразу после начала цикла, то функция main завершается
Не подскажешь как мне вернуть выполнение скрипта на начало. Т.е. что бы проверка выполнялась, только тогда, когда все условия будут выполнены? Мне кажеться что можно использовать while, тогда скрипт не будет идти дальше, покуда не будут выполнены все условия.

И второй вопрос. Как мне сделать цикл, который не будет в основной функции? Мне нужно повторять проверку условия, пока оно не будет выполнено. Я делаю так:
repeat
wait(0)
result, bla, bla = pop_event_dialoga
until result
В основной функции регистрируется команда, поэтому я не могу закинуть цикл в нее.
ну так а в логе что?
Скорее всего все норм, приду домой - чекну
 

SR_team

like pancake
BH Team
4,720
6,369
В "больших" языках принято использовать в таких случаях continue вместо return. Но Lua этого не умеет. А значит при активации изменяй значение переменной, нопример _enabled и далее используй условие для выполнения нужной части кода
 
  • Нравится
Реакции: CAPTA!N

CAPTA!N

Новичок
220
49
В "больших" языках принято использовать в таких случаях continue вместо return. Но Lua этого не умеет. А значит при активации изменяй значение переменной, нопример _enabled и далее используй условие для выполнения нужной части кода
Не совсем понял. Вроде так?
if isKeyDown(87) and isKeyJustPressed(88) and isCharInAnyCar(playerPed) then
bla = 1
else bla =0 end
if bla ==1 then
body
end
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
Не совсем понял. Вроде так?
if isKeyDown(87) and isKeyJustPressed(88) and isCharInAnyCar(playerPed) then
bla = 1
else bla =0 end
if bla ==1 then
body
end
почти. так:
Lua:
if isKeyDown(87) and isKeyJustPressed(88) and isCharInAnyCar(playerPed) then
bla = not bla
end
if bla then
body
end
Как мне сделать цикл, который не будет в основной функции? Мне нужно повторять проверку условия, пока оно не будет выполнено. Я делаю так:
repeat
wait(0)
result, bla, bla = pop_event_dialoga
until result
а зачем? его можно и в основной засунуть, такое не будет создавать никаких проблем.
 
Последнее редактирование:
  • Нравится
Реакции: CAPTA!N и 4el0ve4ik

4el0ve4ik

Известный
Всефорумный модератор
1,548
1,338
Спасибо большое, приду домой - попробую.

И вот похоже не заметили:
И второй вопрос. Как мне сделать цикл, который не будет в основной функции? Мне нужно повторять проверку условия, пока оно не будет выполнено. Я делаю так:
repeat
wait(0)
result, bla, bla = pop_event_dialoga
until result
В основной функции регистрируется команда, поэтому я не могу закинуть цикл в нее.
Код:
function main()
  if doStuff then
    -- do something
    doStuff = false
  end
end

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

CAPTA!N

Новичок
220
49
а зачем? его можно и в основной засунуть, такое не будет создавать никаких проблем.
Ну так как я его закину туда, если в опкоде регистрации команды нужно указывать функцию, которая будет выполняться? Т.е. тело скрипта будет выполняться в другой функции.
 

4el0ve4ik

Известный
Всефорумный модератор
1,548
1,338
Ну так как я его закину туда, если в опкоде регистрации команды нужно указывать функцию, которая будет выполняться? Т.е. тело скрипта будет выполняться в другой функции.
Именно, я же тебе кино пример, мне Фип его кидал
 
  • Нравится
Реакции: CAPTA!N

FYP

Известный
Автор темы
Администратор
1,758
5,722
Ну так как я его закину туда, если в опкоде регистрации команды нужно указывать функцию, которая будет выполняться? Т.е. тело скрипта будет выполняться в другой функции.
до меня всё равно не доходит в чем проблема. покажи код, который, как ты считаешь, будет нерабочим.
 
  • Нравится
Реакции: CAPTA!N

CAPTA!N

Новичок
220
49
до меня всё равно не доходит в чем проблема. покажи код, который, как ты считаешь, будет нерабочим.
Lua:
function main()
   if not isSampfuncsLoaded() or not isSampLoaded() then return end
    sampRegisterChatCommand("inta", dialog)
   while true do wait(0) end
end

function dialog()
    sampShowDialog(13, "стадион 8 \nСтадион Дерби"), "Магия", "Координаты", 2)
   sampSetCurrentDialogListItem(0)
   repeat
     wait(0)
     re, but, list, input = sampHasDialogRespond(13)
   until re
       if list == 0 --[[id элемента диалога]] then setCharCoordinates(playerPed, -1398.103515, 937.631164, 1036.479125)
setInteriorVisible(11)
setCharInterior(playerPed, 11)
end
       if list == 1 then setCharCoordinates(playerPed, -1398.065307, -217.028900, 1051.115844)
setInteriorVisible(5)
setCharInterior(playerPed, 5)
end
end
Так как цикл не в function mail, то игра крашит
 

4el0ve4ik

Известный
Всефорумный модератор
1,548
1,338
Lua:
function main()
   if not isSampfuncsLoaded() or not isSampLoaded() then return end
    sampRegisterChatCommand("inta", dialog)
   while true do wait(0) end
end

function dialog()
    sampShowDialog(13, "стадион 8 \nСтадион Дерби"), "Магия", "Координаты", 2)
   sampSetCurrentDialogListItem(0)
   repeat
     wait(0)
     re, but, list, input = sampHasDialogRespond(13)
   until re
       if list == 0 --[[id элемента диалога]] then setCharCoordinates(playerPed, -1398.103515, 937.631164, 1036.479125)
setInteriorVisible(11)
setCharInterior(playerPed, 11)
end
       if list == 1 then setCharCoordinates(playerPed, -1398.065307, -217.028900, 1051.115844)
setInteriorVisible(5)
setCharInterior(playerPed, 5)
end
end
Так как цикл не в function mail, то игра крашит
Перенести сам в маин или жди покуда закончится учёба)
 
  • Нравится
Реакции: CAPTA!N

FYP

Известный
Автор темы
Администратор
1,758
5,722
Lua:
function main()
   if not isSampfuncsLoaded() or not isSampLoaded() then return end
    sampRegisterChatCommand("inta", dialog)
   while true do wait(0) end
end

function dialog()
    sampShowDialog(13, "стадион 8 \nСтадион Дерби"), "Магия", "Координаты", 2)
   sampSetCurrentDialogListItem(0)
   repeat
     wait(0)
     re, but, list, input = sampHasDialogRespond(13)
   until re
       if list == 0 --[[id элемента диалога]] then setCharCoordinates(playerPed, -1398.103515, 937.631164, 1036.479125)
setInteriorVisible(11)
setCharInterior(playerPed, 11)
end
       if list == 1 then setCharCoordinates(playerPed, -1398.065307, -217.028900, 1051.115844)
setInteriorVisible(5)
setCharInterior(playerPed, 5)
end
end
Так как цикл не в function mail, то игра крашит

понятно. тут нужно делать как предложил 4el0ve4ik, т.к. в обработчике команды нельзя использовать задержки.
Lua:
function main()
   if not isSampfuncsLoaded() or not isSampLoaded() then return end
   sampRegisterChatCommand("inta", dialog)
   
   while true do
     wait(0)
     if processDialog then
       processDialog = false
       repeat
         wait(0)
         local re, but, list, input = sampHasDialogRespond(13)
       until re
       if list == 0 --[[id элемента диалога]] then
         setCharCoordinates(playerPed, -1398.103515, 937.631164, 1036.479125)
         setInteriorVisible(11)
         setCharInterior(playerPed, 11)
       end
       if list == 1 then
         setCharCoordinates(playerPed, -1398.065307, -217.028900, 1051.115844)
         setInteriorVisible(5)
         setCharInterior(playerPed, 5)
       end
     end
   end
end

function dialog()
   sampShowDialog(13, "стадион 8 \nСтадион Дерби"), "Магия", "Координаты", 2)
   sampSetCurrentDialogListItem(0)
   processDialog = true
end
 
  • Нравится
Реакции: CAPTA!N