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

why ega

РП игрок
Модератор
2,540
2,222
вроде неплохие статьи по таблицам:

Я то понимаю что это, но не умею их использовать правильно :)
 
  • Нравится
Реакции: YarikVL

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
Я то понимаю что это, но не умею их использовать правильно :)
Как-то так.
Lua:
-- Из этого:
local value_1 = "String"
local value_2 = 1
local value_3 = 1.1
local value_4 = imgui.ImBuffer(10)
local value_5 = imgui.ImInt(0)

-- В это:

local settings = {
    value_1 = "String",
    value_2 = 1,
    value_3 = 1.1,
    value_4 = imgui.ImBuffer(10),
    value_5 = imgui.ImInt(0),
}

-- Можешь также для красоты и удобства разделить по категориям.

local settings = {
    test_1 = {
        value_1 = "String",
        value_2 = 1,
    },
    test_2 = {
        value_3 = 1.1,
        value_4 = imgui.ImBuffer(10),
    },
}
 
Последнее редактирование:
  • Нравится
Реакции: accord-

Макс | Lycorn

Участник
156
13
В плане? Если ты про то, какую статью читать - читай обе и можешь еще несколько почитать
Каким массивом пользоваться?)

Как-то так.
Lua:
local value_1 = "String"
local value_2 = 1
local value_3 = 1.1
local value_4 = imgui.ImBuffer(10)
local value_5 = imgui.ImInt(0)

-- >

local settings = {
    value_1 = "String",
    value_2 = 1,
    value_3 = 1.1,
    value_4 = imgui.ImBuffer(10),
    value_5 = imgui.ImInt(0),
}

-- Можешь также для красоты и удобства разделить по категориям.

local settings = {
    test_1 = {
        value_1 = "String",
        value_2 = 1,
    },
    test_2 = {
        value_3 = 1.1,
        value_4 = imgui.ImBuffer(10),
    },
}
Честно скажу, вообще не понял что тут :)
 

Revavi

Участник
101
24
как узнать какая версия клиента запущена? я знаю про getGameVersion, но мало чего от туда могу понять
 

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
Каким массивом пользоваться?)


Честно скажу, вообще не понял что тут :)
У тебя, скорее всего, все переменные выглядят как у меня в начале, где везде "local". Тебе нужно сделать так, как ниже. 2 способа есть внизу, как можно исправить твою ошибку.

как узнать какая версия клиента запущена? я знаю про getGameVersion, но мало чего от туда могу понять
Такое нашёл.
 

Макс | Lycorn

Участник
156
13
У тебя, скорее всего, все переменные выглядят как у меня в начале, где везде "local". Тебе нужно сделать так, как ниже. 2 способа есть внизу, как можно исправить твою ошибку.


Такое нашёл.
1685382549704.png
1685382574122.png
У меня вот такая штука, там где с _, я сделал так, ибо думал что пофикситься, но не :)
 
  • Грустно
Реакции: de_clain

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
Тебе бы с циклом сделать, что-ли. 🤔
Ну да ладно. В любом случае, у тебя дофига локальных переменных, из-за этого ругается Луа.
Сделай как у меня здесь:
любым способом, кроме первых 5 строчек. Это я как пример их использовал.
 
  • Нравится
Реакции: percheklii

Макс | Lycorn

Участник
156
13
Тебе бы с циклом сделать, что-ли. 🤔
Ну да ладно. В любом случае, у тебя дофига локальных переменных, из-за этого ругается Луа.
Сделай как у меня здесь:

любым способом, кроме первых 5 строчек. Это я как пример их использовал.
Можешь 1 пример приложить с моими переменными? Увижу, дальше сам буду делать :)
 

Dmitriy Makarov

25.05.2021
Проверенный
2,478
1,113
Можешь 1 пример приложить с моими переменными? Увижу, дальше сам буду делать :)
В твоём случае рекомендую использовать второй способ, чтобы не запутаться.
Lua:
local settings = {
    commands = {
        bindercmd1 = imgui.ImBuffer(256),
        bindercmd2 = imgui.ImBuffer(256),
        bindercmd3 = imgui.ImBuffer(256),
        -- И т.д.
    },
    hotkeys = {
        binderhotkey1 = imgui.ImBuffer(256),
        binderhotkey2 = imgui.ImBuffer(256),
        binderhotkey3 = imgui.ImBuffer(256),
        -- И т.д.
    },
    delay = {
        binderdelay1 = imgui.ImInt(1000),
        binderdelay1 = imgui.ImInt(1000),
        binderdelay1 = imgui.ImInt(1000),
        -- И т.д.
    },
}
 
  • Нравится
Реакции: Макс | Lycorn

Макс | Lycorn

Участник
156
13
В твоём случае рекомендую использовать второй способ, чтобы не запутаться.
Lua:
local settings = {
    commands = {
        bindercmd1 = imgui.ImBuffer(256),
        bindercmd2 = imgui.ImBuffer(256),
        bindercmd3 = imgui.ImBuffer(256),
        -- И т.д.
    },
    hotkeys = {
        binderhotkey1 = imgui.ImBuffer(256),
        binderhotkey2 = imgui.ImBuffer(256),
        binderhotkey3 = imgui.ImBuffer(256),
        -- И т.д.
    },
    delay = {
        binderdelay1 = imgui.ImInt(1000),
        binderdelay1 = imgui.ImInt(1000),
        binderdelay1 = imgui.ImInt(1000),
        -- И т.д.
    },
}
а все, понял, спасибо огромное :)
 

why ega

РП игрок
Модератор
2,540
2,222
Каким массивом пользоваться?)
Кратко постараюсь пересказать суть таблиц.
Таблица - совокупность каких-либо данных, хранящихся в одном месте.
Lua:
local alphabet = {"a", "b", "c"} -- от формата записи ничего не зависит, таблицу можно писать как в одну строку, так и на тысячи строк
local pets = { -- элементы в "{}" перечисляются через запятую
    "dog",
    "cat",
    "wolf"
} -- по факту, таблицы alphabet и pets по структуре ничем не отличаются
В таблицах существуют так называемые "ключи" - названия ячеек в таблицах
Lua:
local colors = {
    white = 0xFFFFFF, -- ключ "white" содержит значение "0xFFFFFF"
    black = 0x000000 -- ключ "black" содержит значение "0x000000"
}

-- в такой таблице тоже есть ключи, хоть мы их и не указываем, если мы не указываем ключ,
-- то он будет равен индексу элемента в таблице
local enum = {
    "zalupa", -- ключ "1" содержит значение "zalupa"
    "huy", -- ключ "2" содержит значение "huy"
    "car" -- ключ "3" содержит значение "car"
}
Массив - таблица, в которой не указаны ключи, т.е. таблица enum будет являться массивом
Создавать таблицы умеем, теперь надо их как-то использовать:
Lua:
local cars = {
    "BMW",
    "LADA",
    "AUDI"
}

-- для того, чтобы получить значение в массиве, нам необходимо указать название таблицы
-- и в "[]" указать индекс элемента
print(cars[1]) -- выведет "BMW"


local cars = {
    germany = "BMW",
    russia = "LADA",
    neEbu = "AUDI"
}


-- а что делать, если у нас не массив?
-- нам необходимо вызывать значение по ключу, это можно сделать двумя способами:

-- первый способ - обратиться к ключу через точку (стоит подметить, что это работает
-- только с ключами, которые состоят из английского алфавита и по желанию из цифр,
-- это делается так:
print(cars.germany) -- выведет "BMW"
-- второй способ - сделать также, как и с массивом
-- такой способ желательно использовать только тогда, когда это не подходит под первый случай
-- также, это можно использовать, когда название ключа заранее не известно
print(cars["germany"]) -- выведет "BMW"
Таблица может содержать абсолютно любые типы данных (вроде есть какие-то траблы с nil, но точно не помню): строки, числа, функции, таблицы в таблице и т.д.
Например вот:
Lua:
local sbornikHuyni = { -- желательно давать названия на английском, а не транслитом, но это лишь пример, поэтому пишу говно
    func = function() print("abc") end,
    num = 31,
    str = "cheeee",
    tab = {"BMW", "LADA", "AUDI"}
} -- тут приведены не все типы данных


-- получения элемента из таблицы не зависит от его типа,
-- все происходит так, как было описано в прошлых кодах
print(sbornikHuyni.str) -- т.к. у нас таблица sbornikHuyni не является массивом и ключи на ангийском, обращаемся через точку
-- out: "cheeee"
print(sbornikHuyni.num)
-- out: "31"
print(sbornikHuyni.tab[2]) -- т.к. у нас в таблице sbornikHuyni содержится массив, обращаемся к его элементу
-- out: "LADA"
print(sbornikHuyni.func()) -- вызываем функцию из таблицы
-- out: "abc"
Хрен знает что еще объяснить и так уже пишу это минут 30, про циклы для таблиц, можешь почитать в статьях
Также существуют метатаблицы, это таблицы, которые регулируют поведение (то, что будет делать таблица при получении значения из нее; то, что таблица будет делать, когда из нее получают значение и т.д.) таблицы, на которую наложена метатаблица, но думаю это пока рановато для тебя
 

Макс | Lycorn

Участник
156
13
Кратко постараюсь пересказать суть таблиц.
Таблица - совокупность каких-либо данных, хранящихся в одном месте.
Lua:
local alphabet = {"a", "b", "c"} -- от формата записи ничего не зависит, таблицу можно писать как в одну строку, так и на тысячи строк
local pets = { -- элементы в "{}" перечисляются через запятую
    "dog",
    "cat",
    "wolf"
} -- по факту, таблицы alphabet и pets по структуре ничем не отличаются
В таблицах существуют так называемые "ключи" - названия ячеек в таблицах
Lua:
local colors = {
    white = 0xFFFFFF, -- ключ "white" содержит значение "0xFFFFFF"
    black = 0x000000 -- ключ "black" содержит значение "0x000000"
}

-- в такой таблице тоже есть ключи, хоть мы их и не указываем, если мы не указываем ключ,
-- то он будет равен индексу элемента в таблице
local enum = {
    "zalupa", -- ключ "1" содержит значение "zalupa"
    "huy", -- ключ "2" содержит значение "huy"
    "car" -- ключ "3" содержит значение "car"
}
Массив - таблица, в которой не указаны ключи, т.е. таблица enum будет являться массивом
Создавать таблицы умеем, теперь надо их как-то использовать:
Lua:
local cars = {
    "BMW",
    "LADA",
    "AUDI"
}

-- для того, чтобы получить значение в массиве, нам необходимо указать название таблицы
-- и в "[]" указать индекс элемента
print(cars[1]) -- выведет "BMW"


local cars = {
    germany = "BMW",
    russia = "LADA",
    neEbu = "AUDI"
}


-- а что делать, если у нас не массив?
-- нам необходимо вызывать значение по ключу, это можно сделать двумя способами:

-- первый способ - обратиться к ключу через точку (стоит подметить, что это работает
-- только с ключами, которые состоят из английского алфавита и по желанию из цифр,
-- это делается так:
print(cars.germany) -- выведет "BMW"
-- второй способ - сделать также, как и с массивом
-- такой способ желательно использовать только тогда, когда это не подходит под первый случай
-- также, это можно использовать, когда название ключа заранее не известно
print(cars["germany"]) -- выведет "BMW"
Таблица может содержать абсолютно любые типы данных (вроде есть какие-то траблы с nil, но точно не помню): строки, числа, функции, таблицы в таблице и т.д.
Например вот:
Lua:
local sbornikHuyni = { -- желательно давать названия на английском, а не транслитом, но это лишь пример, поэтому пишу говно
    func = function() print("abc") end,
    num = 31,
    str = "cheeee",
    tab = {"BMW", "LADA", "AUDI"}
} -- тут приведены не все типы данных


-- получения элемента из таблицы не зависит от его типа,
-- все происходит так, как было описано в прошлых кодах
print(sbornikHuyni.str) -- т.к. у нас таблица sbornikHuyni не является массивом и ключи на ангийском, обращаемся через точку
-- out: "cheeee"
print(sbornikHuyni.num)
-- out: "31"
print(sbornikHuyni.tab[2]) -- т.к. у нас в таблице sbornikHuyni содержится массив, обращаемся к его элементу
-- out: "LADA"
print(sbornikHuyni.func()) -- вызываем функцию из таблицы
-- out: "abc"
Хрен знает что еще объяснить и так уже пишу это минут 30, про циклы для таблиц, можешь почитать в статьях
Также существуют метатаблицы, это таблицы, которые регулируют поведение (то, что будет делать таблица при получении значения из нее; то, что таблица будет делать, когда из нее получают значение и т.д.) таблицы, на которую наложена метатаблица, но думаю это пока рановато для тебя
Спасибки :)

В твоём случае рекомендую использовать второй способ, чтобы не запутаться.
Lua:
local settings = {
    commands = {
        bindercmd1 = imgui.ImBuffer(256),
        bindercmd2 = imgui.ImBuffer(256),
        bindercmd3 = imgui.ImBuffer(256),
        -- И т.д.
    },
    hotkeys = {
        binderhotkey1 = imgui.ImBuffer(256),
        binderhotkey2 = imgui.ImBuffer(256),
        binderhotkey3 = imgui.ImBuffer(256),
        -- И т.д.
    },
    delay = {
        binderdelay1 = imgui.ImInt(1000),
        binderdelay1 = imgui.ImInt(1000),
        binderdelay1 = imgui.ImInt(1000),
        -- И т.д.
    },
}
Я это все сделал, но меня теперь крашит), это может быть из-за повторений всего в 20 функций if?