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

k1sher

Известный
201
4
Может быть потому что radius в qwer равен nil?
Так а чему должно быть равно? Если число должно быть равное radius = string.match(arg, "^%s*(%d+)%s*"), то которые я пишу при вводе команды. /kom [число]

Может быть потому что radius в qwer равен nil?
Я понимаю если без команды делать...
Код:
qwe:run(str, aidi, 10.0)
и дальше типа...
Код:
function qwer(str, id, dst)
    wait(0)
    if dst ~= 0.0 then
Далее уже проверку и отправку...
Код:
if dist <= dst then
sampSendChat(str)
А вот через команду не получается.
 
Последнее редактирование модератором:

makasinuch

Новичок
52
5
для отправки фейк синхры не обязательно использовать хук, хук нужен только для перезаписи и перехвата. если тебе нужно только перезаписывать значения в синхре с каким-то промежутком, то можно использовать таймер в хуке:
Lua:
health_value, health_tick = 100, localClock()
function samp.onSendPlayerSync(data)
  if health_value > 0 and localClock() - health_tick > 1.0 then
    health_tick = localClock()
    health_value = health_value - 1
  end
  data.health = health_value
end
будет уменьшать здоровье каждую секунду на 1, пока оно не станет нулём.
а вот удобная функция, если нужно отправлять свою синхру, а не подменять отправляемую: Полезные сниппеты и функции (https://blast.hk/threads/13380/#post-153001)

скорее всего баг какой-то, но кнопки атаки можно эмулировать с помощью setGameKeyState.
По поводу той функции... Я правильно понял, что то что под Спойлером нужно вставить в свой код, а после уже можно в функции Main, как поп примеру, отправлять свои данные?
 

k1sher

Известный
201
4
Если добавить в массив индекс со словами. Как их можно рандомить с помощью local ran = math.random (1,4) ?
 

4el0ve4ik

Известный
Всефорумный модератор
1,550
1,343
Если добавить в массив индекс со словами. Как их можно рандомить с помощью local ran = math.random (1,4) ?
Lua:
function RandomText()
    local ran = math.random (1, 4)
    local text =
    {
        [1] = "Grove",
        [2] = "Ballas",
        [3] = "Vagos",
        [4] = "Aztec"
    }
    return text[ran]
end
 
  • Нравится
Реакции: imring, eiuhuth и k1sher

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Почему цвет выводится другой [ onServerMessage(color, text) ]?
Должно быть так:
etUIB3Z.jpg

А выводит так:
0EFJb1b.jpg
 

k1sher

Известный
201
4
Подскажите пожалуйста ошибки в скрипте.
Код:
local hook = require 'lib.samp.events'


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("radius", adrCMD)
    qwe = lua_thread.create_suspended(qwer)
    wait(-1)
end


function qwer(str, id, radius)
    wait(0)
    if radius ~= 0.0 then
        if doesCharExist(PLAYER_PED) then
            if sampIsPlayerConnected(id) then
                local _, PlayerHandle = sampGetCharHandleBySampPlayerId(id)
                if doesCharExist(PlayerHandle) then
                    local sX, sY, sZ = getCharCoordinates(PLAYER_PED)
                    local pX, pY, pZ = getCharCoordinates(PlayerHandle)
                    local dist = getDistanceBetweenCoords3d(sX, sY, sZ, pX, pY, pZ)
                    sampSendChat(radius)
                    if dist <= tonumber(radius) then
                        sampSendChat(str)
                    end
                end
            end
        end
    else
        sampSendChat(str)
    end
end


function hook.onServerMessage(color, text)
    if adrToggle == 1 then
    if string.find(text, "^%>%> ПМ от %S+%(%d+%)%: %s*hp%s*$") then
        local aidi = string.match(text, "%>%> ПМ от %S+%((%d+)%)%: %s*hp%s*")
        local str = string.format("/sethp %d 160", aidi)
        qwe:run(str, aidi)
    end
    if string.find(text, "^%>%> ПМ от %S+%(%d+%)%: %s*guns%s*$") then
        local aidi = string.match(text, "^%>%> ПМ от %S+%((%d+)%)%: %s*guns%s*$")
        local str = string.format("/sellgun %d eagle", aidi)
        qwe:run(str, aidi)
    end
    if string.find(text, "^%>%> ПМ от %S+%(%d+%)%: %s*tpme%s*$") then
        local aidi = string.match(text, "^%>%> ПМ от %S+%((%d+)%)%: %s*exit%s*$")
        local str = string.format("/sethp %d 0", aidi)
        qwe:run(str, aidi)
        end
    end
end

function adrCMD(arg)
if adrToggle == 1 then
        adrToggle = 0
        sampAddChatMessage("Скрипт деактивирован.", 0xc40000)
    else
            if string.find(arg, "^%s*%d+%s*") then
            radius = string.match(arg, "^%s*(%d+)%s*")
            radius = tonumber(radius)
            adrToggle = 1
            sampAddChatMessage("Скрипт активирован.", 0x08a800)
            sampAddChatMessage("{00fadd}Дистанция до игрока установлена: {FFFFFF}" .. radius .. " {ffffff}М.", 0xFFFFFF)
        else
            sampAddChatMessage("{c40000}Ошибка! {FFFFFF}Введите радиус. Например /radius [Дистанция]", 0xFFFFFF)
        end
    end
end
Не хочет радиус работать.

Я понимаю если без команды делать...
Код:
qwe:run(str, aidi, 10.0)
и дальше типа...
Код:
function qwer(str, id, dst)
    wait(0)
    if dst ~= 0.0 then
Далее уже проверку и отправку...
Код:
if dist <= dst then
sampSendChat(str)
А вот через команду не получается.
 

itsLegend

Фонд борьбы за жуков 🐞
Администратор
2,696
1,468
Я понимаю если без команды делать...
Какой команды? Что за чушь. У тебя для вызываемой функции необходимо указать 3 параметра, ты указываешь 2: str, id, а radius в этом случае равен nil.
Если бы ты объявил глобальную переменную radius1 и проверял бы её в функции qwer, то это худо-бедно работало, но у тебя именно radius, а значит то, что в области функции это новая локальная переменная, для неё не указано значение => nil.
У тебя есть всё для дебага, включая вывод в консоль SAMPFUNCS, можно же проверить переменную radius (или др.) в этой функции, не на столько же всё плохо.
 
  • Нравится
Реакции: eiuhuth

FYP

Известный
Автор темы
Администратор
1,763
5,906
@imring sampAddChatMessage принимает цвет в формате (A)RGB, а от сервера приходит RGBA.
преобразование rgba в rgb:
Lua:
local rgb = bit.rshift(rgba, 8)
 

qrlk

Известный
Друг
411
926
Помогите закрыть диалог. Вызываю /getgun, беру оружие через sampsenddialogresponse, но закрыть не могу.

Lua:
function main()
while not isSampAvailable() do wait(200) end
    while true do
    wait(0)
        if isKeyDown(82) and isKeyDown(90) then
            sampSendChat("/getgun")
            wait(100)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 5, -1)
            wait(0)
        end
    end
end
 

memir

🇷🇺
Всефорумный модератор
339
611
Помогите закрыть диалог. Вызываю /getgun, беру оружие через sampsenddialogresponse, но закрыть не могу.

Lua:
function main()
while not isSampAvailable() do wait(200) end
    while true do
    wait(0)
        if isKeyDown(82) and isKeyDown(90) then
            sampSendChat("/getgun")
            wait(100)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 5, -1)
            wait(0)
        end
    end
end
Код:
sampCloseCurrentDialogWithButton(button)
 

qrlk

Известный
Друг
411
926
@imring sampAddChatMessage принимает цвет в формате (A)RGB, а от сервера приходит RGBA.
преобразование rgba в rgb:
Lua:
function main()
while not isSampAvailable() do wait(200) end
    while true do
    wait(0)
        if isKeyDown(82) and isKeyDown(90) then
            sampSendChat("/getgun")
            wait(100)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 5, -1)
            wait(0)
        end
    end
end
Код:
sampCloseCurrentDialogWithButton(button)
нет эффекта. может ошибся.
Lua:
function main()
while not isSampAvailable() do wait(200) end
    while true do
    wait(0)
        if isKeyDown(82) and isKeyDown(90) then
            sampSendChat("/getgun")
            wait(100)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            wait(200)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            wait(200)
            sampSendDialogResponse(123, 1, 5, -1)
            wait(100)
            sampCloseCurrentDialogWithButton(button)
        end
    end
end
 

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
нет эффекта. может ошибся.
Lua:
function main()
while not isSampAvailable() do wait(200) end
    while true do
    wait(0)
        if isKeyDown(82) and isKeyDown(90) then
            sampSendChat("/getgun")
            wait(100)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            wait(200)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            wait(200)
            sampSendDialogResponse(123, 1, 5, -1)
            wait(100)
            sampCloseCurrentDialogWithButton(button)
        end
    end
end

Lua:
sampCloseCurrentDialogWithButton(0)
 

memir

🇷🇺
Всефорумный модератор
339
611
нет эффекта. может ошибся.
Lua:
function main()
while not isSampAvailable() do wait(200) end
    while true do
    wait(0)
        if isKeyDown(82) and isKeyDown(90) then
            sampSendChat("/getgun")
            wait(100)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            sampSendDialogResponse(123, 1, 0, -1)
            wait(200)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            sampSendDialogResponse(123, 1, 1, -1)
            wait(200)
            sampSendDialogResponse(123, 1, 5, -1)
            wait(100)
            sampCloseCurrentDialogWithButton(button)
        end
    end
end
button - переменная, вместо нее надо было подставить номер кнопки