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

YarikVL

Известный
Проверенный
4,796
1,813
Возможно ли на луа написать чтобы мышка делала клик по нужному месту?
 
  • Нравится
Реакции: хуега)

deadfamq

Участник
108
22
хочу написать скрипт, чтобы автоматически качать ломку. Я уже его написал, но хочу сделать так, чтоб при появлении в чате текста "Недостаточно наркотиков" 2 раза нажимался энтер и продолжалась работа скрипта. Надеюсь кто-то поможет)

Вот код:

Lua:
local active = false
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end
вроде должно работать
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)

    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
 
Последнее редактирование:

Loocking

Известный
1,372
467
как проверить находишься ли в снайперском режиме?
 
Последнее редактирование:

kiyoshii

Новичок
26
15
вроде должно работать
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)

    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
хз почему, но не работает, энтер не нажимается
 

deadfamq

Участник
108
22
хз почему, но не работает, энтер не нажимается
извини это я туплю (кодировку ставь на windows 1251)
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')
local active = false
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end
function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
 
  • Нравится
Реакции: kiyoshii

kiyoshii

Новичок
26
15
извини это я туплю (кодировку ставь на windows 1251)
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')
local active = false
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end
function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        setVirtualKeyDown(0x0D, true)
        wait(100)
        setVirtualKeyDown(0x0D, false)
    end
end
теперь нажимается вроде, но дело в том что при первом нажатии энтера, должен появится диалог типо "вы хотите купить наркотики?" и две кнопки - купить и назад. После этого скрипт должен нажать ещё раз энтер, но у меня даже диалог почему-то не открывается. И после этого нажатия скрипт не продолжает работать. Буду очень рад если поможешь)
 
  • Нравится
Реакции: deadfamq

deadfamq

Участник
108
22
теперь нажимается вроде, но дело в том что при первом нажатии энтера, должен появится диалог типо "вы хотите купить наркотики?" и две кнопки - купить и назад. После этого скрипт должен нажать ещё раз энтер, но у меня даже диалог почему-то не открывается. И после этого нажатия скрипт не продолжает работать. Буду очень рад если поможешь)
напишу
 

Pashyka

Участник
220
17
Хочу сделать поиск по таблице и вывод кнопок, если совпадение есть, мне нужно чтобы при любом регистре искало нормально, но код ниже почему-то неработает, можете нацелить по ошибке?

Lua:
function imgui.OnDrawFrame()   
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText(u8'##SearchText', cmds, 384, u8"Поиск", 2)
        for k,v in pairs(cmd) do
            if cmds.v:len() > 0 then
                if string.lower(v):find(string.lower(cmds.v)) then
                    imgui.Button(v, imgui.ImVec2(-0.1, 0))
                end
            else
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,225
Хочу сделать поиск по таблице и вывод кнопок, если совпадение есть, мне нужно чтобы при любом регистре искало нормально, но код ниже почему-то неработает, можете нацелить по ошибке?

Lua:
function imgui.OnDrawFrame()  
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText(u8'##SearchText', cmds, 384, u8"Поиск", 2)
        for k,v in pairs(cmd) do
            if cmds.v:len() > 0 then
                if string.lower(v):find(string.lower(cmds.v)) then
                    imgui.Button(v, imgui.ImVec2(-0.1, 0))
                end
            else
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
Lua:
local items = {
    'tExt',
    'HELLo',
    'worLD'
}
local search = imgui.ImBuffer(256)

-- frame:
for k, v in ipairs(items) do
    if #search.v == 0 or v:lower():find(search.v:lower()) then
        imgui.Text(v)
    end
end
 

Pashyka

Участник
220
17
Lua:
local items = {
    'tExt',
    'HELLo',
    'worLD'
}
local search = imgui.ImBuffer(256)

-- frame:
for k, v in ipairs(items) do
    if #search.v == 0 or v:lower():find(search.v:lower()) then
        imgui.Text(v)
    end
end
Не робит, тоже не ищет, из-за кодировки может быть? Хотя вроде все учтено

Lua:
cmd = {
    u8"Привет тест",
    u8"Тест привет"
}
 

Pashyka

Участник
220
17
для русских символов нужно использовать кастомную функу rlower

Мб я тупой конечно, я нашел эту функцию, по сути она, но все равно не робит, по разному пробовал и string.rlower(v) и v.rlower()


Lua:
function imgui.OnDrawFrame()  
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText('##SearchText', cmds, 384, u8"Поиск", 2)
        for k, v in pairs(cmd) do
            if #cmds.v == 0 or string.rlower(v):find(string.rlower(cmds.v)) then
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
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 string.rlower(s)
    s = s:lower()
    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
 

deadfamq

Участник
108
22
теперь нажимается вроде, но дело в том что при первом нажатии энтера, должен появится диалог типо "вы хотите купить наркотики?" и две кнопки - купить и назад. После этого скрипт должен нажать ещё раз энтер, но у меня даже диалог почему-то не открывается. И после этого нажатия скрипт не продолжает работать. Буду очень рад если поможешь)
работает 100 проц, чекал сам
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        lua_thread.create( function()
            setVirtualKeyDown(0x0D, true)
            wait(100)
            setVirtualKeyDown(0x0D, false)
        end)
    end
end

function ev.onShowDialog(dialogId, style, title, button1, button2, text)
    if dialogId == 285 then
        if text:find('Вы собираетесь купить (%d+) грамм за (%d+) вирт') then
            sampSendDialogResponse(285, 1, 0, '')
        end
    end
end
 
  • Нравится
Реакции: kiyoshii

kiyoshii

Новичок
26
15
работает 100 проц, чекал сам
Lua:
require 'lib.moonloader'
local ev = require('lib.samp.events')

local active = false

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('lomka', function()
        active = not active
        sampAddChatMessage(active and 'AutoLomka ON' or 'AutoLomka OFF', -1)
    end)
    while true do
        wait(0)
        if active then
            sampSendChat("/usedrugs 3")
            wait(700)
        end
    end
end

function ev.onServerMessage(color, text)
    if text:find('Недостаточно наркотиков') then
        lua_thread.create( function()
            setVirtualKeyDown(0x0D, true)
            wait(100)
            setVirtualKeyDown(0x0D, false)
        end)
    end
end

function ev.onShowDialog(dialogId, style, title, button1, button2, text)
    if dialogId == 285 then
        if text:find('Вы собираетесь купить (%d+) грамм за (%d+) вирт') then
            sampSendDialogResponse(285, 1, 0, '')
        end
    end
end
лучший, работает, спасибо огромное)
 
  • Влюблен
Реакции: deadfamq

Pashyka

Участник
220
17
Мб я тупой конечно, я нашел эту функцию, по сути она, но все равно не робит, по разному пробовал и string.rlower(v) и v.rlower()


Lua:
function imgui.OnDrawFrame() 
    if acmd.v then
        setDarkStyle()
        local X, Y = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(X / 2, Y / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400,300), imgui.Cond.FirstUseEver)
        imgui.Begin(u8'Команды сервера', acmd, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoScrollbar)
        imgui.PushItemWidth(-1)
        imgui.NewInputText('##SearchText', cmds, 384, u8"Поиск", 2)
        for k, v in pairs(cmd) do
            if #cmds.v == 0 or string.rlower(v):find(string.rlower(cmds.v)) then
                imgui.Button(v, imgui.ImVec2(-0.1, 0))
            end
        end
        imgui.End()
    end
end
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 string.rlower(s)
    s = s:lower()
    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

@chapo Все функции перепробовал такого типа, ничего не выходит вообще