Полезные сниппеты и функции

Vespan

loneliness
Проверенный
2,139
1,781
не знаю как названить ну кароче улучшеный поиск в таблице по ключу
Lua:
tableKey = function(self, key)
    for k,v in pairs(self) do
        for l in k:gmatch("[^.]+") do
            if l == key then
                return v
            end
        end
    end
end
Lua:
local tbl = {
    ['bool8.bool32.int'] = "bool",
    ['fixedString32.encodedString2048.encodedString4096'] = "string32",
    ['compressedFloat'] = "float",
}
print(tableKey(tbl,"int")) -- bool
print(tableKey(tbl,"encodedString2048")) -- string32
print(tableKey(tbl,"booling")) -- nil

--все же лучше чем
local tbl = {
    ['bool8'] = "bool",
    ['bool32'] = "bool",
    ['int'] = "bool",
    ['fixedString32'] = "string32",
    ['encodedString2048'] = "string32",
    ['encodedString4096'] = "string32",
    ['compressedFloat'] = "float",
}
 
Последнее редактирование:

kirieshki.

Новичок
20
16
Переливающийся текст, работает с renderFontDrawText
Так как темы такой не нашёл, делаю свою.
Пример:

Код:
Lua:
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 string.insert(str1, str2, pos) -- функция вставки строки в строку по позиции
    return str1:sub(1,pos)..str2..str1:sub(pos+1)
end

function gradient_text(text, speed)
    local time = os.clock()
    local a = 255
    for i=string.len(RText) - 1, 0, -1 do
        local r = math.floor(math.sin((time * speed + i / 7)) * 127 + 128)
        local g = math.floor(math.sin((time * speed + i / 7)  + 2) * 127 + 128)
        local b = math.floor(math.sin((time * speed + i / 7)  + 3) * 127 + 128)
        local col = join_argb(a, r, g, b)
        local hex = ('%06X'):format(col)
        local hex = string.sub(hex, string.len(hex) - 5, string.len(hex))
        local hex = '{'..hex..'}'
        RText = string.insert(RText, hex, i)
    end
    return string.insert(text, RText, string.len(text))
end

Пример использования кода:
Lua:
-- лучше использовать в цикле while true в функции main()
local text = 'privet'
renderFontDrawText(font, 'privet'..gradient_text(text, 1), x, y, 0xFFFFFFFF)
 

Вложения

  • Arizona-RP-2025-01-27-00-05-48-_online-video-cutter.com_.gif
    Arizona-RP-2025-01-27-00-05-48-_online-video-cutter.com_.gif
    42.1 KB · Просмотры: 139

chromiusj

Стань той переменой, которую хочешь увидеть в мире
Модератор
5,729
4,039
Переливающийся текст, работает с renderFontDrawText
Так как темы такой не нашёл, делаю свою.
Пример:

Код:
Lua:
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 string.insert(str1, str2, pos) -- функция вставки строки в строку по позиции
    return str1:sub(1,pos)..str2..str1:sub(pos+1)
end

function gradient_text(text, speed)
    local time = os.clock()
    local a = 255
    for i=string.len(RText) - 1, 0, -1 do
        local r = math.floor(math.sin((time * speed + i / 7)) * 127 + 128)
        local g = math.floor(math.sin((time * speed + i / 7)  + 2) * 127 + 128)
        local b = math.floor(math.sin((time * speed + i / 7)  + 3) * 127 + 128)
        local col = join_argb(a, r, g, b)
        local hex = ('%06X'):format(col)
        local hex = string.sub(hex, string.len(hex) - 5, string.len(hex))
        local hex = '{'..hex..'}'
        RText = string.insert(RText, hex, i)
    end
    return string.insert(text, RText, string.len(text))
end

Пример использования кода:
Lua:
-- лучше использовать в цикле while true в функции main()
local text = 'privet'
renderFontDrawText(font, 'privet'..gradient_text(text, 1), x, y, 0xFFFFFFFF)
я сначала подумал, что цвет текста можно произвольный делать, но внимательно посмотрел
короче все придумали еще задавно посмотришь в сурсах
 

ARMOR

Мне кажется, я всё проебал
Модератор
5,022
7,098
В муне 0.26 неправильно получается и устанавливается кватернион сущностей, в 0.27 это было исправлено, но почти никто не использует 0.27 так что вот:

Описание: Получает кватернион сущности по её указателю ( не по хендлу )
Lua:
local ffi = require("ffi")
ffi.cdef[[
    typedef struct CVector CVector;
    #pragma pack(push, 8)
    struct CVector
    {
        float x;
        float y;
        float z;
    };
    #pragma pack(pop)
    typedef struct CMatrix CMatrix;
    #pragma pack(push, 8)
    struct CMatrix
    {
        CVector right;
        unsigned int flags;
        CVector up;
        unsigned int pad1;
        CVector at;
        unsigned int pad2;
        CVector pos;
        unsigned int pad3;
        CMatrix *m_pAttachMatrix;
        int m_bAttachMatrixTemporary;
    };
    #pragma pack(pop)
    typedef struct CQuaternion CQuaternion;
    #pragma pack(push, 8)
    struct CQuaternion
    {
        CVector imag;
        float real;
    };
    #pragma pack(pop)
]]

local CPlaceable__GetMatrix = ffi.cast("CMatrix*(__thiscall*)(uintptr_t)", 0x411990)

function matrixToQuaternion(matrix)
    local trace = matrix.right.x + matrix.up.y + matrix.at.z
    local q = ffi.new("CQuaternion")
    
    if trace > 0 then
        local s = math.sqrt(trace + 1) * 2
        q.real = 0.25 * s
        q.imag.x = (matrix.at.y - matrix.up.z) / s
        q.imag.y = (matrix.right.z - matrix.at.x) / s
        q.imag.z = (matrix.up.x - matrix.right.y) / s
    else
        if matrix.right.x > matrix.up.y and matrix.right.x > matrix.at.z then
            local s = math.sqrt(1 + matrix.right.x - matrix.up.y - matrix.at.z) * 2
            q.real = (matrix.at.y - matrix.up.z) / s
            q.imag.x = 0.25 * s
            q.imag.y = (matrix.right.y + matrix.up.x) / s
            q.imag.z = (matrix.right.z + matrix.at.x) / s
        elseif matrix.up.y > matrix.at.z then
            local s = math.sqrt(1 + matrix.up.y - matrix.right.x - matrix.at.z) * 2
            q.real = (matrix.right.z - matrix.at.x) / s
            q.imag.x = (matrix.right.y + matrix.up.x) / s
            q.imag.y = 0.25 * s
            q.imag.z = (matrix.up.z + matrix.at.y) / s
        else
            local s = math.sqrt(1 + matrix.at.z - matrix.right.x - matrix.up.y) * 2
            q.real = (matrix.up.x - matrix.right.y) / s
            q.imag.x = (matrix.right.z + matrix.at.x) / s
            q.imag.y = (matrix.up.z + matrix.at.y) / s
            q.imag.z = 0.25 * s
        end
    end
    return q.imag.x, q.imag.y, q.imag.z, q.real
end

function GetEntityQuaternion(pEntity)
    local x, y, z, w = 0, 0, 0, 0;
    local pMatrix = CPlaceable__GetMatrix(pEntity)
    if (pMatrix ~= 0 or pEntity ~= 0) then
        x, y, z, w = matrixToQuaternion(pMatrix);
    end
    return x, y, z, w;
end

Описание: Изменяет кватернион сущности по её указателю ( Не хендлу )
Lua:
local ffi = require("ffi")
ffi.cdef[[
    typedef struct CVector CVector;
    #pragma pack(push, 8)
    struct CVector
    {
        float x;
        float y;
        float z;
    };
    #pragma pack(pop)
    typedef struct CMatrix CMatrix;
    #pragma pack(push, 8)
    struct CMatrix
    {
        CVector right;
        unsigned int flags;
        CVector up;
        unsigned int pad1;
        CVector at;
        unsigned int pad2;
        CVector pos;
        unsigned int pad3;
        CMatrix *m_pAttachMatrix;
        int m_bAttachMatrixTemporary;
    };
    #pragma pack(pop)
    typedef struct CQuaternion CQuaternion;
    #pragma pack(push, 8)
    struct CQuaternion
    {
        CVector imag;
        float real;
    };
    #pragma pack(pop)
]]

local CPlaceable__GetMatrix = ffi.cast("CMatrix*(__thiscall*)(uintptr_t)", 0x411990)
local CMatrix__SetRotate = ffi.cast("void(__thiscall*)(CMatrix*, CQuaternion*)", 0x59BBF0)
local CEntity__UpdateRwFrame = ffi.cast("void(__thiscall*)(uintptr_t)", 0x532B00)
local CEntity__UpdateRW = ffi.cast("void(__thiscall*)(uintptr_t)", 0x446F90)

function setEntityQuaternion(pEntity, x, y, z, w)
    if (pEntity) then
        local quaternion = ffi.new("CQuaternion");
        quaternion.imag.x = x;
        quaternion.imag.y = y;
        quaternion.imag.z = z;
        quaternion.real = -w;
        local pMatrix = CPlaceable__GetMatrix(pEntity);
        CMatrix__SetRotate(pMatrix, quaternion);
        CEntity__UpdateRwFrame(pEntity)
        CEntity__UpdateRW(pEntity)
    end
end

Пример использования:
Lua:
function main()
    while true do
        wait(0)
        if isCharInAnyCar(playerPed) then
            local handle = storeCarCharIsInNoSave(playerPed)
            local pVehicle = getCarPointer(handle)
            local x, y, z, w = GetEntityQuaternion(pVehicle)
            setVehicleQuaternion(handle, x, y, z, w)
        end
    end
end
 

moreveal

Известный
Проверенный
928
623
description: Function to prevent a user from renaming the name of the Script.

code:
-- function to prevent renaming your script

function checkScriptName(correct_name)
    if thisScript().filename ~= correct_name then
        thisScript():unload()
    end

    if thisScript().filename ~= correct_name then
        sampAddChatMessage("Do not rename the script.", -1)
        os.rename(thisScript().path, thisScript().directory .. "\\" .. correct_name)
        thisScript():reload()
    end
end
unloading and then renaming? lol
 
  • Нравится
Реакции: Willy4ka и Cloud.

Vespan

loneliness
Проверенный
2,139
1,781
Пути навигации ИИ в одиночной игре (взять все из /data/paths/*.dat)
sa-mp-000.png
sa-mp-000.png
не ебу, на воде координаты, на суше и на воздухе так и по z = 0, возможно для миссий

применение - тепнуть игрока на тратуар, машину на дорогу(да есть в муне для этого функция ну не важно), или ботов так можно сделать которые по тратуару будут ходить к заданой точке!?!?!?!
вообщем, не важно, мозг присуствует(луашко) придумаете сами

(вроде была тема/ответ с нодами но не нашел, да и вроде там только ноды по транспорту были)
(вроде были еще ноды для полета транспорта, как найду то обновлю ответ)(луашко)
 

Вложения

  • peds.json
    1.9 MB · Просмотры: 3
  • cars.json
    1.5 MB · Просмотры: 5
  • navi.json
    1.4 MB · Просмотры: 4

vuule

Новичок
7
0
Открывает/Закрывает консоль sampfuncs

Lua:
local ffi = require("ffi")
local sampfuncs = getModuleHandle("SampFuncs.asi")
-- R1
function setSFConsoleState(bValue)
    local pSfConsole = ffi.cast("void**", sampfuncs + 0x11572C)[0]
    ffi.cast("void(__thiscall*)(void*, bool)", sampfuncs + 0x12EBB)(pSfConsole, bValue)
end
-- R3
function setSFConsoleState(bValue)
    local pSfConsole = ffi.cast("void**", sampfuncs + 0x1136C0)[0]
    ffi.cast("void(__thiscall*)(void*, bool)", sampfuncs + 0x131E7)(pSfConsole, bValue)
end

Пример использования:
Lua:
setSFConsoleState(true)
Is this all because I tried to see if it would work, otherwise I use R3 but it won't work at all
 

UBP

Известный
369
246
---Форматирует JSON строку с отступами
Lua:
---Форматирует JSON строку с отступами
---@param str string JSON строка
---@param indent number|nil Размер отступа (по умолчанию 2)
---@return string formatted Отформатированная строка
local function format_json(str, indent)
    indent = indent or 2
    local formatted = str:gsub("%{", "{\n"):gsub("%}", "\n}")
                        :gsub("%[", "[\n"):gsub("%]", "\n]")
                        :gsub(",%s*", ",\n")
   
    local level = 0
    local result = {}
    for line in formatted:gmatch("[^\n]+") do
        level = level - (line:match("^%s*[%]%}]") and 1 or 0)
        table.insert(result, string.rep(" ", level * indent) .. line:match("^%s*(.-)%s*$"))
        level = level + (line:match("[%{%[]%s*$") and 1 or 0)
    end
    return table.concat(result, "\n")
end
-- Функция для создания отсортированной таблицы
Lua:
-- Порядок полей для разных типов
local field_orders = {
    default = {
        __type = 1,
        value = 2,
        size = 3,
        x = 4,
        y = 5,
        z = 6,
        w = 7
    },
    vec2 = {
        __type = 1,
        x = 2,
        y = 3
    },
    vec4 = {
        __type = 1,
        x = 2,
        y = 3,
        z = 4,
        w = 5
    }
}
-- Функция сортировки ключей вспомогательного массива
--@param keys table Таблица ключей
---@param value_type string Тип значения
local function sort_keys(keys, value_type, data)
    if not data then return keys end
    local order = field_orders[value_type] or field_orders.default
    table.sort(keys, function(a, b)
        local a_val = data[a]
        local b_val = data[b]
        local a_has_type = type(a_val) == 'table' and a_val.__type
        local b_has_type = type(b_val) == 'table' and b_val.__type
        if (a_has_type and b_has_type) or (not a_has_type and not b_has_type) then
            local is_num_a = type(a) == 'number'
            local is_num_b = type(b) == 'number'
           
            if is_num_a ~= is_num_b then
                return is_num_a
            end
            if is_num_a and is_num_b then
                return a < b
            end
            return tostring(a) < tostring(b)
        end
        return a_has_type
    end)
    return keys
end

-- Функция для создания отсортированной таблицы
--@param data table Данные для сортировки
--@return table Отсортированная таблица
local function create_sorted_table(data, value_type)
    if type(data) ~= 'table' then return data end
    local keys = {}
    for k in pairs(data) do
        table.insert(keys, k)
    end
    keys = sort_keys(keys, value_type or (data.__type and data.__type or 'default'), data)
    local result = {}
    for _, k in ipairs(keys) do
        local v = data[k]
        result[k] = create_sorted_table(v, type(v) == 'table' and v.__type)
    end
    return result
end


Вырезано из https://www.blast.hk/threads/228834/
 

Vespan

loneliness
Проверенный
2,139
1,781
легчайшей функцией отправлять nebo читать много данных в/из snet
client/server
Lua:
bstream_class = getmetatable(snet.bstream.new()).__index
function bstream_class:massiveRead(...)
    local result = {}
    for _,_type in pairs({...}) do
        local v_len = (type(_type) == 'table' and self:read(_type[2]) or nil)
        table.insert(result, self:read((type(_type) == 'table' and _type[1] or _type), v_len) )
    end
    return unpack(result)
end
function bstream_class:massiveWrite(...)
    for _,t in pairs({...}) do
        if #t == 3 then--if this string
            self:write(t[2], #t[3])
        end
        self:write(t[1], t[#t])
    end
    return self
end
bstream = snet.bstream

Lua:
local bs = bstream.new()
bs:massiveWrite({BS_BOOLEAN, public}, {BS_STRING,BS_UINT8, name})
client:send(1, bs, 4)     
--
local public, name = bs:massiveRead(BS_BOOLEAN, {BS_STRING, BS_UINT8})
print(public,name)
--
server:send(710, bstream.new():massiveWrite({BS_UINT8, id},{BS_STRING,BS_UINT8,nickname}),4,address,port)
 
Последнее редактирование:

Cosmo

Известный
Друг
660
2,796
Описание:
В апи мунлоадера есть функция sampSetLocalPlayerName, но нет её обратного варианта для получения локального ника. Теперь есть. На мой взгляд это более логично и быстрее, чем получать сначала свой айди, а потом по нему уже получать свой ник. Кстати, функцию получения локального ID тоже добавил. Спасибо за помощь @ARMOR

Код функций (для 0.3.7 R3):

Lua:
local SAMP = getModuleHandle("samp.dll")
local CPlayerPool__GetLocalPlayerName = ffi.cast("const char*(__thiscall*)(uintptr_t)", SAMP + 0xA170)
local CNetGame__GetPlayerPool = ffi.cast("uintptr_t(__thiscall*)(uintptr_t)", SAMP + 0x1160)

function sampGetLocalPlayerName()
    local pNetGame = ffi.cast("uintptr_t*", SAMP + 0x26E8DC)[0]
    local pPlayerPool = CNetGame__GetPlayerPool(pNetGame)
    local szName = CPlayerPool__GetLocalPlayerName(pPlayerPool)
    return ffi.string(szName)
end

function sampGetLocalPlayerId()
    local pNetGame = ffi.cast("uintptr_t*", SAMP + 0x26E8DC)[0]
    local pPlayerPool = CNetGame__GetPlayerPool(pNetGame)
    return ffi.cast("uint16_t*", pPlayerPool + 0x2F1C)[0]
end

Использование:
Lua:
local self_nick = sampGetLocalPlayerName()
local self_id = sampGetLocalPlayerId()

print(("%s(%d)"):format(self_nick, self_id)) -- Alpha_Cosmo(123)
 
Последнее редактирование:

ARMOR

Мне кажется, я всё проебал
Модератор
5,022
7,098
Описание: Получаем поворот кости педа по её ID.

Код:
Lua:
local ffi = require("ffi")

local CEntity__UpdateRpHAnim = ffi.cast("void(__thiscall*)(uintptr_t pEntity)", 0x532B20)
local GetAnimHierarchyFromSkinClump = ffi.cast("uintptr_t(__cdecl*)(uintptr_t pClump)", 0x734A40)
local RpHAnimIDGetIndex = ffi.cast("int32_t(__cdecl*)(uintptr_t pHierarchy, int32_t nId)", 0x7C51A0)

ffi.cdef[[
    #pragma pack(push, 8)
    typedef struct RwV3d RwV3d;
    struct RwV3d {
        float x, y, z;
    };
    #pragma pack(pop)

    #pragma pack(push, 8)
    typedef struct RwMatrixTag RwMatrixTag;
    struct RwMatrixTag
    {
        RwV3d right;
        int flags;
        RwV3d top;
        int pad1;
        RwV3d at;
        int pad2;
        RwV3d pos;
        int pad3;
    };
    #pragma pack(pop)
]]

function getBoneRotate(nHandle, nBoneId)
    local pPed = getCharPointer(nHandle)

    if (pPed == nil) then
        return false, 0, 0, 0
    end

    local pFlags = ffi.cast("int32_t*", pPed + 0x46C)

    local pTargetFlag = pFlags + 2

    if bit.band(pTargetFlag[0], 0x400) ~= 0 then
        CEntity__UpdateRpHAnim(pPed)
        pTargetFlag[0] = bit.bor(pTargetFlag[0], 0x400)
    end

    local pAnimHierarcy = GetAnimHierarchyFromSkinClump(ffi.cast("uintptr_t*", pPed + 0x18)[0])

    if (pAnimHierarcy ~= nil) then
        local nId = RpHAnimIDGetIndex(pAnimHierarcy, nBoneId)
        local mMatrix = ffi.cast("RwMatrixTag**", pAnimHierarcy + 0x8)[0][nId]

        local fPitch = math.asin(-mMatrix.at.y) * (180 / math.pi)
        local fYaw   = math.atan2(mMatrix.at.x, mMatrix.at.z) * (180 / math.pi)
        local fRoll  = math.atan2(mMatrix.top.y, mMatrix.right.y) * (180 / math.pi)

        return true, fPitch, fYaw, fRoll
    end

    return false, 0, 0, 0
end

Пример использования:
Lua:
function main()
    while not isSampAvailable() do wait(0) end

    sampRegisterChatCommand("test", function ()
        local result, x, y, z = getBoneRotate(playerPed, 8)
        if (result) then
            sampAddChatMessage(string.format("x: %0.3f, y: %0.3f, z: %0.3f", x, y, z), -1)
        end
    end)

    wait(-1)
end
 
Последнее редактирование:

БеzликиЙ

Автор темы
Проверенный
954
549

Неадекватная сова

Известный
Проверенный
278
224
Посмотреть вложение 234891

Lua:
drawModernSlider("Прозрачность", sliderValue, 0.0, 1.0, 0.01, 200, 8, window_center)

Lua:
function drawModernSlider(label, value, min, max, step, slider_length, slider_height, slider_pos)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local cursor_pos = ImGui.GetCursorScreenPos()
    local slider_length = slider_length or 200 -- длина слайдера
    local slider_height = slider_height or 8 -- высота слайдера
    local knob_radius = 10 -- радиус ручки слайдера
    local value_normalized = (value[0] - min) / (max - min) -- нормализованное значение для расчета позиции ручки

    -- Рассчитываем позицию текста
    local text_pos = ImGui.ImVec2(slider_pos.x, slider_pos.y - 20) -- Позиция текста над слайдером

    -- Рисуем текст слайдера
    ImGui.SetCursorScreenPos(text_pos)
    ImGui.Text(label .. ": " .. string.format("%.2f", value[0]))

    -- Рисуем фон слайдера
    draw_list:AddRectFilled(ImGui.ImVec2(slider_pos.x, slider_pos.y), ImGui.ImVec2(slider_pos.x + slider_length, slider_pos.y + slider_height), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.5, 0.5, 0.5, 0.5)), slider_height / 2)

    -- Рисуем заполненную часть слайдера
    draw_list:AddRectFilled(ImGui.ImVec2(slider_pos.x, slider_pos.y), ImGui.ImVec2(slider_pos.x + slider_length * value_normalized, slider_pos.y + slider_height), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.26, 0.59, 0.98, 0.8)), slider_height / 2)

    -- Рисуем ручку слайдера
    local knob_pos = ImGui.ImVec2(slider_pos.x + slider_length * value_normalized, slider_pos.y + slider_height / 2)
    draw_list:AddCircleFilled(knob_pos, knob_radius, ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)), 16)

    -- Реализация взаимодействия с ручкой слайдера
    local is_hovered = ImGui.IsMouseHoveringRect(ImGui.ImVec2(knob_pos.x - knob_radius, knob_pos.y - knob_radius), ImGui.ImVec2(knob_pos.x + knob_radius, knob_pos.y + knob_radius))
    local mouse_delta = ImGui.GetIO().MouseDelta
    if is_hovered and ImGui.IsMouseDown(0) then
        value[0] = value[0] + mouse_delta.x * (max - min) / slider_length
        if value[0] < min then value[0] = min end
        if value[0] > max then value[0] = max end
    end

    -- Сдвигаем курсор после рисования слайдера
    ImGui.SetCursorScreenPos(ImGui.ImVec2(cursor_pos.x, slider_pos.y + slider_height + 20))
end
Посмотреть вложение 234895

Lua:
drawLoadingIndicator(window_center.x, window_center.y, 40, 8, {0.4, 0.6, 0.9, 1})
Lua:
function drawLoadingIndicator(x, y, radius, dotsCount, color)
    local draw_list = imgui.GetWindowDrawList()
    local centre = imgui.ImVec2(x, y)
    local time = os.clock()

    for i = 1, dotsCount do
        local angle = (time * 2 + i / dotsCount * 2 * math.pi) % (2 * math.pi)
        local dotRadius = radius * 0.1
        local dotX = centre.x + radius * math.cos(angle)
        local dotY = centre.y + radius * math.sin(angle)
        local alpha = (math.sin(time * 10 + i) + 1) / 2 -- Анимация прозрачности
        local dotColor = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color[1], color[2], color[3], alpha))

        draw_list:AddCircleFilled(imgui.ImVec2(dotX, dotY), dotRadius, dotColor)
    end
end



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

Lua:
drawRotatingGradientCircle(window_center.x, window_center.y, 50, 6)

Lua:
function drawRotatingGradientCircle(x, y, radius, segments)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local time = os.clock() * 0.5 -- Уменьшаем скорость вращения
    local full_circle = math.pi * 2
    local segment_angle = full_circle / segments

    for i = 0, segments - 1 do
        local start_angle = (i * segment_angle) + time
        local end_angle = start_angle + segment_angle
        -- Генерируем цвет на основе угла
        local r = math.abs(math.sin(start_angle)) -- Красный канал изменяется по синусу
        local g = math.abs(math.sin(start_angle + full_circle / 3)) -- Зеленый сдвигается на треть круга
        local b = math.abs(math.sin(start_angle + full_circle * 2 / 3)) -- Синий сдвигается на две трети
        local color = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(r, g, b, 1))

        draw_list:PathArcTo(ImGui.ImVec2(x, y), radius, start_angle, end_angle, 10)
        draw_list:PathStroke(color, false, 2.0)
    end
end


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


Lua:
 -- в рендер в начало или перед imgui.End()
drawNotifications()
-- Другой код интерфейса

-- вызываем после нажатия кнопки например
addNotification("Привет, это тестовое уведомление!", 5) -- текст и продолжительность в секундах
Lua:
local notifications = {}

function addNotification(text, duration)
    table.insert(notifications, {
        text = text,
        duration = duration,
        alpha = 0, -- начальная прозрачность
        state = "appearing" -- начальное состояние
    })
end

function drawNotifications()
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local screen_width, screen_height = getScreenResolution()
    local notification_height = 30
    local notification_margin = 10
    local animation_speed = 0.02

    for i, notification in ipairs(notifications) do
        if notification.state == "appearing" then
            notification.alpha = notification.alpha + animation_speed
            if notification.alpha >= 1 then
                notification.alpha = 1
                notification.state = "displaying"
                notification.display_start = os.clock()
            end
        elseif notification.state == "displaying" then
            if os.clock() - notification.display_start >= notification.duration then
                notification.state = "disappearing"
            end
        elseif notification.state == "disappearing" then
            notification.alpha = notification.alpha - animation_speed
            if notification.alpha <= 0 then
                table.remove(notifications, i)
            end
        end

        local text_size = ImGui.CalcTextSize(notification.text)
        local notification_width = text_size.x + 20
        local x = (screen_width - notification_width) / 2
        local y = screen_height - (notification_height + notification_margin) * i

        draw_list:AddRectFilled(ImGui.ImVec2(x, y), ImGui.ImVec2(x + notification_width, y + notification_height), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.1, 0.1, 0.1, notification.alpha)), 5)
        draw_list:AddText(ImGui.ImVec2(x + 10, y + (notification_height - text_size.y) / 2), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, notification.alpha)), notification.text)
    end
end

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


Lua:
local value1 = imgui.new.float(20)
local value2 = imgui.new.float(80)
drawDoubleValueSlider(window_center.x, window_center.y, 300, 0, 100, value1, value2, "Выберите диапазон")
Lua:
function drawDoubleValueSlider(x, y, width, min, max, value1, value2, label)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local sliderHeight = 20
    local knobRadius = 12
    local lineY = y + sliderHeight / 2
    local value1Pos = (value1[0] - min) / (max - min) * width
    local value2Pos = (value2[0] - min) / (max - min) * width
    local gradientStartColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.6, 0.6, 0.9, 1))
    local gradientEndColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.3, 0.3, 0.8, 1))
    local knobColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1))
    local textColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1))
    local shadowColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0, 0, 0, 0.5))

    -- Рисуем градиентную линию слайдера
    draw_list:AddRectFilledMultiColor(ImGui.ImVec2(x, lineY - sliderHeight / 2), ImGui.ImVec2(x + width, lineY + sliderHeight / 2), gradientStartColor, gradientEndColor, gradientEndColor, gradientStartColor)

    -- Рисуем активную область слайдера
    draw_list:AddRectFilled(ImGui.ImVec2(x + value1Pos, lineY - sliderHeight / 2), ImGui.ImVec2(x + value2Pos, lineY + sliderHeight / 2), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.26, 0.59, 0.98, 0.8)), knobRadius / 2)

    -- Рисуем ручки слайдера с тенью
    draw_list:AddCircleFilled(ImGui.ImVec2(x + value1Pos + 2, lineY + 2), knobRadius, shadowColor, 16)
    draw_list:AddCircleFilled(ImGui.ImVec2(x + value1Pos, lineY), knobRadius, knobColor, 16)
    draw_list:AddCircleFilled(ImGui.ImVec2(x + value2Pos + 2, lineY + 2), knobRadius, shadowColor, 16)
    draw_list:AddCircleFilled(ImGui.ImVec2(x + value2Pos, lineY), knobRadius, knobColor, 16)

    -- Рисуем текст слайдера
    if label then
        draw_list:AddText(ImGui.ImVec2(x + (width / 2) - ImGui.CalcTextSize(label).x / 2, y - 30), textColor, label)
    end

    -- Отображение текущих значений
    local valueText1 = string.format("%.2f", value1[0])
    local valueText2 = string.format("%.2f", value2[0])
    draw_list:AddText(ImGui.ImVec2(x + value1Pos - ImGui.CalcTextSize(valueText1).x / 2, lineY + knobRadius + 5), textColor, valueText1)
    draw_list:AddText(ImGui.ImVec2(x + value2Pos - ImGui.CalcTextSize(valueText2).x / 2, lineY + knobRadius + 5), textColor, valueText2)

    -- Взаимодействие с ручками слайдера
    local isHovered1 = ImGui.IsMouseHoveringRect(ImGui.ImVec2(x + value1Pos - knobRadius, lineY - knobRadius), ImGui.ImVec2(x + value1Pos + knobRadius, lineY + knobRadius))
    local isHovered2 = ImGui.IsMouseHoveringRect(ImGui.ImVec2(x + value2Pos - knobRadius, lineY - knobRadius), ImGui.ImVec2(x + value2Pos + knobRadius, lineY + knobRadius))
    local mouseDelta = ImGui.GetIO().MouseDelta.x
    if isHovered1 and ImGui.IsMouseDown(0) then
        value1[0] = math.min(math.max(value1[0] + mouseDelta * (max - min) / width, min), value2[0])
    elseif isHovered2 and ImGui.IsMouseDown(0) then
        value2[0] = math.max(math.min(value2[0] + mouseDelta * (max - min) / width, max), value1[0])
    end
end
Посмотреть вложение 234899
Lua:
drawLoadingIndicator(window_center.x, window_center.y, 50, 8, 0.1)

-- последнее значчение от 0 до 1


Lua:
function drawLoadingIndicator(x, y, radius, thickness, progress)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local start_angle = -math.pi / 2
    local max_angle = 2 * math.pi
    local progress_angle = start_angle + max_angle * progress
    local bg_color = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.2, 0.2, 1))
    local fg_color = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.4, 0.7, 0.2, 1))

    -- Рисуем фон индикатора
    draw_list:PathArcTo(ImGui.ImVec2(x, y), radius, start_angle, start_angle + max_angle, 64)
    draw_list:PathStroke(bg_color, false, thickness)

    -- Рисуем прогресс индикатора
    draw_list:PathArcTo(ImGui.ImVec2(x, y), radius, start_angle, progress_angle, 64)
    draw_list:PathStroke(fg_color, false, thickness)
end



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

Lua:
local tasks = {
    {name = "Задача 1", completed = false},
    {name = "Задача 2", completed = true},
    {name = "Задача 3", completed = false},
}

imgui.SetCursorPos(window_center)
drawTaskList(tasks)

Lua:
function drawTaskList(tasks)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()

    for i, task in ipairs(tasks) do
        local checkboxID = "##taskCheckbox" .. tostring(i)
        local checkboxSize = 20
        local cursorPos = ImGui.GetCursorScreenPos()
        local checkboxPos = {x = cursorPos.x + 5, y = cursorPos.y + 5}
        local textSize = ImGui.CalcTextSize(task.name)
        local rowHeight = math.max(checkboxSize, textSize.y) + 10
        local isChecked = ImGui.new.bool(task.completed)

        -- Рисуем кастомный чекбокс
        if ImGui.InvisibleButton(checkboxID, ImGui.ImVec2(checkboxSize, checkboxSize)) then
            task.completed = not task.completed
        end
        local col = task.completed and ImGui.GetColorU32(ImGui.Col.FrameBgActive) or ImGui.GetColorU32(ImGui.Col.FrameBg)
        draw_list:AddRectFilled(ImGui.ImVec2(checkboxPos.x, checkboxPos.y), ImGui.ImVec2(checkboxPos.x + checkboxSize, checkboxPos.y + checkboxSize), col, 4)
        if task.completed then
            draw_list:AddLine(ImGui.ImVec2(checkboxPos.x + 4, checkboxPos.y + checkboxSize / 2), ImGui.ImVec2(checkboxPos.x + checkboxSize - 4, checkboxPos.y + checkboxSize / 2), ImGui.GetColorU32(ImGui.Col.Text))
        end

        -- Рисуем текст задачи
        ImGui.SetCursorScreenPos(ImGui.ImVec2(cursorPos.x + checkboxSize + 10, cursorPos.y + (rowHeight - textSize.y) / 2))
        if task.completed then
            ImGui.PushStyleColor(ImGui.Col.Text, ImGui.ImVec4(0.5, 0.5, 0.5, 1)) -- Используем ImVec4 для цвета
        else
            ImGui.PushStyleColor(ImGui.Col.Text, ImGui.ImVec4(1, 1, 1, 1)) -- Белый цвет для невыполненных задач
        end
        ImGui.Text(task.name)
        ImGui.PopStyleColor()

        -- Сдвигаем курсор вниз для следующей задачи
        ImGui.SetCursorScreenPos(ImGui.ImVec2(cursorPos.x, cursorPos.y + rowHeight))
    end
end



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


Lua:
updateAndDrawFloatingTexts() -- где то в рендере имгуи

addFloatingText("Привет, мир!", 5, 1, 1, imgui.ImVec2(100, 100)) -- например по нажатию кнопки


Lua:
local floatingTexts = {}
function addFloatingText(text, duration, fadeInTime, fadeOutTime, position)
    table.insert(floatingTexts, {
        text = text,
        totalDuration = duration,
        fadeInTime = fadeInTime,
        fadeOutTime = fadeOutTime,
        position = position,
        alpha = 0,
        timer = 0
    })
end

function updateAndDrawFloatingTexts()
    local ImGui = imgui
    for i = #floatingTexts, 1, -1 do
        local ft = floatingTexts[i]
        ft.timer = ft.timer + ImGui.GetIO().DeltaTime

        -- Рассчитываем альфа-канал для эффекта появления и исчезновения
        if ft.timer < ft.fadeInTime then
            ft.alpha = ft.timer / ft.fadeInTime
        elseif ft.timer > (ft.totalDuration - ft.fadeOutTime) then
            ft.alpha = 1 - (ft.timer - (ft.totalDuration - ft.fadeOutTime)) / ft.fadeOutTime
        else
            ft.alpha = 1
        end

        -- Отрисовка текста с учетом альфа-канала
        ImGui.PushStyleColor(ImGui.Col.Text, ImGui.ImVec4(1, 1, 1, ft.alpha))
        ImGui.SetCursorPos(ft.position)
        ImGui.Text(ft.text)
        ImGui.PopStyleColor()

        -- Удаление текста, если его время отображения истекло
        if ft.timer >= ft.totalDuration then
            table.remove(floatingTexts, i)
        end
    end
end


Посмотреть вложение 234906
Lua:
drawLoadingIndicator2(window_center.x, window_center.y, 50, 12, 2)


Lua:
function drawLoadingIndicator2(centerX, centerY, radius, segments, speed)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local time = ImGui.GetTime()

    -- Определяем цвета для градиента
    local colors = {
        ImGui.ImVec4(0.4, 0.8, 1.0, 1), -- Светло-голубой
        ImGui.ImVec4(0.2, 0.4, 0.8, 1)  -- Темно-синий
    }

    for i = 1, segments do
        local angle = (2 * math.pi / segments) * (i - 1) + (time * speed)
        local segmentRadius = radius * (0.8 + 0.2 * math.sin(time * speed + i)) -- Радиус сегмента с анимацией

        -- Создаем градиент для сегмента
        local color = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(
            colors[1].x * (1 - i / segments) + colors[2].x * (i / segments),
            colors[1].y * (1 - i / segments) + colors[2].y * (i / segments),
            colors[1].z * (1 - i / segments) + colors[2].z * (i / segments),
            0.5 + 0.5 * math.sin(time * speed + i) -- Изменение прозрачности для создания эффекта глубины
        ))

        -- Рисуем сегменты с градиентом и эффектом глубины
        for layer = 1, 3 do
            local layerRadius = segmentRadius - (layer - 1) * 5 -- Уменьшаем радиус для создания слоев
            local center = ImGui.ImVec2(
                centerX + layerRadius * math.cos(angle),
                centerY + layerRadius * math.sin(angle)
            )
            draw_list:AddCircleFilled(center, radius * 0.1, color, 12)
        end
    end
end

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


Lua:
drawMagicCircle(window_center.x, window_center.y, 111)

Lua:
function drawMagicCircle(centerX, centerY, radius)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local mousePos = ImGui.GetMousePos()
    local distance = math.sqrt((mousePos.x - centerX)^2 + (mousePos.y - centerY)^2)
    local maxDistance = radius
    local distanceRatio = math.min(distance / maxDistance, 1)
    local color = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1 - distanceRatio, distanceRatio, 0, 1))

    -- Рисуем волшебный круг
    draw_list:AddCircleFilled(ImGui.ImVec2(centerX, centerY), radius, color, 24)

    -- Опционально: рисуем рамку вокруг круга
    draw_list:AddCircle(ImGui.ImVec2(centerX, centerY), radius, ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 0.5)), 24)
end


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

Lua:
drawRotatingCompass(window_center.x, window_center.y, 99)


Lua:
function drawRotatingCompass(centerX, centerY, radius)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local mousePos = ImGui.GetMousePos()
    local angleToMouse = math.atan2(mousePos.y - centerY, mousePos.x - centerX)
    local time = ImGui.GetTime()
    local pulsate = math.sin(time * 5) * 0.5 + 0.5

    -- Цвета
    local baseColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.1, 0.1, 0.1, 0.9)) -- Темный с полупрозрачностью
    local arrowColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.9, 0.3, 0.3, 1)) -- Ярко-красный
    local textColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)) -- Белый
    local outlineColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.7, 0.7, 0.7, 0.5)) -- Серый с полупрозрачностью

    -- Тень для текста
    local textShadowColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0, 0, 0, 0.5))

    -- Основа компаса
    draw_list:AddCircleFilled(ImGui.ImVec2(centerX, centerY), radius, baseColor, 24)
    draw_list:AddCircle(ImGui.ImVec2(centerX, centerY), radius, outlineColor, 24, 1.0) -- Обводка

    -- Стрелка компаса с пульсацией
    local arrowLength = radius * 0.8 * pulsate
    local arrowX = centerX + arrowLength * math.cos(angleToMouse)
    local arrowY = centerY + arrowLength * math.sin(angleToMouse)
    draw_list:AddLine(ImGui.ImVec2(centerX, centerY), ImGui.ImVec2(arrowX, arrowY), arrowColor, 2 + pulsate)
    draw_list:AddCircleFilled(ImGui.ImVec2(arrowX, arrowY), 5 + pulsate, arrowColor)

    -- Метки направлений
    local directions = {"N", "E", "S", "W"}
    for i, dir in ipairs(directions) do
        local angle = math.pi / 2 * (i - 1)
        local dirX = centerX + (radius + 15) * math.cos(angle)
        local dirY = centerY + (radius + 15) * math.sin(angle)
        -- Тень для текста
        draw_list:AddText(ImGui.ImVec2(dirX - ImGui.CalcTextSize(dir).x / 2 + 1, dirY - ImGui.CalcTextSize(dir).y / 2 + 1), textShadowColor, dir)
        draw_list:AddText(ImGui.ImVec2(dirX - ImGui.CalcTextSize(dir).x / 2, dirY - ImGui.CalcTextSize(dir).y / 2), textColor, dir)
    end

    -- Текстовое направление
    local directionText = string.format("Угол: %.2f°", math.deg(angleToMouse))
    -- Тень для текста
    draw_list:AddText(ImGui.ImVec2(centerX - ImGui.CalcTextSize(directionText).x / 2 + 1, centerY + radius + 30 + 1), textShadowColor, directionText)
    draw_list:AddText(ImGui.ImVec2(centerX - ImGui.CalcTextSize(directionText).x / 2, centerY + radius + 30), textColor, directionText)
end
Немного измененная версия уведомлений.
Рисуется на GetForegroundDrawList и можно указать hex цвет фона

Lua:
local notifications = {}

function addNotification(text, duration, backgroundColor)
    local function hexToRGB(hex)
        local r = tonumber(hex:sub(1, 2), 16) or 0
        local g = tonumber(hex:sub(3, 4), 16) or 0
        local b = tonumber(hex:sub(5, 6), 16) or 0
        return r / 255, g / 255, b / 255
    end
    local bR, bG, bB = hexToRGB(backgroundColor)
    
    table.insert(notifications, {
        text = text,
        color = {bR, bG, bB},
        duration = duration,
        alpha = 0, -- начальная прозрачность
        state = "appearing" -- начальное состояние
    })
end

function drawNotifications()
    local ImGui = imgui
    local draw_list = imgui.GetForegroundDrawList()
    local screen_width, screen_height = getScreenResolution()
    local notification_height = 50
    local notification_margin = 10
    local animation_speed = 0.02

    for i, notification in ipairs(notifications) do
        if notification.state == "appearing" then
            notification.alpha = notification.alpha + animation_speed
            if notification.alpha >= 1 then
                notification.alpha = 1
                notification.state = "displaying"
                notification.display_start = os.clock()
            end
        elseif notification.state == "displaying" then
            if os.clock() - notification.display_start >= notification.duration then
                notification.state = "disappearing"
            end
        elseif notification.state == "disappearing" then
            notification.alpha = notification.alpha - animation_speed
            if notification.alpha <= 0 then
                table.remove(notifications, i)
            end
        end

        local text_size = ImGui.CalcTextSize(notification.text)
        local notification_width = text_size.x + 20
        local x = (screen_width - notification_width) / 2
        local y = screen_height - (notification_height + notification_margin) * i

        draw_list:AddRectFilled(ImGui.ImVec2(x, y), ImGui.ImVec2(x + notification_width, y + notification_height), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(notification.color[1], notification.color[2], notification.color[3], notification.alpha)), 5)
        draw_list:AddText(ImGui.ImVec2(x + 10, y + (notification_height - text_size.y) / 2), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, notification.alpha)), notification.text)
    end
end