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

MLycoris

На вид оружие массового семяизвержения
Проверенный
1,991
2,190
Lua:
-- пример использования
if imgui.ColoredButton(u8'Кнопка', '32CD32') then
    sampAddChatMessage('Кнопка нажата', -1)
end
if imgui.ColoredButton(u8'Кнопка2', 'F94242', 50) then
    sampAddChatMessage('Кнопка нажата', -1)
end
if imgui.ColoredButton(u8'Кнопка3', '0000F9', 60, imgui.ImVec2(280, 24)) then
    sampAddChatMessage('Кнопка нажата', -1)
end

-- где нибудь в коде
function imgui.ColoredButton(text,hex,trans,size) -- 1 назв, 2 цвет, 3 прозрачность (необяз), 4 размер (необяз)
    local r,g,b = tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6))
    if tonumber(trans) ~= nil and tonumber(trans) < 101 and tonumber(trans) > 0 then
        a = trans
    else a = 60 end
    imgui.PushStyleColor(imgui.Col.Button, imgui.ImVec4(r/255, g/255, b/255, a/100))
    imgui.PushStyleColor(imgui.Col.ButtonHovered, imgui.ImVec4(r/255, g/255, b/255, a/100))
    imgui.PushStyleColor(imgui.Col.ButtonActive, imgui.ImVec4(r/255, g/255, b/255, a/100))
    local button = imgui.Button(text, size)
    imgui.PopStyleColor(3)
    return button
end
1688159583936.png


Спасибо, а что означает 50? или 60
Прозрачность, я написал в начале функции
 
  • Нравится
Реакции: sep и tsunamiqq

tsunamiqq

Участник
433
17
Lua:
-- пример использования
if imgui.ColoredButton(u8'Кнопка', '32CD32') then
    sampAddChatMessage('Кнопка нажата', -1)
end
if imgui.ColoredButton(u8'Кнопка2', 'F94242', 50) then
    sampAddChatMessage('Кнопка нажата', -1)
end
if imgui.ColoredButton(u8'Кнопка3', '0000F9', 60, imgui.ImVec2(280, 24)) then
    sampAddChatMessage('Кнопка нажата', -1)
end

-- где нибудь в коде
function imgui.ColoredButton(text,hex,trans,size) -- 1 назв, 2 цвет, 3 прозрачность (необяз), 4 размер (необяз)
    local r,g,b = tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6))
    if tonumber(trans) ~= nil and tonumber(trans) < 101 and tonumber(trans) > 0 then
        a = trans
    else a = 60 end
    imgui.PushStyleColor(imgui.Col.Button, imgui.ImVec4(r/255, g/255, b/255, a/100))
    imgui.PushStyleColor(imgui.Col.ButtonHovered, imgui.ImVec4(r/255, g/255, b/255, a/100))
    imgui.PushStyleColor(imgui.Col.ButtonActive, imgui.ImVec4(r/255, g/255, b/255, a/100))
    local button = imgui.Button(text, size)
    imgui.PopStyleColor(3)
    return button
end
Посмотреть вложение 206378
Спасибо, а как изменить цвет beginchild? так-же в mimgui
 

tsunamiqq

Участник
433
17
Кроме смены всей темы, не знаю
Жаль

Lua:
-- пример использования
if imgui.ColoredButton(u8'Кнопка', '32CD32') then
    sampAddChatMessage('Кнопка нажата', -1)
end
if imgui.ColoredButton(u8'Кнопка2', 'F94242', 50) then
    sampAddChatMessage('Кнопка нажата', -1)
end
if imgui.ColoredButton(u8'Кнопка3', '0000F9', 60, imgui.ImVec2(280, 24)) then
    sampAddChatMessage('Кнопка нажата', -1)
end

-- где нибудь в коде
function imgui.ColoredButton(text,hex,trans,size) -- 1 назв, 2 цвет, 3 прозрачность (необяз), 4 размер (необяз)
    local r,g,b = tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6))
    if tonumber(trans) ~= nil and tonumber(trans) < 101 and tonumber(trans) > 0 then
        a = trans
    else a = 60 end
    imgui.PushStyleColor(imgui.Col.Button, imgui.ImVec4(r/255, g/255, b/255, a/100))
    imgui.PushStyleColor(imgui.Col.ButtonHovered, imgui.ImVec4(r/255, g/255, b/255, a/100))
    imgui.PushStyleColor(imgui.Col.ButtonActive, imgui.ImVec4(r/255, g/255, b/255, a/100))
    local button = imgui.Button(text, size)
    imgui.PopStyleColor(3)
    return button
end
Посмотреть вложение 206378


Прозрачность, я написал в начале функции
Текст то оно изменяет, но размер нет
UPD: Установил прозрачность, заработало

У кого есть togglebutton для mimgui ? Можете дать пожалуйста
 
Последнее редактирование:

Дядя Энрик.

Активный
338
81
Жаль


Текст то оно изменяет, но размер нет
UPD: Установил прозрачность, заработало

У кого есть togglebutton для mimgui ? Можете дать пожалуйста
Lua:
function imgui.ToggleButton(str_id, bool)
    local rBool = false

    local p = imgui.GetCursorScreenPos()
    local draw_list = imgui.GetWindowDrawList()
    local height = 20
    local width = height * 1.55
    local radius = height * 0.50
    local animTime = 0.13
    
    local color_active = imgui.GetStyle().Colors[imgui.Col.CheckMark]
    local color_inactive = imgui.ImVec4(100 / 255, 100 / 255, 100 / 255, 180 / 255)

    if imgui.InvisibleButton(str_id, imgui.ImVec2(width, height)) then
        bool[0] = not bool[0]
        rBool = true
        LastActiveTime[tostring(str_id)] = clock()
        LastActive[tostring(str_id)] = true
    end

    local hovered = imgui.IsItemHovered()

    imgui.SameLine()
    imgui.SetCursorPosY(imgui.GetCursorPosY()+3)
    imgui.Text(str_id)

    local t = bool[0] and 1.0 or 0.0

    if LastActive[tostring(str_id)] then
        local time = clock() - LastActiveTime[tostring(str_id)]
        if time <= animTime then
            local t_anim = ImSaturate(time / animTime)
            t = bool[0] and t_anim or 1.0 - t_anim
        else
            LastActive[tostring(str_id)] = false
        end
    end

    local col_bg = bringVec4To(not bool[0] and color_active or color_inactive, bool[0] and color_active or color_inactive, LastActiveTime[tostring(str_id)] or 0, animTime)

    draw_list:AddRectFilled(imgui.ImVec2(p.x, p.y + (height / 6)), imgui.ImVec2(p.x + width - 1.0, p.y + (height - (height / 6))), imgui.ColorConvertFloat4ToU32(col_bg), 10.0)
    draw_list:AddCircleFilled(imgui.ImVec2(p.x + (bool[0] and radius + 1.5 or radius - 3) + t * (width - radius * 2.0), p.y + radius), radius - 6, imgui.ColorConvertFloat4ToU32(imgui.GetStyle().Colors[imgui.Col.Text]))

    return rBool
end
 

tsunamiqq

Участник
433
17
Lua:
function imgui.ToggleButton(str_id, bool)
    local rBool = false

    local p = imgui.GetCursorScreenPos()
    local draw_list = imgui.GetWindowDrawList()
    local height = 20
    local width = height * 1.55
    local radius = height * 0.50
    local animTime = 0.13
  
    local color_active = imgui.GetStyle().Colors[imgui.Col.CheckMark]
    local color_inactive = imgui.ImVec4(100 / 255, 100 / 255, 100 / 255, 180 / 255)

    if imgui.InvisibleButton(str_id, imgui.ImVec2(width, height)) then
        bool[0] = not bool[0]
        rBool = true
        LastActiveTime[tostring(str_id)] = clock()
        LastActive[tostring(str_id)] = true
    end

    local hovered = imgui.IsItemHovered()

    imgui.SameLine()
    imgui.SetCursorPosY(imgui.GetCursorPosY()+3)
    imgui.Text(str_id)

    local t = bool[0] and 1.0 or 0.0

    if LastActive[tostring(str_id)] then
        local time = clock() - LastActiveTime[tostring(str_id)]
        if time <= animTime then
            local t_anim = ImSaturate(time / animTime)
            t = bool[0] and t_anim or 1.0 - t_anim
        else
            LastActive[tostring(str_id)] = false
        end
    end

    local col_bg = bringVec4To(not bool[0] and color_active or color_inactive, bool[0] and color_active or color_inactive, LastActiveTime[tostring(str_id)] or 0, animTime)

    draw_list:AddRectFilled(imgui.ImVec2(p.x, p.y + (height / 6)), imgui.ImVec2(p.x + width - 1.0, p.y + (height - (height / 6))), imgui.ColorConvertFloat4ToU32(col_bg), 10.0)
    draw_list:AddCircleFilled(imgui.ImVec2(p.x + (bool[0] and radius + 1.5 or radius - 3) + t * (width - radius * 2.0), p.y + radius), radius - 6, imgui.ColorConvertFloat4ToU32(imgui.GetStyle().Colors[imgui.Col.Text]))

    return rBool
end
Не работает
Lua:
attempt to index global 'LastActive' (a nil value) stack traceback:
 

MLycoris

На вид оружие массового семяизвержения
Проверенный
1,991
2,190
Не работает
Lua:
attempt to index global 'LastActive' (a nil value) stack traceback:
 

tsunamiqq

Участник
433
17
Спасибо, а где там цвет сменить кнопки?
И как убрать округленность? Что-бы было по типу такого
1688222147523.png
 
Последнее редактирование:

ChаtGPT

Активный
397
96
Добрый вечер.
У меня есть задача: Необходимо сделать проверку и сравнить цвет игрока и цвет ганг зоны, на которой он находится. Я не могу понять, почему выходит 2 разных цвета, пытался конвертировать, тоже самое. Цвет ника - красный, цвет территории - красный, проверка не проходит, не знаю что делать.

Код:
local gang_zone_color
local set_player_color
local zones = {}

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('getgz', function()
        local zone = getPlayerGangZone(PLAYER_PED)
        print('onSetPlayerColor: '..set_player_color..' hex_to_argb: '..hex_to_argb(set_player_color))
        print('onCreateGangZone: '..gang_zone_color..' hex_to_argb: '..hex_to_argb(gang_zone_color))
        if gang_zone_color == set_player_color then
             print('+')
        end
    end)
    wait(-1)
end

function sampev.onCreateGangZone(zoneId, squareStart, squareEnd, color)
    zones[zoneId] = {
        from = squareStart,
        to = squareEnd
    }
    gang_zone_color = color -- Получаю и записываю цвет ганг зоны
end

---@param ped any Player handle
---@return number | nil id
function getPlayerGangZone(ped)
    for id, data in pairs(zones) do
        if isCharInArea3d(ped, data.from.x, data.from.y, -100, data.to.x, data.to.y, 1000, false) then  -- 00A4
            return id
        end
    end
end


function sampev.onSetPlayerColor(playerID, color) -- Вызывается каждый раз, когда у любого игрока на сервере меняется цвет
    local result, id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- Получаем id нашего персонажа
    if id == playerID then -- Проверяем, если id того персонажа, у которого изменился цвет совпадает с id нашего персонажа
        local ccolr = sampGetPlayerColor(PLAYER_PED)
        set_player_color = color
      sampAddChatMessage("onSetPlayerColor| "..color..' |sampGetPlayerColor| '..ccolr, 16777215) -- Добавляем в чат строчку о том, что изменился цвет. Второй аргумент - цвет (16777215 - FFFFFF (белый) в десятичной системе счисления)
    end
end




function join_argb(a, r, g, b)
    local argb = b  -- b
    argb = bit.bor(argb, bit.lshift(g, 8))  -- g
    argb = bit.bor(argb, bit.lshift(r, 16)) -- r
    argb = bit.bor(argb, bit.lshift(a, 24)) -- a
    return argb
end

function hex_to_argb(hex)
    local a, r, g, b = explode_argb(tonumber(hex, 16))
    return a, r, g, b
end

function explode_argb(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
 

Heav

Активный
185
71
Привет. Можно ли как-то уменьшить количество imgui.Text() в скрипте все так же имея возможность задать вертикальный отступ между каждой строкой? Для этого я использую imgui.PushStyleVarVec2(imgui.StyleVar.ItemSpacing, imgui.ImVec2(5, 16)), однако если использовать \n для новой строки внутри
imgui.Text(), то возможность задавать таким образом отступ теряется. Пример кода ниже, всем спасибо за ответы!


Screenshot 2023-07-02 071325.png
Screenshot 2023-07-02 071308.png


Lua:
imgui.NextColumn()
imgui.Text(u8'Время') imgui.SetColumnWidth(-1, w.second) -- второй столбик
imgui.PushStyleVarVec2(imgui.StyleVar.ItemSpacing, imgui.ImVec2(5, 16))
        imgui.Text(u8'0:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'2:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'2:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'4:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'7:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'0:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'9:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'10:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'12:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'16:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'19:25') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'20:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'22:30') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'23:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'0:00') imgui.SetColumnWidth(-1, 100)
        imgui.PopStyleVar(1)
 

Дядя Энрик.

Активный
338
81
Привет. Можно ли как-то уменьшить количество imgui.Text() в скрипте все так же имея возможность задать вертикальный отступ между каждой строкой? Для этого я использую imgui.PushStyleVarVec2(imgui.StyleVar.ItemSpacing, imgui.ImVec2(5, 16)), однако если использовать \n для новой строки внутри
imgui.Text(), то возможность задавать таким образом отступ теряется. Пример кода ниже, всем спасибо за ответы!


Посмотреть вложение 206521Посмотреть вложение 206522

Lua:
imgui.NextColumn()
imgui.Text(u8'Время') imgui.SetColumnWidth(-1, w.second) -- второй столбик
imgui.PushStyleVarVec2(imgui.StyleVar.ItemSpacing, imgui.ImVec2(5, 16))
        imgui.Text(u8'0:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'2:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'2:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'4:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'7:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'0:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'9:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'10:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'12:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'16:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'19:25') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'20:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'22:30') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'23:00') imgui.SetColumnWidth(-1, 100)
        imgui.Text(u8'0:00') imgui.SetColumnWidth(-1, 100)
        imgui.PopStyleVar(1)
Lua:
local time = {
   '0:00', '2:00', '4:00', '7:00', '0:00'
}
        imgui.Text(u8'Время')
        for i, text in pairs(time) do
            imgui.Text(u8(text))
        end
попробуй такой вариант
 
  • Нравится
Реакции: Heav