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

kyrtion

Известный
974
354
С либой inicfg такое вроде не прокатит
Значит решено, json?)

Как сделать чтобы оно прибавлялось, а не просто 1 писало?

Govnokod:
local bik = "[Helper bikers]"
local sampev = require 'samp.events'
local otm = 0
function main()
    while not isSampAvailable () do wait (0) end
    sampAddChatMessage (bik .. " загружен", 0xFF0000)
    while true do
        wait (0)
        if wasKeyPressed(0x48) and wasKeyPressed(0x42) and not sampIsCursorActive() then
            sampSendChat('/sellkey ' .. select(2, sampGetPlayerIdByCharHandle(1)) .. ' 100')
            wait (100)
            sampSendChat('/w .                         .')
            sampAddChatMessage (bik  .. " Отмычeк: " .. otm + 1 .. '. Продолжаем  в том же духе!', 0xFF0000)
        end
    end
end
Чтобы отправить от имени скрипта, можно достаточно создать ещё одна функция - отправки локальное сообщение от скрипта не усложняя жизни программистов:
Lua:
function alert(str)
    return sampAddChatMessage('[Helper bikers] '..tostring(str), 0xFFFFFFFF)
end

-- ...
alert('hello') -- => sampAddChatMessage('[Helper bikers] '..tostring('hello'), 0xFFFFFFFF)
 
Последнее редактирование:

Andrinall

Известный
701
518
С либой inicfg такое вроде не прокатит
Прокатит
1685432390692.png
 
  • Нравится
Реакции: whyega52

Макс | Lycorn

Участник
166
13
Вообщем, как мне сделать, что-бы ini файлы я мог хранить в своей папке а не в config'e? Или лучше уже сразу делать сохранение через js? Что я пока-что совсем не умею
 
  • Эм
Реакции: joumey

F1stachka

Новичок
4
1
Здраствуйте, как сделать нажатие стрелочки вправо? когда пишу
setVirtualKeyDown(VK_RIGHT, true) то нажимается Numpad6 который не работает в игре
 

kyrtion

Известный
974
354
@Макс | 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: '..(listSettings[i].is_active and 'enabled' or 'disabled'))
end
 
Последнее редактирование:

Revavi

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

Макс | Lycorn

Участник
166
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

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

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

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

goodflex

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

XRLM

Против ветра рождённый
Проверенный
1,516
1,107
Как сделать подключение 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 или через синхру
 
  • Нравится
Реакции: goodflex

goodflex

Активный
300
70
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

Против ветра рождённый
Проверенный
1,516
1,107
Скрипт начинает работать как нужно, потом когда доходит до нужных координат ничего не происходит.

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
 
  • Нравится
Реакции: goodflex

goodflex

Активный
300
70
потому что получаешь из функи неровное число с точкой. делай через 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,505
1,134
кто знает как правильно проверять /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