- 4,771
- 5,376
Данная тема посвящена нюансам и особенностям разработки Lua скриптов для MoonLoader.
Список вопросов:
Начало разработки.
Взаимодействие с игроками.
Работа с переменными.
Работа с командами.
Начало разработки.
Каждый Lua скрипт при запуске создает поток "main" который и является основным местом работы со скриптом.
Сразу обговорим - скрипт "жив" пока "жив" поток main(), поэтому если мы хотим продолжать работать со скриптом после запуска - будем держать поток активным:
Lua:
function main() -- Объявляем поток main()
wait(-1) -- Устанавливаем бесконечное ожидание
end -- закрываем функцию
Запускаем скрипт - работает!
Что ж, поставим себе цель - при запуске выводить сообщение "Привет мир" в чат.
Что нам для этого нужно?
Заходим на WIKI (Раздел "Функции" moonloader`a) и ищем функции чата - Поиск -> "Chat". Видим функцию sampAddChatMessage(message, color) - то что надо.
Вставляем:
Lua:
function main()
sampAddChatMessage("Привет мир!", 0xFFFFFFFF) -- Выводим сообщение в чат
wait(-1) -- Устанавливаем бесконечное ожидание
end
Код:
(error) test.lua: opcode '0AF8' call caused an unhandled exception
Находим нашу функцию sampAddChatMessage()
Что это значит? Дело в том что нельзя вызывать функции для работы с SA:MP пока сам SA:MP не готов. Что делать? Добавим перед выводом сообщения такой код:
Lua:
if not isSampfuncsLoaded() or not isSampLoaded() then -- Если SF или SA:MP не загружены
return -- Завершаем работу скрипта
end
while not isSampAvailable() do -- Ждём пока функция isSampAvailable() вернет true
wait(0) -- Устанавливаем минимальное ожидание, что бы наша игра не зависла
-- значение 0 говорит что мы ждём следующий кадр (Frame)
end
Что такое wait() и с чем его едят?
Wait позволяет ставить поток в режим ожидания на указанное количество мили-секунд (ms)
Wait нельзя в CallBack-функциях, это приведет к ошибке, а в последствии и смерти, скрипта.
Почему мы ставим 0? Потому-что это минимальная задержка.
Подведем краткий итог кода:
Lua:
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(0)
end
sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
wait(-1)
end
К списку вопросов
Взаимодействие с игроками
Перейдем к примерам посложнее - попробуем получить ник, ид и счет игрока в которого мы прицелились.
Цель поставили, какие нам нужны средства?
Опять бежим к WIKI, всё в тот же раздел функций и ищем функции связанные с целями, Поиск -> Target.
Смотрим в списке есть getCharPlayerIsTargeting(ped).
Она возвращает 2 значения - result, ped.
Первое значение - возвращает результат проверки на целится ли указанный Ped в кого-либо.
Второе - если указанный Ped целится - возвращает саму цель.
Как нам это использовать? Всё просто, уберем бесконечное ожидание и будем проверять значение result.
Lua:
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(0)
end
sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
while true do -- Создаем бесконечный цикл, вместо бесконечного ожидания
wait(0) -- Опять таки чтобы наша игра не зависла, ждем след кадр
local result, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- Каждый кадр получаем данные функции, PLAYER_HANDLE - возвращает ваш Handle
if result then -- Если result вернет true
print("True!") -- Выведем сообщение в лог / консоль
end
end
end
Lua:
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(0)
end
sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
while true do
wait(0)
local result, ped = getCharPlayerIsTargeting(playerPed)
if result then
local result2, id = sampGetPlayerIdByCharHandle(ped) -- Попробуем получить ID игрока по его Ped
if result2 then -- Если получилось
local nickname = sampGetPlayerNickname(id) -- Запишем его ник
local score = sampGetPlayerScore(id) -- и счет
sampAddChatMessage(string.format("%s[%d] имеет счет %d", nickname, id, score), -1) -- И выведем это в чат
end
end
end
end
Работа с переменными
Что у нас получилось? Мы будем получать кучу сообщений в чат о игрока по пока целимся в кого-либо, но как убрать этот флуд?
Давайте создадим переменную перед main(), например targeting, и присвоим ей значение false.
И задействуем её в коде
Lua:
local targeting = false -- Создаем булевую переменную
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(0)
end
sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
while true do
wait(0)
local result, ped = getCharPlayerIsTargeting(playerPed)
if result and not targeting then -- Если мы целимся, но ранее ни в кого не целились
local result2, id = sampGetPlayerIdByCharHandle(ped)
if result2 then
local nickname = sampGetPlayerNickname(id)
local score = sampGetPlayerScore(id)
sampAddChatMessage(string.format("%s[%d] имеет счет %d", nickname, id, score), -1)
targeting = true -- запишем что мы целимся в кого либо и наше условие выше станет ложным
end
elseif not result and targeting then -- Если условие обратное - скажем скрипту что мы не целимся
targeting = false
end
end
end
К списку вопросов
Работа с командами.
Уже лучше, давайте теперь работаем с командами.
Уберем лишний код и оставим следующее:
Lua:
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(0)
end
while true do
wait(0)
end
end
Как добавить команду? Давайте опять порыщем на WIKI, Поиск -> Command
Нашли sampRegisterChatCommand(command, callback)? Отлично, можно уже приступать.
Зарегистрируем нашу команду, например "toster":
Lua:
function main()
if not isSampfuncsLoaded() or not isSampLoaded() then
return
end
while not isSampAvailable() do
wait(0)
end
sampRegisterChatCommand("toster", tosterCallBack) -- Регистрируем ДО бесконечного цикла.
-- Первый параметр - команда, без слэша.
-- Второй - функция-callback которая будет вызваться если будет введена команда.
wait(-1) -- Уберем бесконечный цикл, он тут вовсе не нужен, но нам же нужно чтобы скрипт работал
end
function tosterCallBack(params)
sampAddChatMessage("Дзынь!", -1)
end
Lua:
sampAddChatMessage(params, -1)
Помните я говорил что нельзя использовать wait() внутри callback-функций, это всё еще так, но есть тут одна хитрость!
Lua:
function tosterCallBack()
sampAddChatMessage("Дзынь!", -1)
lua_thread.create(function() -- Создаем новый поток
wait(5000) -- Ждём 5 секунд
sampAddChatMessage("Тоже дзынь, но на 5 секунд позже!", -1) -- Выводим текст в чат
end) -- Тут наш поток умирает :(
end
На сегодня всё, теперь вы чертовы волшебники, поняв как всё работает, можно приступать к изучению примеров Lua скриптов!
Тема будет дополняться по мере изучения популярных вопросов по Lua скриптингу.
Я понимаю что вы невъебенные мастера луа скриптинга, но это тема не для вас
Последнее редактирование: