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

вайега52

Налуашил состояние
Модератор
3,000
3,138
Можно ли как-то избавиться от анонимных функций в сея коде?
Lua:
local commands = {
    {command = "!tg", callback = function(text) telegram:sendMessage(text) end},
    {command = "!tram", callback = function(act) runRoute(act) end}
}

registerHandler("onRunCommand", function(cmd)
    for _, data in ipairs(commands) do
        local pattern = ("%s (.+)"):format(data.command)
        if cmd:find(pattern) then
            data.callback(cmd:match(pattern))
            return false       
        end
    end
end)

пишу автоответчик и столкнулся с проблемой, добавил функцию которая при виде:
"(ник чела) говорит: вы тут? вы бот? и тд"
отправляет в чат:
"дада тут, кнш где еще и тд"
но вот только проблема, этого не происходит,вот код:
Lua:
    onServerMessage = function(_, text)
    if act then
    if (text:match(' .-') or text:match('говорит:')) then
        if text:match("Вы тут?") or text:match("Вы тут") or text:match("Вы здесь") or text:match("тyт") or text:match("Вы за компьютером ?") or text:match("Вы за компьютером") or text:match("тут") or text:match("здесь") or text:match("Вы здесь?") or text:match("вы тут?") or text:match("вы тут") or text:match("вы здесь") or text:match("вы здесь?") or text:match("в ы з д е с ь?") or text:match("вы бот?")  or text:match("вы бот") or text:match("Вы бот?") or text:match("ответ в чат") or text:match("ответ в /b") or text:match("ответ в /n") or text:match("Вы на месте?") or text:match("Вы афк?") or text:match("вы тут? ответ в /n") or text:match("Вы тут? Ответ в /n") or text:match("вы тут? ответ в /b") or text:match("Вы тут? Ответ в /b") then
        if os.time() - t > 6 then
        t = os.time()
        lua_thread.create(function(a)
                if k < 1 then
                if not text:match('%d+(%p)%d+') then
                    mute(true)
                        wait(math.random(890, 1039))
                            freezeCharPositionAndDontLoadCollision(ped, true)
                        wait(math.random(3000, 4000))
                        sampSendChat(otveti[math.random(1, #otveti)])
                        freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                    k = k + 1
                elseif not text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                        sampSendChat(povtoriha[math.random(1, #povtoriha)])
                    k = 0
                    freezeCharPositionAndDontLoadCollision(ped, false)
                end
                if text:match('%d+(%p)%d+') then
                    wait(math.random(890, 1039))
                        freezeCharPositionAndDontLoadCollision(ped, true)
                    wait(math.random(3000, 4000))
                    sampSendChat(matemka[math.random(1, #matemka)])
                    freezeCharPositionAndDontLoadCollision(ped, false)
                    end
                end)
                end
            end
            end
        end
    end
и если что все указанные там переменные я указывал в начале кода, это не в них дело
чет там по коду вообще жопа, скинь фулл код, можешь под хайд, завтра разберемся (сейчас накидал чуть, но не могу понять фулл суть без полного кода)
 
Последнее редактирование:

sosnov

Известный
329
115
Можно ли как-то избавиться от анонимных функций в сея коде?
Lua:
local commands = {
    {command = "!tg", callback = function(text) telegram:sendMessage(text) end},
    {command = "!tram", callback = function(act) runRoute(act) end}
}

registerHandler("onRunCommand", function(cmd)
    for _, data in ipairs(commands) do
        local pattern = ("%s (.+)"):format(data.command)
        if cmd:find(pattern) then
            data.callback(cmd:match(pattern))
            return false     
        end
    end
end)


чет там по коду вообще жопа, скинь фулл код, можешь под хайд, завтра разберемся (сейчас накидал чуть, но не могу понять фулл суть без полного кода)
 

Andrinall

Известный
702
527
Можно ли как-то избавиться от анонимных функций в сея коде?

Могу предложить недоговнокод с использованием loadstring
Чисто в теории с таким способом можно дать пользователю самостоятельно ставить обработчики на команды, дав некоторую документацию по использованию.

Lua:
local commands = {
  { command = "!tg", callback = "telegram:sendMessage(arg)" },
  { command = "!tram", callback = "runRoute(arg)" }
}

function loadCodeWithParams(strcode, params)
  local ctx = {}
  setmetatable(ctx, { __index = _G })
  local mt = getmetatable(ctx)
  for k, v in pairs(params) do mt.__index[k] = v end
  local fn = assert(loadstring(strcode))
  setfenv(fn, ctx)
  return fn
end

registerHandler("onRunCommand", function(cmd)
  for _, data in ipairs(commands) do
    local pattern = ("%s (.*)"):format(data.command)
    local arg = cmd:match(pattern)
    if arg then
      loadCodeWithParams(data.callback, { arg=arg })()
      return false
    end
  end
end)
 
Последнее редактирование:
  • Вау
Реакции: вайега52

l-m

Новичок
28
1
Объясните пожалуйста КАК ЄТО РАБОТАЕТ, не могу засветить кнопку при нажатии на нее, да и вообще функционал с этими кнопка в Sweet Connect
Исходник, пример кода: https://www.blast.hk/threads/64892/
image.png

image.png
 

Карен

Участник
112
17
Lua:
[/B]
function runToPoint(tox, toy)
    lua_thread.create(function()
        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)
            --setGameKeyState(16, 1)
            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)
end
[B]

Как сделать чтобы runToPoint бежал к самому близкому обьекту, а не к самому дальному?
 

вайега52

Налуашил состояние
Модератор
3,000
3,138
не, проверка, является ли аргумент текстом.
upd. уже нашел способ решения.
tonumber() не предназначена для проверки именно типа, она просто переводит какой-то тип в число и если это строка, которая состоит только из чисел или это уже число, т.е. true, то возвращает это число, иначе nil - т.е. false.
1680108150965.png

вот именно проверка типа:
Lua:
local text = 313

if type(text) == "string" then
    ...
else
    print("не строка")
end
1680108232790.png


кстати, я так понимаю ты не совсем понимаешь, что такое типы в луа, поэтому вот небольшой отрывок из статейки

2.1 – Значения и типы​

Lua динамически типизированный язык. Это означает, что значения не имеют типов; только значения. Язык не имеет определений типов. Все значения несут свой собственный тип.

Все значения в Lua первоклассные. Это означает что все значения могут быть сохранены в переменных, переданы как аргументы другим функциям, и возвращены как результаты.

В Lua существует восемь базовых типов: nil, boolean, number, string, function, userdata, thread и table.

Тип nil (нуль) имеет одно единственное значение, nil, его главное свойство это отличаться от любых других значений; обычно это означает отсутствие используемого значения.

Тип boolean (логический) имеет два значения: false (ложь) и true (истина). Оба nil и false означают false; любое другое значение означает true.

Тип number (число) представляет целые (integer) и вещественные (float) числа.

Тип string (строка) представляет неизменные последовательности байт. Строки в Lua могут содержать любое 8-битное значение, включая нули ('\0'). Также Lua противник кодировок; никаких предположений о содержимом строки не делается.

Тип number использует два внутренних представления, или два подтипа, один называется integer (целое), второй float (число с плавающей запятой). Lua имеет явные правила о том, когда какое представление использовать, но при необходимости автоматически конвертирует значение между ними (см. §3.4.3). Следовательно, в большистве случаев программист может игнорировать разницу между целыми и реальными числами, или получить полный контроль над представлением каждого числа. Стандартный Lua использует 64-битные целые (integer) и вещественные числа двойной точности (double 64-bit), но также возможно скомпилировать Lua так, чтобы использовались 32-битные целые и/или вещественные числа одинарной точности (float 32-bit). Эта опция с 32 битами для целых и вещественных чисел особенно актуальна для малых машин и встроенных систем. (Смотри макрос LUA_32BITS в файле luaconf.h.)

Lua может вызывать и манипулировать функциями написанными на Lua и на С (см. §3.4.10). Оба типа функций в Lua представлены типом function (функция).

Тип userdata (пользовательские данные) предназначен для хранения произвольных С данных в Lua переменных. Значение userdata представляет блок памяти (raw memory). Существуют два типа пользовательских данных: full userdata (полные пользовательские данные) - объект с блоком памяти, которым управляет Lua, и light userdata (лёгкие пользовательские данные) - простой С указатель. Пользовательские данные не имеют предопределенных операторов в Lua, кроме оператора присвоения и сравнения на идентичность. Используя метатаблицы, программист может определить операции для значений full userdata (см. §2.4). Значения userdata не могут быть созданы или изменены в Lua, это возможно только через C API. Это гарантирует целостность данных, которыми владеет хост-программа.

Тип thread (поток) представляет независимый поток выполнения и используется для реализации сопрограмм (coroutine) (см. §2.6). Lua потоки это не реальные потоки операционной системы. Lua поддерживает сопрограммы на всех системах, даже на тех, где это не поддерживается операционной системой.

Тип table (таблица) реализует ассоциативные массивы, это значит, что массив может быть проиндексирован не только числами, но и любым Lua значением, кроме nil и NaN. (Not a Number специальное значение для представления неопределенных и непредставимых числовых результатов, таких как 0/0.) Таблицы могут быть гетерогенными (разнородными); т.е. могут содержать значения всех типов (кроме nil). Любой ключ со значением nil не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет ассоциированное значение nil.

Таблицы единственный механизм структурирования данных в Lua; они могут использоваться для представления обычных массивов, последовательностей, таблиц символов, множеств, записей, графов, деревьев и т.п. Для представления записей, Lua использует имена полей как индекс. Язык поддерживает представление a.name, как синтаксическое украшение a["name"]. Существуют различные пути создания таблиц в Lua (см. §3.4.9).

Мы используем термин последовательность (sequence) чтобы обозначить таблицу, где все ключи это натуральные числа {1..n} (1,2,3,...), где n - длина последовательности (см. §3.4.7).

Как и индексы, значения полей в таблице могут быть любого типа. В частности, т.к. функции это первоклассные значения, поля таблицы могут содержать функции. Такие таблицы также могут содержать методы (см. §3.4.11).

Индексирование в таблицах следует принципу "сырого" (raw) равенства в языке. Выражения a и a[j] определяют один и тот же элемент таблицы, если и только если i и j равны (raw equal) (значит, равны без метаметодов). В частности, вещественные числа (float) с целыми значениями равны соответствующим целым (integer), т.е., 1.0 == 1. Во избежание неоднозначностей, любое реальное число с целым значением, которое испльзуется как ключ, конвертируется в соответствующее ему целое число. Например, если написать a[2.0] = true, фактически в таблицу будет вставлен целочисленный (integer) ключ 2. С другой стороны, 2 and "2" разные Lua значения и следовательно обозначают разные данные в таблице.

Таблицы, функции, потоки и пользовательские данные (userdata) - это объекты: переменные фактически не содержат их значений, только ссылки на них. Присвоение, передача параметров и возврат из функций всегда манипулируют ссылками на эти значения; эти операции не подразумевают никакого типа копирования.

Библиотечная функция type возвращает строку с названием переданного ей типа (см. §6.1).

Взято от сюда (можешь почитать на досуге полностью статью, возможно не сразу все дойдет, но рано или поздно сможешь осилить): https://lua.org.ru/manual_ru.html#pdf-type
 
Последнее редактирование:

rissing

Потрачен
7
1
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
ку, как сделать ColorEdit4 и сохранение чтобы потом можно было заменять текст в чате на этот цвет?
 

вайега52

Налуашил состояние
Модератор
3,000
3,138
ку, как сделать ColorEdit4 и сохранение чтобы потом можно было заменять текст в чате на этот цвет?