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

Dmitriy Makarov

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

Макс | Lycorn

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

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

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
Можешь 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

Участник
166
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),
        -- И т.д.
    },
}
а все, понял, спасибо огромное :)
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,798
2,659
Каким массивом пользоваться?)
Кратко постараюсь пересказать суть таблиц.
Таблица - совокупность каких-либо данных, хранящихся в одном месте.
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

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

Макс | Lycorn

Участник
166
13
А в консоли что?
В консоль не пишет, просто крашит игру. Таких повторений у меня 20, ну немного там меняется, из-за этого похоже?
1685385033131.png
 

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
В консоль не пишет, просто крашит игру. Таких повторений у меня 20, ну немного там меняется, из-за этого похоже?
Посмотреть вложение 203070
К переменным неправильно обращаешься.
Замени:
bindercmd11 на settings.commands.bindercmd11

binderhotkey11 на settings.commands.binderhotkey11

bindertext11 на settings.commands.bindertext11
И впредь тоже обращайся к ним через массив.
 

Макс | Lycorn

Участник
166
13
К переменным неправильно обращаешься.
Замени:
bindercmd11 на settings.commands.bindercmd11

binderhotkey11 на settings.commands.binderhotkey11

bindertext11 на settings.commands.bindertext11
И впредь тоже обращайся к ним через массив.
А понял, спасибо, щас попробую.

Можете подробно объяснить о функции doesFileExist
хочу сделать сохранение в ini файл через неё, но впервые буду делать через эту функцию, ранее делал через inicfg
 
Последнее редактирование:

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
А понял, спасибо, щас попробую.

Можете подробно объяснить о функции doesFileExist
хочу сделать сохранение в ini файл через неё, но впервые буду делать через эту функцию, ранее делал через inicfg
А что там объяснять? Функция проверяет, существует ли файл и всё. Она тебе не нужна, чтобы использовать inicfg.save(...)
 

Макс | Lycorn

Участник
166
13
А что там объяснять? Функция проверяет, существует ли файл и всё. Она тебе не нужна, чтобы использовать inicfg.save(...)
Я хочу сделать ini файлы в своей папке, а не в config, а если через inicfg делать сохранение, то оно работает только в файле с config'a
 

Yans

Активный
190
33
Как сделать чтобы оно прибавлялось, а не просто 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
 
D

deleted-user-422095

Гость
Как сделать чтобы оно прибавлялось, а не просто 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:
otm = otm + 1
sampAddChatMessage (bik  .. " Отмычeк: " .. otm .. '. Продолжаем  в том же духе!', 0xFF0000)
 
  • Нравится
Реакции: Yans