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

bab0n

Известный
95
10
Попытка сделать так
Lua:
picks = getAllPickups()
Приводит к такому:
attempt to call global 'getAllPickups' (a nil value)
stack traceback:
E:\sa_mp\moonloader\fullghettohelper.lua: in function <E:\sa_mp\moonloader\fullghettohelper.lua:200>
[ML] (error) fullghettohelper.lua: Script died due to an error. (07D15F04)

Возможно баг @FYP
Если есть альтернатива, подскажите пожалуйста
 

Dmitriy Makarov

25.05.2021
Проверенный
2,481
1,113
Попытка сделать так
Lua:
picks = getAllPickups()
Приводит к такому:
attempt to call global 'getAllPickups' (a nil value)
stack traceback:
E:\sa_mp\moonloader\fullghettohelper.lua: in function <E:\sa_mp\moonloader\fullghettohelper.lua:200>
[ML] (error) fullghettohelper.lua: Script died due to an error. (07D15F04)
На MoonLoader 0.27 работает эта функция вроде.
 
  • Нравится
Реакции: bab0n

lorgon

Известный
657
268
Можно ли сохранять объёмные таблицы(больше 300к строк) в ini конфигах? Стоит ли для этого использовать json и есть ли для него библиотека(что-бы самому не писать функции сохранения/чтения и т. п.)
 

AnWu

Guardian of Order
Всефорумный модератор
4,699
5,220
Можно ли сохранять объёмные таблицы(больше 300к строк) в ini конфигах? Стоит ли для этого использовать json и есть ли для него библиотека(что-бы самому не писать функции сохранения/чтения и т. п.)
сомневаюсь, разумно использовать json. либы точно есть, на гитхабе поищи. однако лучше самому написать 4 строки, ладно 8 на две функции
 
  • Нравится
Реакции: lorgon

JustFedot

Известный
282
284
Утро доброе ребята.
Давно меня не было, уже всё позабывал, вот пытаюсь восстановиться.
Подскажите мне пожалуйста, как можно узнать что меня отключило от сервера?
Знаю способ через беск. цикл с sampGetGamestate(), но может можно что-то использовать без беск. цикла....
сомневаюсь, разумно использовать json. либы точно есть, на гитхабе поищи. однако лучше самому написать 4 строки, ладно 8 на две функции
Какраз вопрос по этому поводу.
В чём разница между json и ini если шо то шо то используется в скрипте по сути как текстовый файл? Я всё ещё нуб, объясните пожалуйста.
 
Последнее редактирование:

Aniki

🐰
Администратор
1,225
1,507
Утро доброе ребята.
Давно меня не было, уже всё позабывал, вот пытаюсь восстановиться.
Подскажите мне пожалуйста, как можно узнать что меня отключило от сервера?
Знаю способ через беск. цикл с sampGetGamestate(), но может можно что-то использовать без беск. цикла....

Какраз вопрос по этому поводу.
В чём разница между json и ini если шо то шо то используется в скрипте по сути как текстовый файл? Я всё ещё нуб, объясните пожалуйста.
1. По идее можно это детектить по приходу пакетов с id 32 и 33, но я не тестил, мб там другие числа
2. Разница в формате данных, json является более продвинутым, так как позволяет хранить таблицы с сильной вложенностью, в то время как .ini позволяет лишь хранить пары ключ-значение в различных секциях, то есть от силы два уровня вложенности
 
Последнее редактирование:
  • Нравится
Реакции: JustFedot

JustFedot

Известный
282
284
1. По идее можно это детектить по приходу пакетов с id 32 и 33, но я не тестил, мб там другие числа
2. Разница в формате данных, json является более продвинутым, так как позволяет хранить таблицы с сильной вложенностью, в то время как .ini позволяет лишь хранить пары ключ-значение в различных секциях, то есть от силы два уровня вложенности
Как-то так?

Lua:
function onReceivePacket(id)
    if id == 34 then
        print('Долбаная арз опять упала')
    end
end
Никогда не работал с этим событием так шо лучше уточню.

С json внутри скрипта работать так-же как и с ini, тоесть как с текстовым файлом?
 

Aniki

🐰
Администратор
1,225
1,507
Как-то так?

Код:
function onReceivePacket(id)
    if id == 32 then
        print('Прошла любовь, завяли помидоры, арз опять вылетела...')
    end
end
Никогда не работал с этим событием так шо лучше уточню.

С json внутри скрипта работать так-же как и с ini, тоесть как с текстовым файлом?
Да, как то так, возможно стоит проверять id == 32 or id == 33 так как возможны разные пакеты для потерянного и закрытого соединения.
С json работать очень просто, данные которые следует сохранить нужно держать в одной таблице и перед сохранением в файл делать s = encodeJson(t) и сохранять s как обычный текст в файле, и наоборот, при чтении из файла делать t = decodeJson(s) и на выходе получать сохраненную таблицу.
 
  • Влюблен
Реакции: JustFedot

Carozza

Новичок
2
0
Привет парни, извините конечно за такой вопрос, просто я сейчас переписываю скрипт, и у меня возникла проблема. Я не понимаю каким образом можно сделать так, чтобы сотрудник ПД написав команду которая уже готова /pdmenu выбрал сам себе там ТЭГ и чтобы допустим когда он выходил в патруль, нажимал кнопочку и ТЭГ автоматически шел в рацию который он сам написал. Да и чтобы при обычном разговоре в рацию он шел, очень сильно нужна ваша помощь.
То есть пример:
/r [Тэг который написал сам] Патрулирую район Маркет.
Вот скрины самого скрипта.
n_LrL039Yek.jpg

3b97Qh2KJp0.jpg
 
Последнее редактирование модератором:

Warklot

Участник
112
3
Hi how to display FromPos, destPos, rotation information? like i wanna see numbers but instead i get blank like nothing showing
Lua:
function sampev.onMoveObject(objectId,fromPos,destPos,speed,rotation)

sampAddChatMessage(FromPos, 0xFFD00000)
sampAddChatMessage (destPos, 0xFFD00000)
sampAddChatMessage (rotation, 0xFFD00000)
end
 

Aniki

🐰
Администратор
1,225
1,507
Hi how to display FromPos, destPos, rotation information? like i wanna see numbers but instead i get blank like nothing showing
Lua:
function sampev.onMoveObject(objectId,fromPos,destPos,speed,rotation)

sampAddChatMessage(FromPos, 0xFFD00000)
sampAddChatMessage (destPos, 0xFFD00000)
sampAddChatMessage (rotation, 0xFFD00000)
end
You should use fromPos.x, fromPos.y, fromPos.z and so on to get values from vector3d type. Also, variables in lua are case-sensitive, you typed FromPos instead of fromPos in sampAddChatMessage, dont forget to fix this too
 
Последнее редактирование:
  • Нравится
Реакции: Warklot

Warklot

Участник
112
3
Hi as you can see i check information on moving objects, but i want to check objects information only if they are on my screen.How to do that? i know there is "isObjectOnScreen" but i don't know how to implement it in functions.

Lua:
 function sampev.onMoveObject(objectId,fromPos,destPos,speed,rotation)

if objectId~=1 then
 
sampAddChatMessage(objectId, 0xFFD00000)
 sampAddChatMessage(speed, 0xFFD00000)

   sampAddChatMessage("PosX "..fromPos.x, 0xFFD00000)
   sampAddChatMessage("PosY "..fromPos.y, 0xFFD00000)
    sampAddChatMessage("PosZ "..fromPos.z, 0xFFD00000)
 sampAddChatMessage("destX "..destPos.x, 0xFFD00000)
   sampAddChatMessage("destY "..destPos.y, 0xFFD00000)
    sampAddChatMessage("destZ "..destPos.z, 0xFFD00000)
    sampAddChatMessage("rotationx "..rotation.x, 0xFFD00000)
    sampAddChatMessage("rotationy "..rotation.y, 0xFFD00000)
  sampAddChatMessage("rotationZ "..rotation.z, 0xFFD00000)
end
end
 

Мира

Участник
455
9
как избавиться от флуда? чтобы на 1 игрока только 1 раз прописывалась и всё.
чтобы было не - если игрок рядом, то постоянно пишется это
а было - если игрок рядом, то напишется раз и всё
Lua:
local peds = getAllChars() -- объявляем массив с хэндлами всех созданных персонажей, включая персонажа игрока.
local res, ped = sampGetCharHandleBySampPlayerId(id)
for _, v in pairs(peds) do -- организуем перебор элементов массива через цикл for
    local result, id = sampGetPlayerIdByCharHandle(v) -- получаем ID игрока через хэндл-элемент массива
    local _, my_id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- отводим отдельную переменную конкретно под собственный ID
    local x, y, z = getCharCoordinates(PLAYER_PED)
    local mX, mY, mZ = getCharCoordinates(v)
    local dist = getDistanceBetweenCoords3d(x, y, z, mX, mY, mZ)
    if result and id ~= my_id and dist <= 5 then -- проверяем успешность; не является ли ID твоим (чтобы не отправить сообщение самому себе)
        --sampAddChatMessage(id, -1) -- выполняем конкантенсацию и отправляем строку в чат
        sampAddChatMessage('Дистанция между вами: '..dist, 0x00DD00)
        --sampAddChatMessage('++', -1)
    end -- закрываем блок условного оператора
end -- закрываем цикл for
 

Aniki

🐰
Администратор
1,225
1,507
как избавиться от флуда? чтобы на 1 игрока только 1 раз прописывалась и всё.
чтобы было не - если игрок рядом, то постоянно пишется это
а было - если игрок рядом, то напишется раз и всё
Lua:
local peds = getAllChars() -- объявляем массив с хэндлами всех созданных персонажей, включая персонажа игрока.
local res, ped = sampGetCharHandleBySampPlayerId(id)
for _, v in pairs(peds) do -- организуем перебор элементов массива через цикл for
    local result, id = sampGetPlayerIdByCharHandle(v) -- получаем ID игрока через хэндл-элемент массива
    local _, my_id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- отводим отдельную переменную конкретно под собственный ID
    local x, y, z = getCharCoordinates(PLAYER_PED)
    local mX, mY, mZ = getCharCoordinates(v)
    local dist = getDistanceBetweenCoords3d(x, y, z, mX, mY, mZ)
    if result and id ~= my_id and dist <= 5 then -- проверяем успешность; не является ли ID твоим (чтобы не отправить сообщение самому себе)
        --sampAddChatMessage(id, -1) -- выполняем конкантенсацию и отправляем строку в чат
        sampAddChatMessage('Дистанция между вами: '..dist, 0x00DD00)
        --sampAddChatMessage('++', -1)
    end -- закрываем блок условного оператора
end -- закрываем цикл for
Если оно у тебя флудит, то этот код вызывается или в бесконечном цикле, или в событии которое постоянно триггерится
Hi as you can see i check information on moving objects, but i want to check objects information only if they are on my screen.How to do that? i know there is "isObjectOnScreen" but i don't know how to implement it in functions.

Lua:
 function sampev.onMoveObject(objectId,fromPos,destPos,speed,rotation)

if objectId~=1 then

sampAddChatMessage(objectId, 0xFFD00000)
sampAddChatMessage(speed, 0xFFD00000)

   sampAddChatMessage("PosX "..fromPos.x, 0xFFD00000)
   sampAddChatMessage("PosY "..fromPos.y, 0xFFD00000)
    sampAddChatMessage("PosZ "..fromPos.z, 0xFFD00000)
sampAddChatMessage("destX "..destPos.x, 0xFFD00000)
   sampAddChatMessage("destY "..destPos.y, 0xFFD00000)
    sampAddChatMessage("destZ "..destPos.z, 0xFFD00000)
    sampAddChatMessage("rotationx "..rotation.x, 0xFFD00000)
    sampAddChatMessage("rotationy "..rotation.y, 0xFFD00000)
  sampAddChatMessage("rotationZ "..rotation.z, 0xFFD00000)
end
end
isObjectOnScreen requires object handle as arguement, which could be obtained by using sampGetObjectHandleBySampId(int id)
 
  • Нравится
Реакции: Warklot

Warklot

Участник
112
3
It presses space button but it doesn't release after wait time
Lua:
if speed>0.30 then
setVirtualKeyDown(VK_SPACE, true)
wait(100)
setVirtualKeyDown(VK_SPACE, false)
       end