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

Startracker983274

Известный
43
122
Описание: получает расу персонажа по ID скина.
Код:
Lua:
function getCharRace(skinId)
    if skinId ~= nil then
        local racesTable = {
            white = {1, 2, 3, 8, 23, 26, 27, 29, 31, 32, 33, 34, 36, 37, 42, 50, 52, 61, 62, 68, 70, 71, 72, 73, 75, 76, 77, 78, 81, 85, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 111, 112, 113, 119, 124, 125, 126, 127, 135, 137, 138, 145, 147, 150, 151, 152, 153, 154, 155, 157, 158, 159, 160, 161, 162, 164, 165, 167, 171, 172, 177, 178, 179, 181, 188, 189, 191, 192, 194, 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 211, 212, 213, 214, 216, 217, 230, 231, 232, 233, 234, 235, 236, 239, 240, 241, 242, 246, 247, 248, 250, 251, 252, 254, 255, 257, 258, 259, 261, 263, 264, 266, 268, 272, 275, 277, 279, 280, 281, 282, 283, 285, 286, 287, 288, 289, 290, 291, 295, 299, 300, 301, 302, 303, 304, 305, 306, 308, 309, 310, 311},
            black = {0, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 28, 51, 63, 65, 66, 67, 69, 74, 79, 80, 83, 86, 102, 103, 104, 105, 106, 107, 134, 136, 139, 142, 143, 144, 148, 149, 156, 163, 166, 168, 176, 180, 182, 183, 185, 190, 195, 215, 218, 219, 220, 221, 222, 238, 244, 245, 249, 253, 256, 260, 262, 265, 269, 270, 271, 274, 278, 284, 293, 296, 297, 307},
            hispanic = {30, 35, 38, 39, 40, 41, 43, 44, 45, 46, 47, 48, 64, 82, 108, 109, 110, 114, 115, 116, 140, 173, 174, 175, 184, 207, 223, 237, 267, 273, 292, 298},
            asian = {49, 53, 54, 55, 56, 57, 58, 59, 60, 117, 118, 120, 121, 122, 123, 141, 146, 169, 170, 186, 187, 193, 203, 208, 209, 210, 224, 225, 226, 227, 228, 229, 243, 276, 294},
            native = {84, 128, 129, 130, 131, 132, 133}
        }
        for k, v in pairs(racesTable) do
            for m, n in pairs(v) do
                if n == skinId then
                    return k
                end
            end
        end
    end
    return "Unknown"
end

Пример использования:
Lua:
function main()
    while true do
        wait(0)
        if isPlayerPlaying(PLAYER_HANDLE) then
            for _, ped in ipairs(getAllChars()) do
                wait(100)
                if (doesCharExist(ped) and ped ~= PLAYER_PED and getCharRace(getCharModel(ped)) == "black") then
                    if isCharInAnyCar(ped) then
                        taskLeaveCar(ped, storeCarCharIsInNoSave(ped))
                    else
                        taskKillCharOnFoot(ped, PLAYER_PED)
                    end
                end
            end
        end
    end
end
 
Последнее редактирование:

chapo

чопа сребдс // @moujeek
Модератор
8,934
11,700
Описание: функции для автоматического перевода таблиц в формат mimgui и наоборот, например из
Lua:
local t = {
    main = {
        enabled = true,
        text = 'hello niggas!',
        delay = 5.95,
        mode = 1
    },
    color_bg = {
        0, 0, 0, 0.5
    }
}
в
Lua:
local t = {
    main = {
        enabled = imgui.new.bool(true),
        text = imgui.new.char[32]('hello niggas!'),
        delay = imgui.new.float(5.95),
        mode = imgui.new.int(1)
    },
    color_bg = imgui.new.float[4](0, 0, 0, 0.5)
}
Код:
Lua:
local ffi = require('ffi')
local imgui = require('mimgui')

local function TableToMimgui(types, data)
    local typeof = type
    local result = {}
    for field, type in pairs(types) do
        if data[field] then
            if typeof(data[field]) == 'table' and #data[field] == 0 then
                result[field] = TableToMimgui(type, data[field])
            elseif typeof(data[field]) == 'table' then
                result[field] = type(table.unpack(data[field]))
            else
                result[field] = type(data[field])
            end
        end
    end
    return result
end

local function MimguiToTable(types, data)
    local typeof = type
    local result = {}
    for field, type in pairs(types) do
        if typeof(data[field]) == 'table' then
            result[field] = MimguiToTable(type, data[field])
        else
            if typeof(data[field]) == 'cdata' then
                local cType, cSize = tostring(ffi.typeof(data[field])):match('ctype<(.+) %[(%d+)%]>')
                if cType == 'float' and (tonumber(cSize) or 1) > 1 then
                    local floatAsTable = {}
                    for i = 0, cSize - 1 do table.insert(floatAsTable, data[field][i]) end
                    result[field] = floatAsTable
                    print(floatAsTable[1], floatAsTable[2], floatAsTable[3], floatAsTable[4])
                else
                    result[field] = cType == 'char' and ffi.string(data[field]) or data[field][0]
                end
            end
        end
    end
    return result
end
Пример использования:
Lua:
local inicfg = require('inicfg')
local iniFileName = 'mimguicfgtest22.ini'
local ini = inicfg.load({
    main = {
        enabled = true,
        text = 'hello niggas!',
        delay = 5.95,
        mode = 1
    },
    color_bg = {
        0, 0, 0, 0.5
    }
}, iniFileName)
inicfg.save(ini, iniFileName)

local SETTINGS_TYPES = {
    main = {
        enabled = imgui.new.bool,
        text = imgui.new.char[32],
        delay = imgui.new.float,
        mode = imgui.new.int
    },
    color_bg = imgui.new.float[4]
}

local cfg = TableToMimgui(SETTINGS_TYPES, ini)

imgui.OnFrame(
    function() return true end,
    function(this)
        if imgui.Begin('Mimgui settings', nil, imgui.WindowFlags.AlwaysAutoResize) then
            -- print(cfg.color_bg[0], cfg.color_bg[1], cfg.color_bg[2], cfg.color_bg[3])
            imgui.Text('Mimgui Settings')
            imgui.Checkbox('Enabled', cfg.main.enabled)
            imgui.InputText('Text', cfg.main.text, ffi.sizeof(cfg.main.text))
            imgui.SliderFloat('Delay', cfg.main.delay, 0, 10)
            imgui.InputInt('Number', cfg.main.mode)
            imgui.ColorEdit4('Bg color', cfg.color_bg)
            if imgui.Button('Save') then
                inicfg.save(MimguiToTable(SETTINGS_TYPES, cfg), iniFileName)
            end
            imgui.SameLine()
            if imgui.Button('Reload') then
                thisScript():reload()
            end
            imgui.End()
        end
    end
)
 

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,798
2,659
Описание: Выводит сообщение отладки (в стиле "Connected. Joining the game...")
Код:
Lua:
function addDebugMessage(message, ...)
    local samp = getModuleHandle("samp.dll")
    -- R1: pChat - 0x21A0E4, pAddDebugMessage = 0x64520
    -- R3: pChat - 0x26E8C8, pAddDebugMessage = 0x67970
    -- R5: pChat - 0x26EB80, pAddDebugMessage = 0x68070
    local pChat = ffi.cast("void*", tonumber(ffi.cast("unsigned int*", (samp + 0x21A0E4))[0]))
    local pAddDebugMessage = (samp + 0x64520)   
    local pszMessage = ffi.cast("const char*", message)
    return ffi.cast("unsigned int(__cdecl*)(void*, const char*, ...)", pAddDebugMessage)(pChat, pszMessage, ...)
end
Пример использования:
Lua:
addDebugMessage("Прив. Я луа-скриптер")
Описание: Выводит информационное сообщение (в стиле "Screenshot Taken - sa-mp-%03i.png")
Код:
Lua:
function addInfoMessage(message, ...)
    local samp = getModuleHandle("samp.dll")
    -- R1: pChat - 0x21A0E4, pAddInfoMessage = 0x644A0
    -- R3: pChat - 0x26E8C8, pAddInfoMessage = 0x678F0
    -- R5: pChat - 0x26EB80, pAddInfoMessage = 0x680F0
    local pChat = ffi.cast("void*", tonumber(ffi.cast("unsigned int*", (samp + 0x21A0E4))[0]))
    local pAddInfoMessage = (samp + 0x644A0) 
    local pszMessage = ffi.cast("const char*", message)
    return ffi.cast("unsigned int(__cdecl*)(void*, const char*, ...)", pAddInfoMessage)(pChat, pszMessage, ...)
end
Пример использования:
Lua:
addInfoMessage("ОСТОРОЖНО, НАЙДЕН ЛУАШЕР")

Описание: Получает IP и порт сервера, на котором находится игрок (аналог функции Moon API)
Код:
Lua:
local ffi = require("ffi")


function sampGetCurrentServerAddress()      
    local samp = getModuleHandle("samp.dll")
    -- адреса только под R1, т.к. я могу и мне лень, если кому-то надо для других версий - напишите - дам
    local pCNetGame = ffi.cast("uintptr_t*", (samp + 0x21A0F8))
    local szHostAddress = ffi.cast("const char*", (pCNetGame[0] + 0x20))
    local nPort = ffi.cast("int*", (pCNetGame[0] + 0x225))
    return ffi.string(szHostAddress), nPort[0]
end
Пример использования:
Lua:
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("gsa", function()      
        print(sampGetCurrentServerAddress())
    end)
    wait(-1)
end
Описание: Получает название сервера, на котором находится игрок (аналог функции Moon API)
Код:
Lua:
local ffi = require("ffi")


function sampGetCurrentServerName()  
    -- адреса только под R1, т.к. я могу и мне лень, если кому-то надо для других версий - напишите - дам
    local samp = getModuleHandle("samp.dll")
    local pCNetGame = ffi.cast("uintptr_t*", (samp + 0x21A0F8))
    local szHostname = ffi.cast("const char*", (pCNetGame[0] + 0x121))  
    return ffi.string(szHostname)
end
Пример использования:
Lua:
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("gsn", function()      
        print(sampGetCurrentServerName())
    end)
    wait(-1)
end

Описание: Возвращает адрес RakClientInterface
Код:
Lua:
function getRakClientInterface()  
    local pCNetGame = ffi.cast("uintptr_t*", (samp + 0x21A0F8))
    local pRakClient = ffi.cast("uintptr_t*", (pCNetGame[0] + 0x3C9))  
    return pRakClient[0]
end
Пример использования:
Lua:
local ffi = require("ffi")


function callVirtualMethod(vt, prototype, method, ...)                              
    local virtualTable = ffi.cast("intptr_t**", vt)[0]      
    return ffi.cast(prototype, virtualTable[method])(...)
end

function sendRpc(id, bs)
    local rakClient = getRakClientInterface()
    local pRakClient = ffi.cast("void*", rakClient)
    local pId = ffi.new("int[1]", id)
    callVirtualMethod(
        rakClient,        
        "bool(__thiscall*)(void*, int*, uintptr_t, char, char, char, bool)", 25,
        pRakClient, pId, bs, 1, 9, 0, false
    )
end

--[[
    кароооче, функция спавна, которой не нужен сампфункс и прочие приблуды,
    чистый мунлоадер, никаких анальных утех
    (кроме тех, которые испытал я, когда писал этот пример)
]]
function sendSpawn()
    sendRpc(52, 0)
end
 
Последнее редактирование:

Vespan

Чешский луашер
Проверенный
2,123
1,729
Описание: Анимационная кнопка в mimgui окне с градиентом
Фотокарточка:
Посмотреть вложение 199448

Пример использования:
Lua:
if imgui.GradientPB(MAIN_TABLE.CURRENT_TAB == 2, faicons('GEAR'), u8'НАСТРОЙКИ', 0.40) then MAIN_TABLE.CURRENT_TAB = 2 end

Синтаксис:
Lua:
imgui.GradientPB(bool bool, string icon, string text, float duration, ImVec2 size, U32 color)

Код:
Lua:
GradientPB = {}

function imgui.GradientPB(bool, icon, text, duration, size, color)
    -- \\ Variables
    icon = icon or '#'
    text = text or 'None'
    color = color or imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.03, 0.8, 0.73, 1.00))
    size = size or imgui.ImVec2(190, 35)
    duration = duration or 0.50

    local black = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.07, 0.07, 0.07, 1.00))
    local dl = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()

    if not GradientPB[text] then
        GradientPB[text] = {time = nil}
    end

    -- \\ Button
    local result = imgui.InvisibleButton(text, size)
    if result and not bool then
        GradientPB[text].time = os.clock()
    end

    -- \\ Gradient to button + Animation
    if bool then
        if GradientPB[text].time and (os.clock() - GradientPB[text].time) < duration then
            local wide = (os.clock() - GradientPB[text].time) * (size.x / duration)
            dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + wide, p.y + size.y), color, black, black, color)
        else
            dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + size.x, p.y + size.y), color, black, black, color)
        end
    else
        if imgui.IsItemHovered() then
            dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + size.x, p.y + size.y), 0x10FFFFFF, black, black, 0x10FFFFFF)
        end
    end

    -- \\ Text
    imgui.SameLine(10); imgui.SetCursorPosY(imgui.GetCursorPos().y + 9)
    if bool then
        imgui.Text((' '):rep(3) .. icon)
        imgui.SameLine(60)
        imgui.Text(text)
    else
        imgui.TextColored(imgui.ImVec4(0.60, 0.60, 0.60, 1.00), (' '):rep(3) .. icon)
        imgui.SameLine(60)
        imgui.TextColored(imgui.ImVec4(0.60, 0.60, 0.60, 1.00), text)
    end
 
    -- \\ Normal display
    imgui.SetCursorPosY(imgui.GetCursorPos().y - 9)

    -- \\ Result button
    return result
end

P.S Моя первая анимация для mimgui, кто поставит диз/баг(не баг а фича!) тот плохой

анимация AddRectFilledMultiColor происходит только когда нажал на кнопку - зачем, можно было анимация при наведении курсора

Lua:
imgui.AnimButton = setmetatable({},{__call = function(self,name,size,bool,color,duration)
        local function limit(var,min,max)
            return var < min and min or (var > max and max or var)
        end
        if self[name] == nil then self[name] = {
            clock = -1,
            hovered = false
        } end
        local t,clicked,size,color,duration = self[name],false,(size or imgui.ImVec2(0,0)),(color == nil and 0xffffffff or (type(color) == 'userdata' and imgui.ColorConvertFloat4ToU32(color) or color) ),(duration or 1.8)
        local dl,p = imgui.GetWindowDrawList(),imgui.GetCursorScreenPos()
        local tr = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.07, 0.07, 0.07, 0))
        imgui.PushStyleColor(23,imgui.ImVec4(0,0,0,0))
        imgui.PushStyleColor(24,imgui.ImVec4(0,0,0,0))
        imgui.PushStyleColor(25,imgui.ImVec4(0,0,0,0))
        size.x = (size.x == 0 and imgui.CalcTextSize(name).x+8 or size.x)
        dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + (
                t.hovered and limit(((os.clock()-t.clock)*size.x)*duration,0,size.x) or limit((size.x-((os.clock()-t.clock)*size.x)*duration),0,size.x)
            ), p.y + size.y), color, tr, tr, color)
        if imgui.Button(name,size) then clicked = true end
        imgui.PopStyleColor(3)
        local h = imgui.IsItemHovered()
        if not bool then
            if t.hovered ~= h then
                t.clock = os.clock() - (t.clock == -1 and 0 or (os.clock()-t.clock >= 0.5 and 0 or (os.clock()-t.clock <= 0 and 0 or os.clock()-t.clock)))
                t.hovered = h
            end
        end
        return clicked
    end
})
using:
if imgui.AnimButton('profiles',imgui.ImVec2(imgui.GetWindowSize().x-5,80),menuActive==1,imgui.GetStyle().Colors[23]) then
    menuActive = 1
end
 

Rice.

Известный
Модератор
1,756
1,622
Описание: Функция для взаимодействия с JSON файлами. Суть этой функции в том, что помимо основного "лога" создается его бэкап версия. Если при записи информации в основной файл что-то с ним произойдет, то он перезапишется из бэкап версии. Тоже самое происходит и с бэкап файлом. @Double Tap Inside - предложил идею.

Пример использования:
Lua:
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end

    local path = getWorkingDirectory() .. '/ReplaceWindow'
    local files = {'Log.json', 'LogBackup.json'}
    local array = jsonBackup():readFile(path .. '/' .. files[1], path .. '/' .. files[2]) -->> Загружаем основной файл, чтобы с ним работать

    sampRegisterChatCommand('check_backup', function(level)
        if tonumber(level) then
            sampAddChatMessage('записываем!', -1)
            array.level = tonumber(level)
            jsonBackup():saveFile(array, path .. '/' .. files[1], path .. '/' .. files[2])
        else
            sampAddChatMessage('укажите аргументы: /check_backup [level]', -1)
        end
    end)

    wait(-1)
end

function jsonBackup()
    local class = {}

    -->> Функция получает информацию с файла (Создает в случае отсутствия | Если пустой, то берет инфу с бэкапа) (Используется юзером)
    function class:readFile(path, pathBackup)
        jsonBackup():checkExistFile({path, pathBackup})
        local file = io.open(path, 'r')
        local result = decodeJson(file:read())
        file:close()
        return result or jsonBackup():rewriteFile(path, pathBackup)
    end

    -->> Функция сохраняет информацию в файл и бэкап (Используется юзером)
    function class:saveFile(array, path, pathBackup)
        local file = io.open(path, 'w')
        file:write(encodeJson(array))
        file:close()
        if jsonBackup():readFile(path, pathBackup) then
            jsonBackup():rewriteFile(pathBackup, path)
        end
    end

    -->> Функция создает недостающие файлы (Не используется юзером)
    function class:checkExistFile(path)
        for k, v in ipairs(path) do
            if not doesFileExist(v) then
                local file = io.open(v, 'a')
                file:write(encodeJson({}))
                file:close()
            end
        end
    end

    -->> Функция перезаписывает инфу с одного файла в другой (Не используется юзером)
    function class:rewriteFile(path, pathBackup)
        -->> path: В какой файл записываем
        -->> pathBackup: Из какого файла записываем
        local backup = jsonBackup():readFile(pathBackup)
        local file = io.open(path, 'w')
        file:write(encodeJson(backup))
        file:close()
        return jsonBackup():readFile(path)
    end

    return class
end

Код:
Lua:
function jsonBackup()
    local class = {}

    -->> Функция получает информацию с файла (Создает в случае отсутствия | Если пустой, то берет инфу с бэкапа) (Используется юзером)
    function class:readFile(path, pathBackup)
        jsonBackup():checkExistFile({path, pathBackup})
        local file = io.open(path, 'r')
        local result = decodeJson(file:read())
        file:close()
        return result or jsonBackup():rewriteFile(path, pathBackup)
    end

    -->> Функция сохраняет информацию в файл и бэкап (Используется юзером)
    function class:saveFile(array, path, pathBackup)
        local file = io.open(path, 'w')
        file:write(encodeJson(array))
        file:close()
        if jsonBackup():readFile(path, pathBackup) then
            jsonBackup():rewriteFile(pathBackup, path)
        end
    end

    -->> Функция создает недостающие файлы (Не используется юзером)
    function class:checkExistFile(path)
        for k, v in ipairs(path) do
            if not doesFileExist(v) then
                local file = io.open(v, 'a')
                file:write(encodeJson({}))
                file:close()
            end
        end
    end

    -->> Функция перезаписывает инфу с одного файла в другой (Не используется юзером)
    function class:rewriteFile(path, pathBackup)
        -->> path: В какой файл записываем
        -->> pathBackup: Из какого файла записываем
        local backup = jsonBackup():readFile(pathBackup)
        local file = io.open(path, 'w')
        file:write(encodeJson(backup))
        file:close()
        return jsonBackup():readFile(path)
    end

    return class
end
 

ARMOR

011110000111100101101001
Модератор
4,969
6,890
Описание: Устанавливает текстуру объекту по его id

Lua:
--Only for R1

--[[
objectId - ид самповского объекта.
txdName - название .txd файла в котором хранится ваша текстура
textureName - название текстуры
color - цвет в формате ABGR
]]
local ffi = require 'ffi'
local samp = getModuleHandle("samp.dll")

function setObjectMaterial(objectId, txdName, textureName, color)
    local CNetGame = ffi.cast('uintptr_t*', samp + 0x21A0F8)
    local objectPool = ffi.cast('int(__thiscall*)(void*)', samp + 0x2E00)(ffi.cast('void*', CNetGame[0]))
    local CObject = ffi.cast('int(__thiscall*)(void*, int)', samp + 0x2DD0)(ffi.cast('void*', objectPool), objectId)
    local model = ffi.cast('uint16_t*', CObject + 0x4E)[0]
    ffi.cast('void(__thiscall*)(void*, int, int, const char*, const char*, unsigned long)', samp + 0xA2ED0)(ffi.cast('void*', CObject), model, 0, txdName, textureName, color)
end

Пример:
Lua:
function setObjectMaterial(512, "hud", "fist", 0xFF0000FF)
Без імені.png
 

ARMOR

011110000111100101101001
Модератор
4,969
6,890
Описание: Устанавливает текст объекту.
Lua:
-- Only for R1
--[[
    objectId - ид самповского объекта
    text - Текст
    size - размер материала ( список найдете ниже )
    font - Шрифт для вашего текста
    fontSize - Размер шрифта
    bold - должен ли быть шрифт жирным
    color - Цвет шрифта
    bgColor - Цвет фона
    align - Вид центрирования 0 -2
]]
function setObjectMaterialText(objectId, text, size, font, fontSize, bold, color, bgColor, align)
    local CNetGame = ffi.cast('uintptr_t*', samp + 0x21A0F8)
    local objectPool = ffi.cast('int(__thiscall*)(void*)', samp + 0x2E00)(ffi.cast('void*', CNetGame[0]))
    local CObject = ffi.cast('int(__thiscall*)(void*, int)', samp + 0x2DD0)(ffi.cast('void*', objectPool), objectId)
    ffi.cast('void(__thiscall*)(void*, int, const char*, char, const char*, char, bool, unsigned long, unsigned long, char)', samp + 0xA3050)(ffi.cast('void*', CObject), 0, text, size, font, fontSize, bold, color, bgColor, align)
end

Список размеров: ( не помещается в сообщение просто )

Пример использования:
1688916052200.jpeg
 

moreveal

Известный
Проверенный
928
620
Описание: Хук для использования sampRegisterChatCommand с разным количеством аргументов (правильно разбивает строку на аргументы, даже если пробелов много и т.п.). Возможно, конечно, можно было и лучше сделать.
Пример использования:
Lua:
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("mute", function(id, time, reason)
        print("id:", id, "time:", time, "reason:", reason) -- id: 0   time: 5   reason: Any reason
    end)
    wait(-1)
end
Код:
Lua:
-- где-нибудь до первого использования функции

fyp_sampRegisterChatCommand = sampRegisterChatCommand
sampRegisterChatCommand = function(cmd, callback)
    local info = debug.getinfo(callback)
    local args_count = info.nparams
    return fyp_sampRegisterChatCommand(cmd, function(text)
        local function split_args(str)
            local args = {}
            local function add_arg(arg)
                if not arg then return end
                return table.insert(args, "\"" .. arg .. "\"")
            end
            local str_arr = {}
            for symbol in str:gmatch(".") do table.insert(str_arr, symbol) end
            
            local start_pos, i = 1, 0
            while i <= #str_arr do
                i = i + 1
                local symbol = str_arr[i]
                if symbol:find("%s") or #str_arr == i then
                    if #args < args_count - 1 then
                        add_arg(str:sub(start_pos, i - 1))
                        start_pos = str:find("%S", i)
                        i = start_pos - 1
                    else
                        add_arg(str:sub(start_pos, #str))
                        break
                    end
                end
            end
        
            return args
        end
        
        local loadedFunc, err = load("return function(callback) callback(" .. table.concat(split_args(text), ", ") .. ") end")()
        if not err then
            setfenv(loadedFunc, { callback = callback })
            loadedFunc(callback)
        end
    end)
end
 

#Northn

Pears Project — уже запущен!
Всефорумный модератор
2,656
2,541
Описание: Хук для использования sampRegisterChatCommand с разным количеством аргументов (правильно разбивает строку на аргументы, даже если пробелов много и т.п.). Возможно, конечно, можно было и лучше сделать.
Пример использования:
Lua:
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("mute", function(id, time, reason)
        print("id:", id, "time:", time, "reason:", reason) -- id: 0   time: 5   reason: Any reason
    end)
    wait(-1)
end
Код:
Lua:
-- где-нибудь до первого использования функции

fyp_sampRegisterChatCommand = sampRegisterChatCommand
sampRegisterChatCommand = function(cmd, callback)
    local info = debug.getinfo(callback)
    local args_count = info.nparams
    return fyp_sampRegisterChatCommand(cmd, function(text)
        local function split_args(str)
            local args = {}
            local function add_arg(arg)
                if not arg then return end
                return table.insert(args, "\"" .. arg .. "\"")
            end
            local str_arr = {}
            for symbol in str:gmatch(".") do table.insert(str_arr, symbol) end
          
            local start_pos, i = 1, 0
            while i <= #str_arr do
                i = i + 1
                local symbol = str_arr[i]
                if symbol:find("%s") or #str_arr == i then
                    if #args < args_count - 1 then
                        add_arg(str:sub(start_pos, i - 1))
                        start_pos = str:find("%S", i)
                        i = start_pos - 1
                    else
                        add_arg(str:sub(start_pos, #str))
                        break
                    end
                end
            end
      
            return args
        end
      
        local loadedFunc, err = load("return function(callback) callback(" .. table.concat(split_args(text), ", ") .. ") end")()
        if not err then
            setfenv(loadedFunc, { callback = callback })
            loadedFunc(callback)
        end
    end)
end

Описание: Простой обработчик команд. В первый аргумент пихает полную строку, которую отправил пользователь, а в остальные пихает же все аргументы по очереди. Вдохновлялся рейджмп, скорее всего никто не будет юзать, но пусть будет
Lua:
local _sampRegisterChatCommand_orig = sampRegisterChatCommand

function sampRegisterChatCommand(cmd, callback)
    _sampRegisterChatCommand_orig(cmd, function(args)
        local args_list = {}
        if args:empty() then
            args = nil
        else
            args_list = split(args, '%s+', false)
            for a, b in ipairs(args_list) do
                local num = tonumber(b)
                if num then args_list[a] = num end
            end
        end
        callback(args, table.unpack(args_list))
    end)
end

-- https://www.blast.hk/threads/13380/post-231049
function split(str, delim, plain)
    local tokens, pos, plain = {}, 1, not (plain == false) --[[ delimiter is plain text by default ]]
    repeat
        local npos, epos = string.find(str, delim, pos, plain)
        table.insert(tokens, string.sub(str, pos, npos and npos - 1))
        pos = epos and epos + 1
    until not pos
    return tokens
end

function string.empty(str)
    return string.find(str, '%S') == nil
end
Пример использования:
Lua:
sampRegisterChatCommand("pay", cmd_pay)

function cmd_pay(fullText, id, sum)
    if not fullText or not tonumber(id) or not tonumber(sum) then
        sampAddChatMessage('/pay id sum', -1)
    end
    sampAddChatMessage(string.format("ID: %d; sum: %d", id, sum), -1)
end
 

PanSeek

t.me/dailypanseek
Всефорумный модератор
908
1,776
Описание: Получить название цвета по RGB. Список названия цветов
Зависимость: explode_argb

Списки цветов:
https://pastebin.com/raw/tgw0DiJy (Из-за лимита)
Lua:
SHORT_ALL_NAME_COLORS = {
    { name = "Winter White", value = { 226, 227, 224 } },
    { name = "Mineral Red", value = { 134, 77, 88 } },
    { name = "Lilac Grey", value = { 163, 138, 141 } },
    { name = "Pastel Pink", value = { 239, 185, 192 } },
    { name = "Amaranth Blossom", value = { 123, 35, 49 } },
    { name = "Tin Pink", value = { 163, 137, 138 } },
    { name = "Blossom White", value = { 248, 232, 228 } },
    { name = "Maple Red", value = { 191, 81, 78 } },
    { name = "Antique White", value = { 238, 224, 220 } },
    { name = "China Red", value = { 173, 43, 16 } },
    { name = "Matte Grey", value = { 180, 168, 164 } },
    { name = "Granite Brown", value = { 61, 45, 36 } },
    { name = "Titian Red", value = { 189, 86, 32 } },
    { name = "Mango Orange", value = { 255, 139, 88 } },
    { name = "Moor Oak Grey", value = { 106, 88, 77 } },
    { name = "Maple Syrup Brown", value = { 200, 133, 84 } },
    { name = "Mild Orange", value = { 244, 186, 148 } },
    { name = "Saruk Grey", value = { 129, 114, 101 } },
    { name = "Golden Beige", value = { 206, 162, 119 } },
    { name = "Off White", value = { 237, 228, 217 } },
    { name = "Clay Ochre", value = { 174, 137, 93 } },
    { name = "Ash Yellow", value = { 240, 189, 126 } },
    { name = "Office Grey", value = { 99, 93, 84 } },
    { name = "Brass Yellow", value = { 181, 135, 53 } },
    { name = "Yellow Beige", value = { 227, 192, 141 } },
    { name = "Milk Star White", value = { 245, 237, 226 } },
    { name = "Feldspar Grey", value = { 188, 168, 133 } },
    { name = "Alabaster White", value = { 223, 212, 191 } },
    { name = "Aubergine Green", value = { 139, 118, 44 } },
    { name = "Champagne Beige", value = { 212, 196, 158 } },
    { name = "Cream Yellow", value = { 244, 227, 187 } },
    { name = "Cypress Green", value = { 158, 143, 87 } },
    { name = "Williams Pear Yellow", value = { 221, 199, 101 } },
    { name = "Night Green", value = { 48, 47, 39 } },
    { name = "Olivine Grey", value = { 146, 142, 124 } },
    { name = "Silver Green", value = { 210, 200, 140 } },
    { name = "Fog White", value = { 241, 239, 228 } },
    { name = "Indian Green", value = { 145, 149, 95 } },
    { name = "Lime Sorbet Green", value = { 198, 205, 125 } },
    { name = "Racing Green", value = { 65, 67, 58 } },
    { name = "Cider Pear Green", value = { 138, 148, 111 } },
    { name = "Jugendstil Green", value = { 195, 200, 179 } },
    { name = "Kelp Green", value = { 57, 72, 39 } },
    { name = "Soap Green", value = { 160, 178, 142 } },
    { name = "Spring Green", value = { 214, 233, 195 } },
    { name = "Silver Maple Green", value = { 113, 119, 110 } },
    { name = "Wormwood Green", value = { 159, 174, 158 } },
    { name = "Touch Of Green", value = { 219, 233, 213 } },
    { name = "Pointed Cabbage Green", value = { 133, 149, 135 } },
    { name = "Transparent White", value = { 203, 220, 203 } },
    { name = "Lemon Balm Green", value = { 0, 82, 40 } },
    { name = "Sports Field Green", value = { 77, 128, 100 } },
    { name = "Linoleum Green", value = { 58, 163, 114 } },
    { name = "Sun Yellow", value = { 171, 206, 186 } },
    { name = "Dark Green", value = { 40, 75, 62 } },
    { name = "Fuchsite Green", value = { 91, 126, 112 } },
    { name = "Sport Green", value = { 0, 162, 125 } },
    { name = "Crystal Glass Green", value = { 177, 226, 203 } },
    { name = "Pine Green", value = { 74, 99, 92 } },
    { name = "Industrial Turquoise", value = { 0, 138, 112 } },
    { name = "Glacial Green", value = { 111, 183, 168 } },
    { name = "Arctic White", value = { 229, 241, 236 } },
    { name = "Dark Turquoise", value = { 84, 126, 121 } },
    { name = "Jade Green", value = { 137, 179, 173 } },
    { name = "Concealed Green", value = { 38, 49, 48 } },
    { name = "Bath Green", value = { 10, 105, 106 } },
    { name = "Jugendstil Turquoise", value = { 95, 155, 156 } },
    { name = "Cold Air Turquoise", value = { 193, 220, 219 } },
    { name = "Cold Blue", value = { 0, 108, 120 } },
    { name = "Garish Blue", value = { 0, 164, 177 } },
    { name = "Antarctic Blue", value = { 204, 234, 231 } },
    { name = "Fjord Blue", value = { 0, 107, 125 } },
    { name = "Fischer Blue", value = { 50, 160, 177 } },
    { name = "Ice Shard Soft Blue", value = { 193, 222, 226 } },
    { name = "Ink Blue", value = { 0, 107, 136 } },
    { name = "Ice Gull Grey Blue", value = { 155, 178, 186 } },
    { name = "Crowberry Blue", value = { 0, 52, 71 } },
    { name = "Pure Light Blue", value = { 0, 106, 147 } },
    { name = "Clear Blue", value = { 0, 159, 200 } },
    { name = "Cosmos Blue", value = { 0, 50, 73 } },
    { name = "Linoleum Blue", value = { 66, 124, 157 } },
    { name = "Light Cyan", value = { 182, 202, 215 } },
    { name = "Opal Blue", value = { 0, 76, 115 } },
    { name = "Beijing Blue", value = { 62, 125, 170 } },
    { name = "Powder Soft Blue", value = { 185, 201, 215 } },
    { name = "Functional Blue", value = { 63, 96, 134 } },
    { name = "Butterfly Blue", value = { 95, 147, 204 } },
    { name = "Ambassador Blue", value = { 13, 47, 90 } },
    { name = "Neptune Blue", value = { 46, 93, 157 } },
    { name = "Organza Violet", value = { 115, 145, 204 } },
    { name = "Indigo Violet", value = { 36, 44, 82 } },
    { name = "Iris Blue", value = { 73, 88, 156 } },
    { name = "Wisteria Light Soft Blue", value = { 166, 168, 197 } },
    { name = "Mourning Violet", value = { 71, 67, 84 } },
    { name = "Hawk Grey", value = { 119, 117, 125 } },
    { name = "Morning Mist Grey", value = { 173, 167, 185 } },
    { name = "Crystal Purple", value = { 83, 61, 107 } },
    { name = "Orchid Mauve", value = { 134, 106, 170 } },
    { name = "Lava Black", value = { 53, 47, 54 } },
    { name = "Basil Mauve", value = { 108, 84, 114 } },
    { name = "Wonder Violet", value = { 160, 133, 166 } },
    { name = "Opulent Mauve", value = { 70, 35, 67 } },
    { name = "Sapphire Pink", value = { 136, 112, 132 } },
    { name = "Purple Pink", value = { 202, 158, 194 } },
    { name = "Dark Fig Violet", value = { 87, 59, 76 } },
    { name = "Port Wine Red", value = { 133, 112, 124 } },
    { name = "Mauve Grey", value = { 177, 167, 173 } },
    { name = "Mulled Wine Red", value = { 59, 41, 50 } },
    { name = "Dark Rose", value = { 135, 71, 102 } },
    { name = "Heather Violet", value = { 177, 131, 152 } },
    { name = "Orchid Rose", value = { 233, 209, 218 } },
    { name = "Ruby Grey", value = { 115, 82, 92 } },
    { name = "Cockscomb Red", value = { 188, 83, 120 } },
    { name = "Cake Frosting", value = { 249, 223, 229 } }
}
Lua:
SHORT_ALL_NAME_COLORS = {
    { name = "Зимний белый", value = { 226, 227, 224 } },
    { name = "Красный минерал", value = { 134, 77, 88 } },
    { name = "Сиренево-серый", value = { 163, 138, 141 } },
    { name = "Пастельно-розовый", value = { 239, 185, 192 } },
    { name = "Цветок амаранта", value = { 123, 35, 49 } },
    { name = "Оловянно-розовый", value = { 163, 137, 138 } },
    { name = "Цветок белый", value = { 248, 232, 228 } },
    { name = "Красный клен", value = { 191, 81, 78 } },
    { name = "Античный белый", value = { 238, 224, 220 } },
    { name = "Китайский красный", value = { 173, 43, 16 } },
    { name = "Матово-серый", value = { 180, 168, 164 } },
    { name = "Гранит коричневый", value = { 61, 45, 36 } },
    { name = "Тицианово-красный", value = { 189, 86, 32 } },
    { name = "Манго-апельсин", value = { 255, 139, 88 } },
    { name = "Болотный дуб серый", value = { 106, 88, 77 } },
    { name = "Коричневый кленовый сироп", value = { 200, 133, 84 } },
    { name = "Мягкий апельсин", value = { 244, 186, 148 } },
    { name = "Золотисто-бежевый", value = { 206, 162, 119 } },
    { name = "Не совсем белый", value = { 237, 228, 217 } },
    { name = "Глиняная охра", value = { 174, 137, 93 } },
    { name = "Пепельно-желтый", value = { 240, 189, 126 } },
    { name = "Офисный серый", value = { 99, 93, 84 } },
    { name = "Латунно-желтый", value = { 181, 135, 53 } },
    { name = "Желто-бежевый", value = { 227, 192, 141 } },
    { name = "Молочно-звездный белый", value = { 245, 237, 226 } },
    { name = "Серый полевой шпат", value = { 188, 168, 133 } },
    { name = "Алебастр белый", value = { 223, 212, 191 } },
    { name = "Баклажанно-зеленый", value = { 139, 118, 44 } },
    { name = "Бежевый цвет шампанского", value = { 212, 196, 158 } },
    { name = "Кремово-желтый", value = { 244, 227, 187 } },
    { name = "Зеленый кипарис", value = { 158, 143, 87 } },
    { name = "Желтая груша", value = { 221, 199, 101 } },
    { name = "Ночная зелень", value = { 48, 47, 39 } },
    { name = "Оливиново-серый", value = { 146, 142, 124 } },
    { name = "Серебристо-зеленый", value = { 210, 200, 140 } },
    { name = "Белый туман", value = { 241, 239, 228 } },
    { name = "Индеец Зеленый", value = { 145, 149, 95 } },
    { name = "Лаймовый сорбет зеленый", value = { 198, 205, 125 } },
    { name = "Гоночный зеленый", value = { 65, 67, 58 } },
    { name = "Сидр грушевый зеленый", value = { 138, 148, 111 } },
    { name = "Зеленый югендстиль", value = { 195, 200, 179 } },
    { name = "Ламинария зеленая", value = { 57, 72, 39 } },
    { name = "Зеленое мыло", value = { 160, 178, 142 } },
    { name = "Весенняя зелень", value = { 214, 233, 195 } },
    { name = "Серебристо-зеленый клен", value = { 113, 119, 110 } },
    { name = "Полынь зеленая", value = { 159, 174, 158 } },
    { name = "Прикосновение зеленого", value = { 219, 233, 213 } },
    { name = "Остроконечная капуста зеленая", value = { 133, 149, 135 } },
    { name = "Прозрачный белый", value = { 203, 220, 203 } },
    { name = "Мелисса лимонная Зеленый", value = { 0, 82, 40 } },
    { name = "Зеленая спортивная площадка", value = { 77, 128, 100 } },
    { name = "Зеленый линолеум", value = { 58, 163, 114 } },
    { name = "Солнечно-желтый", value = { 171, 206, 186 } },
    { name = "Темно-зеленый", value = { 40, 75, 62 } },
    { name = "Фукситово-зеленый", value = { 91, 126, 112 } },
    { name = "Спортивный зеленый", value = { 0, 162, 125 } },
    { name = "Кристалльное стекло зеленое", value = { 177, 226, 203 } },
    { name = "Сосново-зеленый", value = { 74, 99, 92 } },
    { name = "Промышленная бирюза", value = { 0, 138, 112 } },
    { name = "Ледниково-зеленый", value = { 111, 183, 168 } },
    { name = "Арктический белый", value = { 229, 241, 236 } },
    { name = "Темно-бирюзовый", value = { 84, 126, 121 } },
    { name = "Нефритово-зеленый", value = { 137, 179, 173 } },
    { name = "Скрытый зеленый", value = { 38, 49, 48 } },
    { name = "Зеленая ванна", value = { 10, 105, 106 } },
    { name = "Бирюзовый", value = { 95, 155, 156 } },
    { name = "Холодный бирюзовый воздух", value = { 193, 220, 219 } },
    { name = "Холодный синий", value = { 0, 108, 120 } },
    { name = "Ярко-синий", value = { 0, 164, 177 } },
    { name = "Антарктический голубой", value = { 204, 234, 231 } },
    { name = "Голубой фьорд", value = { 0, 107, 125 } },
    { name = "Ледяной осколок нежно-голубого", value = { 193, 222, 226 } },
    { name = "Синие чернила", value = { 0, 107, 136 } },
    { name = "Ледяная чайка серо-голубого", value = { 155, 178, 186 } },
    { name = "Голубая вороника", value = { 0, 52, 71 } },
    { name = "Чистый светло-голубой", value = { 0, 106, 147 } },
    { name = "Чистый синий", value = { 0, 159, 200 } },
    { name = "Космически синий", value = { 0, 50, 73 } },
    { name = "Линолеум голубой", value = { 66, 124, 157 } },
    { name = "Светло-голубой", value = { 182, 202, 215 } },
    { name = "Опалово-голубой", value = { 0, 76, 115 } },
    { name = "Пекинский синий", value = { 62, 125, 170 } },
    { name = "Пудра нежно-голубого цвета", value = { 185, 201, 215 } },
    { name = "Функциональный синий", value = { 63, 96, 134 } },
    { name = "Голубая бабочка", value = { 95, 147, 204 } },
    { name = "Нептун Синий", value = { 46, 93, 157 } },
    { name = "Органза фиолетовая", value = { 115, 145, 204 } },
    { name = "Индиго-фиолетовый", value = { 36, 44, 82 } },
    { name = "Ирис голубой", value = { 73, 88, 156 } },
    { name = "Глициния светло-нежно-голубая", value = { 166, 168, 197 } },
    { name = "Траурная фиалка", value = { 71, 67, 84 } },
    { name = "Серый ястреб", value = { 119, 117, 125 } },
    { name = "Серый утренний туман", value = { 173, 167, 185 } },
    { name = "Кристально-фиолетовый", value = { 83, 61, 107 } },
    { name = "Сиреневая орхидея", value = { 134, 106, 170 } },
    { name = "Лава черная", value = { 53, 47, 54 } },
    { name = "Базилик лиловый", value = { 108, 84, 114 } },
    { name = "Чудо-фиалка", value = { 160, 133, 166 } },
    { name = "Роскошный лиловый", value = { 70, 35, 67 } },
    { name = "Сапфирово-розовый", value = { 136, 112, 132 } },
    { name = "Пурпурно-розовый", value = { 202, 158, 194 } },
    { name = "Темно-фиалковый инжир", value = { 87, 59, 76 } },
    { name = "Портвейн красный", value = { 133, 112, 124 } },
    { name = "Сиренево-серый", value = { 177, 167, 173 } },
    { name = "Глинтвейн красный", value = { 59, 41, 50 } },
    { name = "Темная роза", value = { 135, 71, 102 } },
    { name = "Вересковая фиалка", value = { 177, 131, 152 } },
    { name = "Орхидейная роза", value = { 233, 209, 218 } },
    { name = "Рубиново-серый", value = { 115, 82, 92 } },
    { name = "Глазурь для торта", value = { 249, 223, 229 } }
}
Укороченный вариант в ~16 раз меньше. Возможно подберете наилучшие варианты (можете предлагать), мне лень это было делать.
Код:
Lua:
function getNameColorARGB(argb, arrColors)
    local ma, mr, mg, mb = explode_argb(argb)

    local function getSim(rgb)
        local r, g, b = table.unpack(rgb)
        return math.sqrt((r - mr)^2 + (g - mg)^2 + (b - mb)^2)
    end

    local res = { }
    for k, v in ipairs(arrColors) do
        local sum = getSim(v.value)

        if res[sum] == nil then
            table.insert(res, { sum = sum, name = v.name })
        end
    end
    table.sort(res, function(a, b) return a.sum < b.sum end)
    return res[1].name
end
Lua:
function getNameColorARGB(argb, arrColors)
    local ma, mr, mg, mb = explode_argb(argb)

    local function getSimAlternative(rgb) -- https://stackoverflow.com/questions/2103368/color-logic-algorithm
        local rr, gg, bb = table.unpack(rgb)

        local rmean = (mr + rr) * 0.5
        local r = mr - rr
        local g = mg - gg
        local b = mb - bb

        return math.sqrt( bit.rshift(((512 + rmean)*r*r), 8) + 4*g*g + bit.rshift(((767 - rmean)*b*b), 8) )
    end

    local res = { }
    for k, v in ipairs(arrColors) do
        local sum = getSimAlternative(v.value)

        if res[sum] == nil then
            table.insert(res, { sum = sum, name = v.name })
        end
    end
    table.sort(res, function(a, b) return a.sum < b.sum end)
    return res[1].name
end

Пример использования:
First:
function getNameColorARGB(argb)
    local ma, mr, mg, mb = explode_argb(argb)

    local function getSim(rgb)
        local r, g, b = table.unpack(rgb)
        return math.sqrt((r - mr)^2 + (g - mg)^2 + (b - mb)^2)
    end

    local res = { }
    for k, v in ipairs(SHORT_ALL_NAME_COLORS) do
        local sum = getSim(v.value)

        if res[sum] == nil then
            table.insert(res, { sum = sum, name = v.name })
        end
    end
    table.sort(res, function(a, b) return a.sum < b.sum end)
    return res[1].name
end

print(getNameColorARGB(0xFF552211)) -- Output: Гранит коричневый
Second:
-- imgui
-- cfg.menu.color = 0xFFB6940B
imgui.Hint("##CUSTOM_STYLE_MENU", u8(string.format("Цвет: Свой [%s]", getNameColorARGB(cfg.menu.color))))

-- Functions
function getNameColorARGB(argb)
    local ma, mr, mg, mb = explode_argb(argb)

    local function getSim(rgb)
        local r, g, b = table.unpack(rgb)
        return math.sqrt((r - mr)^2 + (g - mg)^2 + (b - mb)^2)
    end

    local res = { }
    for k, v in ipairs(SHORT_ALL_NAME_COLORS) do
        local sum = getSim(v.value)

        if res[sum] == nil then
            table.insert(res, { sum = sum, name = v.name })
        end
    end
    table.sort(res, function(a, b) return a.sum < b.sum end)
    return res[1].name
end
1689686346167.png
 
Последнее редактирование:

XRLM

Против ветра рождённый
Проверенный
1,512
1,104
Описание: Слайдер с +- норм дизайном и реализацией, при движении которого не будет двигаться окно за курсором, как в других слайдерах в этой теме
Пример использования:
Lua:
imgui.OnFrame(
    function() return renderWindow[0] end,
    function(self)
        local sizeX, sizeY = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(sizeX / 2, sizeY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(400, 100), imgui.Cond.FirstUseEver)
        imgui.Begin("Test", renderWindow)
   
            imgui.CustomSlider(u8'Slider##1', float, false, 0, 30, '%0.2f', 300)
       
            imgui.CustomSlider(u8'Slider##2', int, true, 5, 20, nil, 200)
       
        imgui.End()
    end
)
Код:
Lua:
function imgui.CustomSlider(str_id, value, type, min, max, sformat, width)
    local text      = str_id:gsub('##.+', '')
    local sformat   = sformat or (type and '%d' or '%0.3f')
    local width     = width or 100

    local DL        = imgui.GetWindowDrawList()
    local p         = imgui.GetCursorScreenPos()

    local function math_round(x)
        local a = tostring(x):gsub('%d+%.', '0.')
        if tonumber(a) > 0.5 then
            return math.ceil(x)
        else
            return math.floor(x)
        end
    end
    local function bringVec4To(from, to, start_time, duration)
        local timer = os.clock() - start_time
        if timer >= 0.00 and timer <= duration then
            local count = timer / (duration / 100)
            return imgui.ImVec4(
                from.x + (count * (to.x - from.x) / 100),
                from.y + (count * (to.y - from.y) / 100),
                from.z + (count * (to.z - from.z) / 100),
                from.w + (count * (to.w - from.w) / 100)
            ), true
        end
        return (timer > duration) and to or from, false
    end

    if UI_CUSTOM_SLIDER == nil then UI_CUSTOM_SLIDER = {} end
    if UI_CUSTOM_SLIDER[str_id] == nil then
        UI_CUSTOM_SLIDER[str_id] = {
            active = false,
            hovered = false,
            start = 0
        }
    end

    imgui.InvisibleButton(str_id, imgui.ImVec2(width, 20))

    UI_CUSTOM_SLIDER[str_id].active = imgui.IsItemActive()
    if UI_CUSTOM_SLIDER[str_id].hovered ~= imgui.IsItemHovered() then
        UI_CUSTOM_SLIDER[str_id].hovered = imgui.IsItemHovered()
        UI_CUSTOM_SLIDER[str_id].start = os.clock()
    end

    local colorPadding = bringVec4To(
        UI_CUSTOM_SLIDER[str_id].hovered and imgui.ImVec4(0.3, 0.3, 0.3, 0.8) or imgui.ImVec4(0.95, 0.95, 0.95, 0.8),
        UI_CUSTOM_SLIDER[str_id].hovered and imgui.ImVec4(0.95, 0.95, 0.95, 0.8) or imgui.ImVec4(0.3, 0.3, 0.3, 0.8),
        UI_CUSTOM_SLIDER[str_id].start, 0.2
    )
 
    local colorBackGroundAfter = 0xAA252525
    local colorBackGroundBefore = 0xAA333333
    local colorCircle = 0xBBE7E7E7

    if UI_CUSTOM_SLIDER[str_id].active then
        local c = imgui.GetMousePos()
        if c.x - p.x >= 0 and c.x - p.x <= width then
            local s = c.x - p.x - 10
            local pr = s / (width - 20)
            local v = min + (max - min) * pr
            if v >= min and v <= max then
                value[0] = type and math_round(v) or v
            else
                value[0] = v < min and min or max
            end
        end
    end

    local posCircleX = p.x + 10 + (width - 20) / (max - min) * (value[0] - min)

    if posCircleX > p.x + 10 then DL:AddRectFilled(imgui.ImVec2(p.x, p.y), imgui.ImVec2(posCircleX, p.y + 20), colorBackGroundBefore, 10, 15) end
    if posCircleX < p.x + width - 10 then DL:AddRectFilled(imgui.ImVec2(posCircleX, p.y), imgui.ImVec2(p.x + width, p.y + 20), colorBackGroundAfter, 10, 15) end
    DL:AddRect(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + width, p.y + 20), imgui.GetColorU32Vec4(colorPadding), 10, 15)
    DL:AddCircleFilled(imgui.ImVec2(posCircleX, p.y + 10), 10, colorCircle)

    local sf = imgui.CalcTextSize(string.format(sformat, value[0]))
    local st = imgui.CalcTextSize(text)
    DL:AddText(imgui.ImVec2(p.x + width / 2 - sf.x / 2, p.y + 10 - sf.y / 2), imgui.GetColorU32Vec4(imgui.GetStyle().Colors[imgui.Col.Text]), string.format(sformat, value[0]))
    DL:AddText(imgui.ImVec2(p.x + width + 5, p.y + 10 - st.y / 2), imgui.GetColorU32Vec4(imgui.GetStyle().Colors[imgui.Col.Text]), text)

    return UI_CUSTOM_SLIDER[str_id].active
end
Аргументы:
АргументТип данныхСтатусОписание
str_idstringОбязательныйУникальный ID элемента
valueint/floatОбязательныйЗначение по умолчанию
typeboolОбязательныйЗначение true будет указывать на то, что тип данных value - int, а false на float
minint/floatОбязательныйМинимальное значение слайдера
maxint/floatОбязательныйМаксимальное значение слайдера
sformatstringНеобязательныйФормат строки значения слайдера
widthintНеобязательныйДлина слайдера
Демонстрация:
Grand-Theft-Auto-San-Andreas-2023.08.02-21.31.07.02-_online-video-cutter.com_.gif
 
Последнее редактирование:

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,798
2,659
Описание: Получает размеры .png картинки
Пример использования:
Lua:
function getPngSize(path)
    local file = io.open(path, "rb")
    if not file then return end
    local getBigEndianValueFromString = function(bytes) return (bytes:byte(4) + bytes:byte(3) * 256 + bytes:byte(2) * 65536 + bytes:byte(1) * 16777216) end
    file:seek("set", 16)   
    local bytesWidth = file:read(4)
    local width = getBigEndianValueFromString(bytesWidth)
    local bytesHeight = file:read(4)
    local height = getBigEndianValueFromString(bytesHeight)   
    file:close()
    return width, height
end


local path = "C:\\Users\\egaaa\\OneDrive\\Изображения\\hack.png"
local width, height = getPngSize(path)
print(width, height)
Код:
Lua:
function getPngSize(path)
    local file = io.open(path, "rb")
    if not file then return end
    local getBigEndianValueFromString = function(bytes) return (bytes:byte(4) + bytes:byte(3) * 256 + bytes:byte(2) * 65536 + bytes:byte(1) * 16777216) end
    file:seek("set", 16)   
    local bytesWidth = file:read(4)
    local width = getBigEndianValueFromString(bytesWidth)
    local bytesHeight = file:read(4)
    local height = getBigEndianValueFromString(bytesHeight)   
    file:close()
    return width, height
end

Описание: Затирает функцию прыжка
Пример использования:
Lua:
local memory = require("memory")


function clearBmxBunnyHop()   
    memory.fill(0x6C07A7, 0x90, 367, true)
end


clearBmxBunnyHop() -- затирает полностью функцию прыжка
Код:
Lua:
local memory = require("memory")


function clearBmxBunnyHop()   
    memory.fill(0x6C07A7, 0x90, 367, true)
end
 
Последнее редактирование:

белаколаэнжоер

Потрачен
4
3
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Описание: убирает брызги при прыжке в воду (мб повышает фпс)

Код:
Lua:
require('ffi').cast('float*', 0x858C4C)[0] = 0 -- стандартное значение 1000

Пример использования:
Lua:
function main()
    require('ffi').cast('float*', 0x858C4C)[0] = 0
end
 
Последнее редактирование:
  • Вау
Реакции: whyega52

Gorskin

♥ Love Lua ♥
Проверенный
1,342
1,179

Описание: Затирает функцию прыжка
Пример использования:
Lua:
local memory = require("memory")


function clearBmxBunnyHop()
    memory.fill(0x6C07A7, 0x90, 367, true)
end


clearBmxBunnyHop() -- затирает полностью функцию прыжка
Код:
Lua:
local memory = require("memory")


function clearBmxBunnyHop()
    memory.fill(0x6C07A7, 0x90, 367, true)
end
В чем прикол писать для каждого байта nop - No Operations если можно в адресе начала функции вписать байты конца функции, иначе говоря сделать прыжок. Объективно не грамотный подход, + можно использовать только writeMemory в моём способе. Не скажу что у тебя прям ошибка но лучше использовать ассемблер более правильно (даже солиднее выглядело бы)
И ещё скажу что с твоим методом изъебешься возвращать оригинальные байты для того чтобы вернуть функцию. Представь себе hex2bin с 367 байтами 😦
 
  • Нравится
Реакции: F0RQU1N and и whyega52

whyega52

Гений, миллионер, плейбой, долбаеб
Модератор
2,798
2,659
но лучше использовать ассемблер более правильно (даже солиднее выглядело бы)
И ещё скажу что с твоим методом изъебешься возвращать оригинальные байты для того чтобы вернуть функцию. Представь себе hex2bin с 367 байтами 😦
Да, зеленый пока, не додумался до того, что можно джамп бахнуть

Описание: Затирает функцию прыжка
Пример использования:
Lua:
local memory = require("memory")


function clearBmxBunnyHop()  
    memory.fill(0x6C07A7, 0x90, 367, true)
end


clearBmxBunnyHop() -- затирает полностью функцию прыжка
Код:
Lua:
local memory = require("memory")


function clearBmxBunnyHop()  
    memory.fill(0x6C07A7, 0x90, 367, true)
end
Описание: Устанавливает статус работы баннихопа на BMX. Спасибо @ARMOR
Пример использования:
Lua:
local ffi = require("ffi")


function setBmxBunnyHopState(state)
    local originalByte = 0x83
    local retByte = 0xC3
    local byte = ffi.cast("uint8_t*", 0x6C0390)
    byte[0] = (state and originalByte or retByte)
end


setBmxBunnyHopState(false) -- выключает возможность прыжка на BMX
Код:
Lua:
local ffi = require("ffi")


function setBmxBunnyHopState(state)
    local originalByte = 0x83
    local retByte = 0xC3
    local byte = ffi.cast("uint8_t*", 0x6C0390)
    byte[0] = (state and originalByte or retByte)
end
 
Последнее редактирование:
  • Нравится
Реакции: ARMOR