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

The Sunset

Новичок
22
4
Час назад скрипт еще нормально чинил авто, а потом вдруг перестал...
Когда нахожусь не в транспорте - скрипт нормально работает, все правильно, но в транспорте - выдает ошибку:
opcode '0224' call caused an unhandled exception
stack traceback:
[C]: in function 'setCarHealth'
D:\Games\GTA for BD\moonloader\cmdcheats.lua:58: in function <D:\Games\GTA for BD\moonloader\cmdcheats.lua:55>

Вот часть кода:
Lua:
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    reg_cmd()

    wait(-1)
end

function reg_cmd()
    local cmd = sampRegisterChatCommand
    local luachat = sampAddChatMessage

    cmd('/hpcar',
    function()
        local player_car = isCharInAnyCar(PLAYER_PED)
        if player_car == true  then
            setCarHealth(1, default_hpcar)
            luachat('Транспорт починен!', 0xFFD700)
        else
            luachat('Вы не в транспорте!', 0xFFD700)
        end
    end)

end
Я пробовал делать проверку на хп т/с с помощью getCarHealth, но тогда ошибку выдает на сам getCarHealth, но уже с opcode '0227'
Как быть?..

после 18 строки кода, который ты скинул выше:
Lua:
if player_car then
  carhandle = storeCarCharIsIn(PLAYER_PED)
  setCarHealth(carhandle, default_hpcar)
end
- с этим он тоже не хочет работать.
 
Последнее редактирование:

Musaigen

abobusnik
Проверенный
1,607
1,363
Час назад скрипт еще нормально чинил авто, а потом вдруг перестал...
Когда нахожусь не в транспорте - скрипт нормально работает, все правильно, но в транспорте - выдает ошибку:
opcode '0224' call caused an unhandled exception
stack traceback:
[C]: in function 'setCarHealth'
D:\Games\GTA for BD\moonloader\cmdcheats.lua:58: in function <D:\Games\GTA for BD\moonloader\cmdcheats.lua:55>

Вот часть кода:
Lua:
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    reg_cmd()

    wait(-1)
end

function reg_cmd()
    local cmd = sampRegisterChatCommand
    local luachat = sampAddChatMessage

    cmd('/hpcar',
    function()
        local player_car = isCharInAnyCar(PLAYER_PED)
        if player_car == true  then
            setCarHealth(1, default_hpcar)
            luachat('Транспорт починен!', 0xFFD700)
        else
            luachat('Вы не в транспорте!', 0xFFD700)
        end
    end)

end
Я пробовал делать проверку на хп т/с с помощью getCarHealth, но тогда ошибку выдает на сам getCarHealth, но уже с opcode '0227'
Как быть?..


- с этим он тоже не хочет работать.
Что в default_hpcar?

Lua:
fixCar(storeCarCharIsInNoSave(playerPed))
setCarHealth(storeCarCharIsInNoSave(playerPed), default_hpcar)
 

Kuharz

Известный
407
154
Какие функции или еще что нужно для того, чтобы сделать скрипт, который работать на подобии long chat (для тех, кто не в курсе, выводит сообщения, которые пишут игроки далеко от вас в зоне прорисовки), но не все строки, а по заданным словам?
 

Aniki

🐰
Администратор
1,228
1,558
Какие функции или еще что нужно для того, чтобы сделать скрипт, который работать на подобии long chat (для тех, кто не в курсе, выводит сообщения, которые пишут игроки далеко от вас в зоне прорисовки), но не все строки, а по заданным словам?
https://blast.hk/threads/15508/ - код открыт, изучай
Чтобы работало по заданным словам, нужно в хуке onPlayerChatBubble дополнительно проверять сообщение через string.find/string.match
К слову в начале скрипта есть blacklist, можно добавлять туда нежелательные паттерны
 

Quasper

Известный
835
354
Какие функции или еще что нужно для того, чтобы сделать скрипт, который работать на подобии long chat (для тех, кто не в курсе, выводит сообщения, которые пишут игроки далеко от вас в зоне прорисовки), но не все строки, а по заданным словам?
библиотека SAMP.lua
И в ней есть такой RPC как onPlayerChatBubble
 

serhiyrubin

Известный
396
106
Можно функцию которая скрывает ники и чтобы можно было вернуть обратно?
Нашел на клео, осталось переписать на луа(

0@ = SAMP.Base()
000A: 0@ += 0x21A0F8
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 1 //0@ == stSAMP
000A: 0@ += 0x3C5 //0@ == stServerPresets
0A8D: 1@ = read_memory 0@ size 4 virtual_protect 1
1@ += 0x38
0A8C: write_memory 1@ size 1 value 0 virtual_protect 1

ON
0A8C: write_memory 1@ size 1 value 1 virtual_protect 1
 
Последнее редактирование:

trefa

3d print
Всефорумный модератор
2,107
1,262
Можно функцию которая скрывает ники и чтобы можно было вернуть обратно?
Нашел на клео, осталось переписать на луа(

0@ = SAMP.Base()
000A: 0@ += 0x21A0F8
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 1 //0@ == stSAMP
000A: 0@ += 0x3C5 //0@ == stServerPresets
0A8D: 1@ = read_memory 0@ size 4 virtual_protect 1
1@ += 0x38
0A8C: write_memory 1@ size 1 value 0 virtual_protect 1

ON
0A8C: write_memory 1@ size 1 value 1 virtual_protect 1
https://blast.hk/threads/15478/ там все есть, осталось только значения корректировать.
 

Kuharz

Известный
407
154
https://blast.hk/threads/15508/ - код открыт, изучай
Чтобы работало по заданным словам, нужно в хуке onPlayerChatBubble дополнительно проверять сообщение через string.find/string.match
К слову в начале скрипта есть blacklist, можно добавлять туда нежелательные паттерны
Видел данный скрипт и как понял, он берет текст над головой, а мне нужно из чата, но на дали, как лонг чат.
 

Nagenbl4

Новичок
107
2
Hi! На Arizona есть полоска голода, возможно ли её изменять не визуально для себя? В плане я был сыт, ввёл команду и стал голоден.
 

Belo4ka_belka

Известный
191
7
Здравствуйте. Возникла проблема: не могу поставить фокус на инпут в диалоге. Ситуация следующая: при первом отображении диалога фокус на инпут не ставится. Если диалог скрыть и отобразить второй и следующие разы то все работает, фокус стоит. Путем комментирования строк выяснил что такая ситуация наблюдается из-за функции TextColoredRGB. Если этой строки нет то все работает с первого раза, однако эта функция мне нужна, да и я уверен, что конфликт с этой функцией явно не по вине автора происходит, а по моей. Подскажите способ решения проблемы. Код:
Код:
function imgui.TextColoredRGB(text)
    local style = imgui.GetStyle()
    local colors = style.Colors
    local ImVec4 = imgui.ImVec4

    local explode_argb = function(argb)
        local a = bit.band(bit.rshift(argb, 24), 0xFF)
        local r = bit.band(bit.rshift(argb, 16), 0xFF)
        local g = bit.band(bit.rshift(argb, 8), 0xFF)
        local b = bit.band(argb, 0xFF)
        return a, r, g, b
    end

    local getcolor = function(color)
        if color:sub(1, 6):upper() == 'SSSSSS' then
            local r, g, b = colors[1].x, colors[1].y, colors[1].z
            local a = tonumber(color:sub(7, 8), 16) or colors[1].w * 255
            return ImVec4(r, g, b, a / 255)
        end
        local color = type(color) == 'string' and tonumber(color, 16) or color
        if type(color) ~= 'number' then return end
        local r, g, b, a = explode_argb(color)
        return imgui.ImColor(r, g, b, a):GetVec4()
    end

    local render_text = function(text_)
        for w in text_:gmatch('[^\r\n]+') do
            local text, colors_, m = {}, {}, 1
            w = w:gsub('{(......)}', '{%1FF}')
            while w:find('{........}') do
                local n, k = w:find('{........}')
                local color = getcolor(w:sub(n + 1, k - 1))
                if color then
                    text[#text], text[#text + 1] = w:sub(m, n - 1), w:sub(k + 1, #w)
                    colors_[#colors_ + 1] = color
                    m = n
                end
                w = w:sub(1, n - 1) .. w:sub(k + 1, #w)
            end
            if text[0] then
                for i = 0, #text do
                    imgui.TextColored(colors_[i] or colors[1], u8(text[i]))
                    imgui.SameLine(nil, 0)
                end
                imgui.NewLine()
            else imgui.Text(u8(w)) end
        end
    end

    render_text(text)
end

function imgui.OnDrawFrame()
    if show_main_window.v and (MainIni.Status.Read == "READ" or FirstRun) then
        sw, sh = getScreenResolution()
        imgui.SetNextWindowSizeConstraints(imgui.ImVec2(300, 0), imgui.ImVec2(sw / 2, sh / 2))
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.Always, imgui.ImVec2(0.5, 0.5))
        if IsAppear then
            imgui.SetNextWindowSize(imgui.ImVec2(0.0, 0.0), imgui.Cond.Always)
        end
        imgui.Begin(u8(MainIni.Require.Title), show_main_window, 4 + 2 + 32)
        imgui.ShowCursor = true
        textGui, StrCol = MainIni.Require.Text:gsub("<e>", "\n")
            StrCol = StrCol + 1
            TBegin = imgui.GetCursorPosY()
        imgui.TextColoredRGB(textGui)
        imgui.PushItemWidth(-1.0)
        imgui.InputText(u8'##empty_field', moonimgui_text_buffer)
        if IsAppear then -- условие возвращает истину только один раз при открытии окна
            imgui.SetKeyboardFocusHere(-1.0)
            IsAppear = false
        end
        imgui.PopItemWidth()
            ButtonY = TBegin + imgui.GetTextLineHeight() * StrCol + 30
        imgui.PushItemWidth(50.0)
        imgui.SetCursorPos(imgui.ImVec2(imgui.GetWindowWidth() / 2 - 50.0, ButtonY))
        if imgui.Button(u8(MainIni.Require.ButtonText)) then
            isCorrectClose = true
            show_main_window.v = false
        end
        imgui.End()
    end
end

function onWindowMessage(msg, wparam, lparam)
    if(msg == 0x100 or msg == 0x101) then
        if(wparam == key.VK_ESCAPE and show_main_window.v) and not isPauseMenuActive() then
            consumeWindowMessage(true, false)
            if(msg == 0x101)then
                if show_main_window.v then
                    isCorrectClose = false
                    show_main_window.v = false
                end
            end
        elseif wparam == key.VK_RETURN and not isKeyDown(key.VK_RETURN) and not isPauseMenuActive() and show_main_window.v then
            isCorrectClose = true
            show_main_window.v = false
            consumeWindowMessage(true, false)
        end
    end
end

Есть ещё вторая проблема, если я не смогу её решить без костылей, то решу по-своему. Проблема следующая: после того как я добавил обработчик onWindowMessage чтобы закрывать окно через esc и enter, на инпут в окне невозможно поставить фокус (он ставится и через секунду исчезает) - даже вручную. Это наблюдается только в том случае, если предыдущий диалог был закрыт с помощью клавиши ентер (если закрыть мышкой нажав на крестик, или кнопку, или через esc то все нормально). Т.Е. если я нажал ентер и диалог закрылся, то при следующем его появлении фокус поставить будет невозможно. Я хочу решить это простым перезапуском скрипта при каждом закрытии диалога, понимаю что это костыль, но сейчас я вариантов не вижу, может-быть вы что-нибудь подскажете?
 

The Sunset

Новичок
22
4
Туплю, не понимаю, почему у меня не работает активация на клавишу? По-разному делал - ни в какую.
Вопрос: Что именно нужно для того, чтобы активировать скрипт на клавишу?..