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

BARRY BRADLEY

Известный
711
176
Здравствуйте. Вот допустим у меня есть хук на string.find(text,"Привет"), допустим меня бесит данное сообщения. Есть люди которые пишут: "привет","пРивет", "ПРИВЕТ". Как обойти чувствительность к регистру? Есть ли хоть какие-то варианты, кроме как создавать миллионы хуков на одно слово?
Как вариант сделать получаему строку и нужное слово в нижний или верхний регистр и тогда через string.find
Функция которая делает строку в нижнем регистре для русских букв:
Lua:
-- Перевод букв в нижний или верхний регистр на русском
local russian_characters = {[168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я'}


function rusLower(s)
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch+32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end

Далее в хуке:
Код:
string.find(rusLower(text), rusLower("Привет")),
 

.Makarov.

Известный
190
35
Как вариант сделать получаему строку и нужное слово в нижний или верхний регистр и тогда через string.find
Функция которая делает строку в нижнем регистре для русских букв:
Lua:
-- Перевод букв в нижний или верхний регистр на русском
local russian_characters = {[168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я'}


function rusLower(s)
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch+32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end

Далее в хуке:
Код:
string.find(rusLower(text), rusLower("Привет")),
Да, я уже видел это. Но в данном случае оно будет искать сообщение либо в нижнем регистре, либо в верхнем. Не срабатывая на сообщения в таком формате: "ПрИвЕт" =(
 

trefa

Известный
Всефорумный модератор
2,097
1,233
Да, я уже видел это. Но в данном случае оно будет искать сообщение либо в нижнем регистре, либо в верхнем. Не срабатывая на сообщения в таком формате: "ПрИвЕт" =(
Чего, она просто переводит в нижний регистр и всё. И по нижнему регистру ищет.
 
  • Нравится
Реакции: .Makarov.

BARRY BRADLEY

Известный
711
176
Да, я уже видел это. Но в данном случае оно будет искать сообщение либо в нижнем регистре, либо в верхнем. Не срабатывая на сообщения в таком формате: "ПрИвЕт" =(
Сработает, ибо оно переведет весь текст (всю строку) в нижний регистр
 
  • Нравится
Реакции: .Makarov.

Mr_Incognito

Активный
331
50
Всем привет.
Вывел название пунктов диалога в строку
Lua:
function sampev.onShowDialog(dialogId, style, title, button1, button2, text)
    sampAddChatMessage(text)
end
Как мне каждый пункт сделать отдельно? Допустим раскидать их (пункты) по переменным?
 

Dotalovo666

Новичок
8
0
На сервере есть система антистана когда в тебя попадают первим ти станишся Пол мл сек и даеш тичку в ответ и от тебя непроходит урон. Можна зделать скрипт чтоб фиксануть баг. Буду очень благодарен.
 

BARRY BRADLEY

Известный
711
176
Всем привет.
Вывел название пунктов диалога в строку
Lua:
function sampev.onShowDialog(dialogId, style, title, button1, button2, text)
    sampAddChatMessage(text)
end
Как мне каждый пункт сделать отдельно? Допустим раскидать их (пункты) по переменным?
Если тебе надо просто получит каждый пункт с диалога отдельно, то тут тебе поможет функция split:
Lua:
function split(str, delim, plain) -- bh FYP
   local tokens, pos, plain = {}, 1, not (plain == false) --[[ delimiter is plain text by default ]]
   repeat
       local npos, epos = string.find(str, delim, pos, plain)
       table.insert(tokens, string.sub(str, pos, npos and npos - 1))
       pos = epos and epos + 1
   until not pos
   return tokens
end

Использование:
Lua:
-- хук
local split_text = split(text, "\n") -- получаем таблицу с нашими пунктами
sampAddChatMessage(split_text[1], -1) -- выводим 1 пункт диалога. (Так же можно выводить или проверять все через for)
На сервере есть система антистана когда в тебя попадают первим ти станишся Пол мл сек и даеш тичку в ответ и от тебя непроходит урон. Можна зделать скрипт чтоб фиксануть баг. Буду очень благодарен.
Возможно антистан тебе поможет. Странная ситуация.
 

Dotalovo666

Новичок
8
0
Если тебе надо просто получит каждый пункт с диалога отдельно, то тут тебе поможет функция split:
Lua:
function split(str, delim, plain) -- bh FYP
   local tokens, pos, plain = {}, 1, not (plain == false) --[[ delimiter is plain text by default ]]
   repeat
       local npos, epos = string.find(str, delim, pos, plain)
       table.insert(tokens, string.sub(str, pos, npos and npos - 1))
       pos = epos and epos + 1
   until not pos
   return tokens
end

Использование:
Lua:
-- хук
local split_text = split(text, "\n") -- получаем таблицу с нашими пунктами
sampAddChatMessage(split_text[1], -1) -- выводим 1 пункт диалога. (Так же можно выводить или проверять все через for)

Возможно антистан тебе поможет. Странная ситуация.
Антистан непомагает
Если тебе надо просто получит каждый пункт с диалога отдельно, то тут тебе поможет функция split:
Lua:
function split(str, delim, plain) -- bh FYP
   local tokens, pos, plain = {}, 1, not (plain == false) --[[ delimiter is plain text by default ]]
   repeat
       local npos, epos = string.find(str, delim, pos, plain)
       table.insert(tokens, string.sub(str, pos, npos and npos - 1))
       pos = epos and epos + 1
   until not pos
   return tokens
end

Использование:
Lua:
-- хук
local split_text = split(text, "\n") -- получаем таблицу с нашими пунктами
sampAddChatMessage(split_text[1], -1) -- выводим 1 пункт диалога. (Так же можно выводить или проверять все через for)

Возможно антистан тебе поможет. Странная ситуация.
Или же можно зделать скрипт когда даеш 1 тичку з дигла и чтоб по тебе не прошло 2-3 тички в пвп
 
Последнее редактирование:

Oaeaa

Новичок
4
0
Как можно реализовать, что при появлении в чате "1" в sampAddChatMessage давались ответы "ы b г j", а при 2 давались "о w з q" и так далее (чтобы как цифры, так и 2 были заранее заготовленные в текстовом документе, с ответами к ним

1 ы b г j
2 о w з q
И так далее...

А так же, есть ли какой то русскоязычный гайд по этому вопросу?
 

HarlyCloud

Потрачен
238
66
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Можно ли создавать несколько бесконечных циклов в функции мейн??
 
D

deleted-user-204957

Гость
хотел сделать автоответчик/автокаптер
Суть: Автоматом пишет /capture когда в чате появляется строка "Вам осталось до зарплаты:"
Кому не трудно дайте, готовый код)
Тебе в раздел - Услуги/Заказы.
Можно ли создавать несколько бесконечных циклов в функции мейн??
Зачем тебе несколько бесконечных циклов? Именно в main
 

HarlyCloud

Потрачен
238
66
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
хотел сделать автоответчик/автокаптер
Суть: Автоматом пишет /capture когда в чате появляется строка "Вам осталось до зарплаты:"
Кому не трудно, сделайте код)
Ищи вот тут, 14:30 таймкод))
 

BARRY BRADLEY

Известный
711
176
Можно ли создавать несколько бесконечных циклов в функции мейн??
Только через отдельную функцию и поток.
Как можно реализовать, что при появлении в чате "1" в sampAddChatMessage давались ответы "ы b г j", а при 2 давались "о w з q" и так далее (чтобы как цифры, так и 2 были заранее заготовленные в текстовом документе, с ответами к ним

1 ы b г j
2 о w з q
И так далее...

А так же, есть ли какой то русскоязычный гайд по этому вопросу?
Lua:
-- json db
local database = {
{questions=1, answer="ы b г j"},
{questions=2, answer="o w з q"}
}

--- где в хуке onServerMessage(color, text)
for key, val in pairs(database) do
       if string.find(text, database[key]["questions"]) then -- ищим
            sampAddChatMessage(database[key]["answer"], -1) --ответ
       end
end
 
Последнее редактирование:

Mr_Incognito

Активный
331
50
Поомогите снова, пожалуйста.
Задача стоит сравнить две строки. Одна строка из переменной, значение которой я указал сам local var = "Привет"
Вторая строка это элемент массива, значения которых берутся из диалога. Мне надо их сравнить, но в диалоге цвет какой то серый, из за этого они не равны

Lua:
    var1 = "Привет"
    if split_text[2] == var1 then
        sampAddChatMessage('OK', -1)
    end
Проверил этот же код на диалоге, с элементами белого цвета. Всё работает. Как сделать правильно?

UPD.
Вроде нашел решение, даже работает. Это правильно?
Lua:
    if split_text[2]:find(var1) then
        sampAddChatMessage("ok", -1)
    end
 

BARRY BRADLEY

Известный
711
176
Поомогите снова, пожалуйста.
Задача стоит сравнить две строки. Одна строка из переменной, значение которой я указал сам local var = "Привет"
Вторая строка это элемент массива, значения которых берутся из диалога. Мне надо их сравнить, но в диалоге цвет какой то серый, из за этого они не равны

Lua:
    var1 = "Привет"
    if split_text[2] == var1 then
        sampAddChatMessage('OK', -1)
    end
Проверил этот же код на диалоге, с элементами белого цвета. Всё работает. Как сделать правильно?
Делай через string.find, а не через прямое сравнение