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

Revavi

Участник
101
24
кто знает как правильно проверять /stats при заходе на сервер и запуске скрипта?
ну тоесть, есть ли какой то rpc, который отвечает за то, авторизован ли игрок или чёт такое
 

Макс | Lycorn

Участник
156
13
@Макс | Lycorn
Lua:
-- функция json'а
-- чтение: fjson(путь_файл_json):read()
-- запись: fjson(путь_файл_json):write(таблица)

function fjson(filePath)
    local f = {}
    function f:read()
        local f = io.open(filePath, "r+")
        local jsonInString = f:read("*a")
        f:close()
        local jsonTable = decodeJson(jsonInString)
        return jsonTable
    end
    function f:write(t)
        f = io.open(filePath, "w")
        f:write(encodeJson(t))
        f:flush()
        f:close()
    end
    return f
end

-- если нет такой папки myCustomFolder в moonloader, то создает
if not doesDirectoryExist('moonloader/myCustomFolder') then
    createDirectory('moonloader/myCustomFolder')
end

-- {GTA_SA_Folder}/moonloader/myCustomFolder/SETTINGS.json
local jsonFilePath_Settings = getWorkingDirectory()..'/myCustomFolder/SETTINGS.json'

-- проверяет на существование файла SETTINGS.json в папке myCustomFolder
if not doesFileExist(jsonFilePath_Settings) then
    fjson(jsonFilePath_Settings):write({
        listBinder = {
            {
                title = 'Заголовка биндера',
                cooldown = 1 * 1000 -- милисек
                textarea = [[/n 1
/n 2
/n 3
/n 4]],
                is_active = true, -- если неактивна, то этот биндер скрываешь в имгуи
            }
        }
    })
end

-- возвращает таблицы json
-- рекомендую указывать в внутри функции (например, для команды /checkjson и т.д.), не в тело скрипта!
local listSettings = fjson(jsonFilePath_Settings):read()

-- например, чтобы вывести статусы у каждой биндов в таблице listSettings
for i=1, #listSettings do
    print('['..i..'] Title: "'..tostring(listSettings[i].title)..'". Is active: '..(is_active and 'enabled' or 'disabled'))
end
Уф, не разу не делал сохранение через js ) Попробую сегодня

Как сделать подключение 2 и более ini файлов в скрипт?
 

kyrtion

Известный
631
231
кто знает как правильно проверять /stats при заходе на сервер и запуске скрипта?
ну тоесть, есть ли какой то rpc, который отвечает за то, авторизован ли игрок или чёт такое
1. true connect о том что зашел на коннектов сервера.
2. Если успешно авторизован и прочее херни, то ищем положительное connect и спавн педа (sampIsLocalPlayerSpawned())
3. Если заспавнен, то connect false, прописываем /stats.
*. Если вдруг отсоединится снова - то connect ставить true и переходим на 2.

Уф, не разу не делал сохранение через js ) Попробую сегодня

Как сделать подключение 2 и более ini файлов в скрипт?
js это javascript, а json - это и есть json. не путайтесь
 
  • Нравится
Реакции: Revavi и tyukapa

tyukapa

Активный
298
65
Здравствуйте, как можно сделать проверку на то, находится ли игрок на определённых координатах? (Независимо от координат по высоте, Z)
 

XRLM

Известный
2,532
847
Как сделать подключение 2 и более ini файлов в скрипт?
так же, как и первый ини

Здравствуйте, как можно сделать проверку на то, находится ли игрок на определённых координатах? (Независимо от координат по высоте, Z)
Lua:
local x, y, z = getCharCoordinates(handle)
local xx, yy = 0, 0 -- корды на которых должен быть игрок
if x == 0 and y == 0 then

end

Здраствуйте, как сделать нажатие стрелочки вправо? когда пишу
setVirtualKeyDown(VK_RIGHT, true) то нажимается Numpad6 который не работает в игре
отправляй через setGameKeyState или через синхру
 
  • Нравится
Реакции: tyukapa

tyukapa

Активный
298
65
Lua:
local x, y, z = getCharCoordinates(handle)
local xx, yy = 0, 0 -- корды на которых должен быть игрок
if x == 0 and y == 0 then

end
Скрипт начинает работать как нужно, потом когда доходит до нужных координат ничего не происходит.

Lua:
                runToPoint:run(2480, -1668)
                local x, y, z = getCharCoordinates(PLAYER_PED)
                local xx, yy = 2480, -1668
                if x == 2480 and y == -1668 then
                    runToPoint:run(2452, -1667)
                end
 

XRLM

Известный
2,532
847
Скрипт начинает работать как нужно, потом когда доходит до нужных координат ничего не происходит.

Lua:
                runToPoint:run(2480, -1668)
                local x, y, z = getCharCoordinates(PLAYER_PED)
                local xx, yy = 2480, -1668
                if x == 2480 and y == -1668 then
                    runToPoint:run(2452, -1667)
                end
потому что получаешь из функи неровное число с точкой. делай через getDistanceBetweenCoords3d
Lua:
runToPoint:run(2480, -1668)
local x, y, z = getCharCoordinates(PLAYER_PED)
local xx, yy = 2480, -1668
if getDistanceBetweenCoords3d(xx, yy, z, x, y, z) < 0.8 then
    runToPoint:run(2452, -1667)
end
 
  • Нравится
Реакции: tyukapa

tyukapa

Активный
298
65
потому что получаешь из функи неровное число с точкой. делай через getDistanceBetweenCoords3d
Lua:
runToPoint:run(2480, -1668)
local x, y, z = getCharCoordinates(PLAYER_PED)
local xx, yy = 2480, -1668
if getDistanceBetweenCoords3d(xx, yy, z, x, y, z) < 0.8 then
    runToPoint:run(2452, -1667)
end
Скрытое содержимое для пользователя(ей):
 

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
кто знает как правильно проверять /stats при заходе на сервер и запуске скрипта?
ну тоесть, есть ли какой то rpc, который отвечает за то, авторизован ли игрок или чёт такое
Есть такой хук:
INCOMING_RPCS[RPC.SERVERJOIN] = {'onPlayerJoin', {playerId = 'uint16'}, {color = 'int32'}, {isNpc = 'bool8'}, {nickname = 'string8'}}
Но он, если не ошибаюсь, срабатывает ещё до авторизации.
А так, можешь попробовать такой способ:
Lua:
function main()
    while not isSampAvailable() do wait(0) end
    -- Здесь всякие приветствия, регистрация команд и т.д.
   
    -- После команд идёт это:
    repeat
        wait(0)
    until sampIsLocalPlayerSpawned()
    sampSendChat("/stats")
    wait(-1)
end
 
  • Нравится
Реакции: Revavi

tyukapa

Активный
298
65
Как пофиксить? Работает как переключатель, при нажатии на чекбокс персонаж бежит на 1 координату, и всё, скрипт дальше не работает. При выключении чекбокса скрипт бежит на 2 координату. Нужно чтобы при включении он бежал сразу на 1 координату и после того как достиг её, бежал на 2 координату

Lua:
-- imgui
            if imgui.Checkbox(u8'test', test) then
                runToPoint:run(2480, -1668)
                local x, y, z = getCharCoordinates(PLAYER_PED)
                local xx, yy = 2480, -1668
                if getDistanceBetweenCoords3d(xx, yy, z, x, y, z) < 0.8 then
                    runToPoint:run(2452, -1667)
                end
            end
          
-- function

runToPoint = lua_thread.create_suspended(function(tox, toy) -- use: runToPoint:run(x, y)
    local x, y, z = getCharCoordinates(PLAYER_PED)
    local angle = getHeadingFromVector2d(tox - x, toy - y)
    local xAngle = math.random(-50, 50)/100
    setCameraPositionUnfixed(xAngle, math.rad(angle - 90))
    stopRun = false
    while getDistanceBetweenCoords2d(x, y, tox, toy) > 0.8 do
        setGameKeyState(1, -255)
        wait(1)
        x, y, z = getCharCoordinates(PLAYER_PED)
        angle = getHeadingFromVector2d(tox - x, toy - y)
        setCameraPositionUnfixed(xAngle, math.rad(angle - 90))
        if stopRun then
            stopRun = false
            break
        end
    end
end)
 

Макс | Lycorn

Участник
156
13
Разные названия файлов ini делай
Сделал

Я делаю биндер, и те сообщение что пользователь написал в InputTextMultiline должно отсылаться в чат по кмд/клавише, которую задал в inputtext, как сделать?
Пока еще не все в lua знаю, учусь :)
 

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
Сделал

Я делаю биндер, и те сообщение что пользователь написал в InputTextMultiline должно отсылаться в чат по кмд/клавише, которую задал в inputtext, как сделать?
Пока еще не все в lua знаю, учусь :)
Lua:
if imgui.Button("Send") then
    sampAddChatMessage(u8:decode(inputtext.v), -1)
end
С кнопкой пример. С остальными способами также.
 

Макс | Lycorn

Участник
156
13
Lua:
if imgui.Button("Send") then
    sampAddChatMessage(u8:decode(inputtext.v), -1)
end
С кнопкой пример. С остальными способами также.
1685457412591.png
У меня есть такая менюшка, когда игрок зарегистрировал кмд/кнопку, ввел задержку, и после он пишет текст(в InputTextMultiline), и как сделать что-бы этот текст выводился по кмд/кнопке которую он зарегал, и с той задержкой, которую он ввел