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

qwеty

Известный
484
156
В чём проблема? При нажатии на imgui.TextButton в конфиг сохраняется значение true, нажимаю ещё раз и значение в конфиге должно было бы измениться на false, но оно не изменяется, а остается положительным, то есть true (после нажатия функция всё время возвращает true). В свою очередь, с imgui.Checkbox всё нормально работает, значения сохраняються как и должны сохраняться.
jopa:
require 'lib.moonloader'

local imgui = require 'imgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local inicfg = require 'inicfg'

local window_menu = imgui.ImBool(false)
local sw, sh = getScreenResolution()

local directIni = 'moonloader/config/imguihui.ini'
local mainIni = inicfg.load({
    config = {
            func = false,
            func1 = false
        }
}, directIni)

local func = imgui.ImBool(mainIni.config.func)
local func1 = imgui.ImBool(mainIni.config.func1)

function main()
    while not isSampAvailable() do wait(100) end
        if not doesFileExist('moonloader/config/imguihui.ini') then inicfg.save(mainIni, 'imguihui.ini') end
        sampRegisterChatCommand('window', windowmenu)
        while true do
            wait(0)
        end
end

function windowmenu()
    window_menu.v = not window_menu.v
    imgui.Process = window_menu.v
end

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.TextButton(text, bool)
    imgui.TextColoredRGB(string.format('[    %s', bool.v and '{00ff00}ON' or '{ff0000}OFF'))
    if imgui.IsItemClicked() then bool.v = not bool.v end
    imgui.SameLine()
    imgui.Text('  ]  '..text)
    return bool.v
end

function imgui.OnDrawFrame()
        if window_menu.v then
            imgui.SetNextWindowSize(imgui.ImVec2(180, 320), imgui.Cond.FirstUseEver)
            imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
            imgui.ShowCursor = true
            imgui.Begin('Window')
            if imgui.TextButton('gmcar1', func1) then
                mainIni.config.func1 = func1.v
                inicfg.save(mainIni, 'imguihui.ini')
            end
            if imgui.Checkbox('gmcar', func) then
                mainIni.config.func = func.v
                inicfg.save(mainIni, 'imguihui.ini')
            end
        else
            imgui.ShowCursor = false
        end
        imgui.End()
end
up
 

Мира

Участник
455
9
как вывести свой ид не используя переменную, мол на прямую в sampAddChatMessage
 

mzxer

Активный
81
119
В чём проблема? При нажатии на imgui.TextButton в конфиг сохраняется значение true, нажимаю ещё раз и значение в конфиге должно было бы измениться на false, но оно не изменяется, а остается положительным, то есть true (после нажатия функция всё время возвращает true). В свою очередь, с imgui.Checkbox всё нормально работает, значения сохраняються как и должны сохраняться.
jopa:
require 'lib.moonloader'

local imgui = require 'imgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local inicfg = require 'inicfg'

local window_menu = imgui.ImBool(false)
local sw, sh = getScreenResolution()

local directIni = 'moonloader/config/imguihui.ini'
local mainIni = inicfg.load({
    config = {
            func = false,
            func1 = false
        }
}, directIni)

local func = imgui.ImBool(mainIni.config.func)
local func1 = imgui.ImBool(mainIni.config.func1)

function main()
    while not isSampAvailable() do wait(100) end
        if not doesFileExist('moonloader/config/imguihui.ini') then inicfg.save(mainIni, 'imguihui.ini') end
        sampRegisterChatCommand('window', windowmenu)
        while true do
            wait(0)
        end
end

function windowmenu()
    window_menu.v = not window_menu.v
    imgui.Process = window_menu.v
end

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.TextButton(text, bool)
    imgui.TextColoredRGB(string.format('[    %s', bool.v and '{00ff00}ON' or '{ff0000}OFF'))
    if imgui.IsItemClicked() then bool.v = not bool.v end
    imgui.SameLine()
    imgui.Text('  ]  '..text)
    return bool.v
end

function imgui.OnDrawFrame()
        if window_menu.v then
            imgui.SetNextWindowSize(imgui.ImVec2(180, 320), imgui.Cond.FirstUseEver)
            imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
            imgui.ShowCursor = true
            imgui.Begin('Window')
            if imgui.TextButton('gmcar1', func1) then
                mainIni.config.func1 = func1.v
                inicfg.save(mainIni, 'imguihui.ini')
            end
            if imgui.Checkbox('gmcar', func) then
                mainIni.config.func = func.v
                inicfg.save(mainIni, 'imguihui.ini')
            end
        else
            imgui.ShowCursor = false
        end
        imgui.End()
end
imgui.TextButton возвращает текущее состояние кнопки, а не факт нажатия на неё (отличие от imgui.Button и подобных)
почему так - хз
поэтому тока так:
Lua:
-- где то вверху
local func1 = imgui.ImBool(mainIni.config.func1)
local r_func1 = func1.v

-- в imgui.OnDrawFrame
imgui.TextButton('gmcar1', func1)
if func1.v ~= r_func1 then
    r_func1 = func1.v

    mainIni.config.func1 = func1.v
    inicfg.save(mainIni, 'imguihui.ini')
end

Lua:
require 'lib.moonloader'

local imgui = require 'imgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local inicfg = require 'inicfg'

local window_menu = imgui.ImBool(false)
local sw, sh = getScreenResolution()

local directIni = 'moonloader/config/imguihui.ini'
local mainIni = inicfg.load({config = {func = false, func1 = false}}, directIni)

local func = imgui.ImBool(mainIni.config.func)
local func1 = imgui.ImBool(mainIni.config.func1)
local r_func1 = func1.v

function main()
    while not isSampAvailable() do wait(100) end
    if not doesFileExist('moonloader/config/imguihui.ini') then
        inicfg.save(mainIni, 'imguihui.ini')
    end
    sampRegisterChatCommand('window', windowmenu)
    while true do wait(0) end
end

function windowmenu()
    window_menu.v = not window_menu.v
    imgui.Process = window_menu.v
end

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.TextButton(text, bool)
    imgui.TextColoredRGB(string.format('[    %s',
                                       bool.v and '{00ff00}ON' or '{ff0000}OFF'))
    if imgui.IsItemClicked() then bool.v = not bool.v end
    imgui.SameLine()
    imgui.Text('  ]  ' .. text)
    return bool.v
end

function imgui.OnDrawFrame()
    if window_menu.v then
        imgui.SetNextWindowSize(imgui.ImVec2(180, 320), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2),
                               imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.ShowCursor = true
        imgui.Begin('Window')

        imgui.TextButton('gmcar1', func1)
        if func1.v ~= r_func1 then
            r_func1 = func1.v

            mainIni.config.func1 = func1.v
            inicfg.save(mainIni, 'imguihui.ini')
        end
       
        if imgui.Checkbox('gmcar', func) then
            mainIni.config.func = func.v
            inicfg.save(mainIni, 'imguihui.ini')
        end
    else
        imgui.ShowCursor = false
    end
    imgui.End()
end
 
  • Нравится
Реакции: qwеty

MAHEKEH

Известный
1,997
497
Lua:
for i, ped in pairs(getAllChars()) do
if ped ~= PLAYER_PED and not isCharDead(ped) then
local _, id = sampGetPlayerIdByCharHandle(ped)
if _ then --msg('id = , ..id..')

туповатый вопрос, но как то же самое сделать через
Lua:
for i = 1, 1000 do
?
 

Мира

Участник
455
9
в onServerMessage я отследил цифры и сохранил их в ременную nmbr. как мне взаимодействовать с каждыми цифрами по отдельности с интервалом в 1 сек?
мол, чтобы я получил какие-то цифры, например (3 7 1 4), сохранил в ременную (если надо) и к каждой этой цифре раз в 1 сек будет прописывать к примеру sampAddChatMessage('число '..nmbr..' ++')
 

Gorskin

{Reverse Developer} ✓
Проверенный
1,253
1,057
Как заставить игру обновить текстуры? т.е чтобы она по новой их отрисовала. Вот например тут callFunction(0x40D7C0, 1, 1, -1) происходит очистка памяти (текстуры обновляются, только если смотреть в определенную строну. Типо когда смотрю на север или юг то видно обновление текстур, а если запад или восток то нет). Подскажите пожалуйста как сделать такое через callFunction, или callMethod. Мне надо обновить текстуры чтобы применить анизотропную фильтрацию не перезаходя в игру. И чтобы это не зависило от того куда направлена моя камера. Короче говоря мне надо все текстуры сделать лодами и обратно.
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,225
в onServerMessage я отследил цифры и сохранил их в ременную nmbr. как мне взаимодействовать с каждыми цифрами по отдельности с интервалом в 1 сек?
мол, чтобы я получил какие-то цифры, например (3 7 1 4), сохранил в ременную (если надо) и к каждой этой цифре раз в 1 сек будет прописывать к примеру sampAddChatMessage('число '..nmbr..' ++')
Lua:
local nmbr = '1337228'

for i = 1, #nmbr do
    local number_char = tostring(nmbr):sub(i, i)
end
1634313044299.png
 

Мира

Участник
455
9
Lua:
local nmbr = '1337228'

for i = 1, #nmbr do
    local number_char = tostring(nmbr):sub(i, i)
end
Посмотреть вложение 117976
а... думал легко хукну несколько цветов, но нет. пишу в чат примером "321 439", выводится только первое число "321".
мне бы как бы все сохранять по отдельности
Lua:
if text:find('%{FFFFFF%}%a+%_%a+%[%d+%] говорит%:%{B7AFAF%}  (%d+)') then
    nmbr = text:match('%{FFFFFF%}%a+%_%a+%[%d+%] говорит%:%{B7AFAF%}  (%d+)')
    sampAddChatMessage(nmbr, -1)
end
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,225
Как в коде прописать, чтобы создавало папку с именем и в ней файл ini?
если делаешь кфг для настроек, то делай так:
Lua:
local inicfg = require 'inicfg'
local directIni = 'ConfigFileName.ini'
local ini = inicfg.load(inicfg.load({
    section1 = {
        key1 = true,
        key2 = 'string',
        key3 = 5,
    },
}, directIni))
inicfg.save(ini, directIni)
файл создается в папке moonloader\config (папка config создается сама)
 
  • Нравится
Реакции: Mr.Mastire222

Mr.Mastire222

Известный
529
259
если делаешь кфг для настроек, то делай так:
Lua:
local inicfg = require 'inicfg'
local directIni = 'ConfigFileName.ini'
local ini = inicfg.load(inicfg.load({
    section1 = {
        key1 = true,
        key2 = 'string',
        key3 = 5,
    },
}, directIni))
inicfg.save(ini, directIni)
файл создается в папке moonloader\config (папка config создается сама)
как в ней менять кодировку? чтоб в кодриовке 1251 создавался файл ини?