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

XRLM

Известный
2,547
865
Описание: Кнопка для навигации меню
Пример использования:
Lua:
local nav = {
    sel = new.int(config.LastMenu),
    list = {
        {name = 'Onfoot', icon = 'USER'}, {name = 'Incar', icon = 'CAR'}, {name = 'Weapon', icon = 'GUN'}
    }
}

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, 200), imgui.Cond.FirstUseEver)
        imgui.Begin("Test", renderWindow)
            for i, item in ipairs(nav.list) do
                imgui.CustomMenuItem(i, item)
            end
        imgui.End()
    end
)
Код:
Lua:
function imgui.CustomMenuItem(index, item, size, duration)
    local function bringVec2To(from, to, start_time, duration) -- by Cosmo
        local timer = os.clock() - start_time
        if timer >= 0.00 and timer <= duration then
            local count = timer / (duration / 100)
            return imgui.ImVec2(
                from.x + (count * (to.x - from.x) / 100),
                from.y + (count * (to.y - from.y) / 100)
            ), true
        end
        return (timer > duration) and to or from, false
    end
    
    local DL = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()

    local size = size or imgui.ImVec2(150, 35)
    local duration = duration or 0.2
    local str_id = item.name .. '##' .. index

    if UI_CUSTOM_MENU_ITEM == nil then UI_CUSTOM_MENU_ITEM = {} end
    if UI_CUSTOM_MENU_ITEM[str_id] == nil then
        UI_CUSTOM_MENU_ITEM[str_id] = {
            pos1 = nav.sel[0] == index and imgui.ImVec2(p.x, p.y + size.y / 2) or imgui.ImVec2(p.x, p.y),
            pos2 = nav.sel[0] == index and imgui.ImVec2(p.x + size.x, p.y + size.y / 2) or imgui.ImVec2(p.x + size.x, p.y + size.y),
            pos3 = imgui.ImVec2(p.x + size.x - 5, p.y + size.y / 2),
            pos4 = imgui.ImVec2(p.x + size.x - 1, p.y + size.y / 2),
            hovered = false,
            active = nav.sel[0] == index and true or false,
            h_start = 0,
            a_start = 0,
        }
    end

    local pool = UI_CUSTOM_MENU_ITEM[str_id]

    imgui.InvisibleButton(str_id, size)

    local clicked = imgui.IsItemClicked()
    local hovered = imgui.IsItemHovered()

    if hovered ~= pool.hovered and nav.sel[0] ~= index then
        pool.hovered = hovered
        local timer = os.clock() - pool.h_start
        if timer <= duration and timer >= 0 then
            pool.h_start = os.clock() - (duration - timer)
        else
            pool.h_start = os.clock()
        end
    end

    if clicked and nav.sel[0] ~= index then
        pool.active = true
        nav.sel[0] = index
        local timer = os.clock() - pool.a_start
        if timer <= duration and timer >= 0 then
            pool.a_start = os.clock() - (duration - timer)
        else
            pool.a_start = os.clock()
        end
    elseif pool.active and nav.sel[0] ~= index then
        pool.active = false
        local timer = os.clock() - pool.a_start
        if timer <= duration and timer >= 0 then
            pool.a_start = os.clock() - (duration - timer)
        else
            pool.a_start = os.clock()
        end
        if pool.h_start == 0 then
            pool.h_start = os.clock()
        end
    end

    pool.pos1 = bringVec2To(
        (pool.hovered or nav.sel[0] == index) and imgui.ImVec2(p.x, p.y + size.y / 2) or imgui.ImVec2(p.x, p.y),
        (pool.hovered or nav.sel[0] == index) and imgui.ImVec2(p.x, p.y) or imgui.ImVec2(p.x, p.y + size.y / 2),
        pool.h_start,
        duration
    )
    pool.pos2 = bringVec2To(
        (pool.hovered or nav.sel[0] == index) and imgui.ImVec2(p.x + size.x, p.y + size.y / 2) or imgui.ImVec2(p.x + size.x, p.y + size.y),
        (pool.hovered or nav.sel[0] == index) and imgui.ImVec2(p.x + size.x, p.y + size.y) or imgui.ImVec2(p.x + size.x, p.y + size.y / 2),
        pool.h_start,
        duration
    )
    pool.pos3 = bringVec2To(
        nav.sel[0] == index and imgui.ImVec2(p.x + size.x - 5, p.y + size.y / 2) or imgui.ImVec2(p.x + size.x - 5, p.y + size.y / 4),
        nav.sel[0] == index and imgui.ImVec2(p.x + size.x - 5, p.y + size.y / 4) or imgui.ImVec2(p.x + size.x - 5, p.y + size.y / 2),
        pool.a_start,
        duration
    )
    pool.pos4 = bringVec2To(
        nav.sel[0] == index and imgui.ImVec2(p.x + size.x - 1, p.y + size.y / 2) or imgui.ImVec2(p.x + size.x - 1, p.y + size.y / 4 + size.y / 2),
        nav.sel[0] == index and imgui.ImVec2(p.x + size.x - 1, p.y + size.y / 4 + size.y / 2) or imgui.ImVec2(p.x + size.x - 1, p.y + size.y / 2),
        pool.a_start,
        duration
    )

    local color1 = (pool.hovered or nav.sel[0] == index or os.clock() - pool.h_start <= duration) and imgui.GetStyle().Colors[imgui.Col.SeparatorActive] or imgui.ImVec4(0,0,0,0)
    local color2 = (nav.sel[0] == index or os.clock() - pool.a_start <= duration) and imgui.GetStyle().Colors[imgui.Col.Text] or imgui.ImVec4(0,0,0,0)
    local color3 = imgui.GetStyle().Colors[imgui.Col.Text]

    DL:AddRectFilled(pool.pos1, pool.pos2, imgui.GetColorU32Vec4(color1), 10, 15)
    DL:AddRectFilled(pool.pos3, pool.pos4, imgui.GetColorU32Vec4(color2), 5, 15)
    local si = imgui.CalcTextSize(faicons(item.icon))
    local st = imgui.CalcTextSize(item.name)
    DL:AddText(imgui.ImVec2(p.x + 15, p.y + size.y/2 - si.y/2), imgui.GetColorU32Vec4(color3), faicons(item.icon))
    DL:AddText(imgui.ImVec2(p.x + 45, p.y + size.y/2 - st.y/2), imgui.GetColorU32Vec4(color3), item.name)

    return clicked
end
Возможно в вашем имгуи стиле цвет кнопки будет уебищный
Демонстрация:
Grand Theft Auto San Andreas 2023.08.08 - 08.41.05.04 (online-video-cutter.com).gif


Описание: Чекбокс с анимацией. Хотел сделать так, чтобы можно было переключать состояние во время анимации, но реализовать без багов, к сожалению, не получилось, поэтому выкладываю с кд на переключение
Пример использования:
Lua:
local checkbox = new.bool(false)
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, 200), imgui.Cond.FirstUseEver)
        imgui.Begin("Test", renderWindow)
            imgui.CustomCheckbox('Checkbox', checkbox)
        imgui.End()
    end
)
Код:
Lua:
function imgui.CustomCheckbox(str_id, bool, a_speed)
    local p         = imgui.GetCursorScreenPos()
    local DL        = imgui.GetWindowDrawList()

    local label     = str_id:gsub('##.+', '') or ""
    local h         = imgui.GetTextLineHeightWithSpacing() + 2
    local speed     = a_speed or 0.2

    local function bringVec2To(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.ImVec2(
                from.x + (count * (to.x - from.x) / 100),
                from.y + (count * (to.y - from.y) / 100)
            ), true
        end
        return (timer > duration) and to or from, false
    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

    local c = {
        {0.18536826495, 0.42833250947},
        {0.44109925858, 0.70010380622},
        {0.38825341901, 0.70010380622},
        {0.81248970176, 0.28238693976},
    }

    if UI_CUSTOM_CHECKBOX == nil then UI_CUSTOM_CHECKBOX = {} end
    if UI_CUSTOM_CHECKBOX[str_id] == nil then
        UI_CUSTOM_CHECKBOX[str_id] = {
            lines = {
                {
                    from = imgui.ImVec2(0, 0),
                    to = imgui.ImVec2(h*c[1][1], h*c[1][2]),
                    start = 0,
                    anim = false,
                },
                {
                    from = imgui.ImVec2(0, 0),
                    to = bool[0] and imgui.ImVec2(h*c[2][1], h*c[2][2]) or imgui.ImVec2(h*c[1][1], h*c[1][2]),
                    start = 0,
                    anim = false,
                },
                {
                    from = imgui.ImVec2(0, 0),
                    to = imgui.ImVec2(h*c[3][1], h*c[3][2]),
                    start = 0,
                    anim = false,
                },
                {     
                    from = imgui.ImVec2(0, 0),   
                    to = bool[0] and imgui.ImVec2(h*c[4][1], h*c[4][2]) or imgui.ImVec2(h*c[3][1], h*c[3][2]),
                    start = 0,
                    anim = false,
                },
            },
            hovered = false,
            h_start = 0,
        }
    end

    local pool = UI_CUSTOM_CHECKBOX[str_id]

    imgui.BeginGroup()
        imgui.InvisibleButton(str_id, imgui.ImVec2(h, h))
        imgui.SameLine()
        local pp = imgui.GetCursorPos()
        imgui.SetCursorPos(imgui.ImVec2(pp.x, pp.y + h/2 - imgui.CalcTextSize(label).y/2))
        imgui.Text(label)
    imgui.EndGroup()

    local clicked = imgui.IsItemClicked()
    if pool.hovered ~= imgui.IsItemHovered() then
        pool.hovered = imgui.IsItemHovered()
        local timer = os.clock() - pool.h_start
        if timer <= speed and timer >= 0 then
            pool.h_start = os.clock() - (speed - timer)
        else
            pool.h_start = os.clock()
        end
    end

    if clicked then
        local isAnim = false

        for i = 1, 4 do
            if pool.lines[i].anim then
                isAnim = true
            end
        end

        if not isAnim then
            bool[0] = not bool[0]

            pool.lines[1].from = imgui.ImVec2(h*c[1][1], h*c[1][2])
            pool.lines[1].to = bool[0] and imgui.ImVec2(h*c[1][1], h*c[1][2]) or imgui.ImVec2(h*c[2][1], h*c[2][2])
            pool.lines[1].start = bool[0] and 0 or os.clock()

            pool.lines[2].from = bool[0] and imgui.ImVec2(h*c[1][1], h*c[1][2]) or imgui.ImVec2(h*c[2][1], h*c[2][2])
            pool.lines[2].to = bool[0] and imgui.ImVec2(h*c[2][1], h*c[2][2]) or imgui.ImVec2(h*c[2][1], h*c[2][2])
            pool.lines[2].start = bool[0] and os.clock() or 0

            pool.lines[3].from = imgui.ImVec2(h*c[3][1], h*c[3][2])
            pool.lines[3].to = bool[0] and imgui.ImVec2(h*c[3][1], h*c[3][2]) or imgui.ImVec2(h*c[4][1], h*c[4][2])
            pool.lines[3].start = bool[0] and 0 or os.clock() + speed

            pool.lines[4].from = bool[0] and imgui.ImVec2(h*c[3][1], h*c[3][2]) or imgui.ImVec2(h*c[4][1], h*c[4][2])
            pool.lines[4].to = imgui.ImVec2(h*c[4][1], h*c[4][2]) or imgui.ImVec2(h*c[4][1], h*c[4][2])
            pool.lines[4].start = bool[0] and os.clock() + speed or 0
        end
    end

    local pos = {}

    for i = 1, 4 do
        pos[i], pool.lines[i].anim = bringVec2To(
            p + pool.lines[i].from,
            p + pool.lines[i].to,
            pool.lines[i].start,
            speed
        )
    end

    local color = imgui.GetStyle().Colors[imgui.Col.ButtonActive]
    local c = imgui.GetStyle().Colors[imgui.Col.ButtonHovered]
    local colorHovered = bringVec4To(
        pool.hovered and imgui.ImVec4(c.x, c.y, c.z, 0) or imgui.ImVec4(c.x, c.y, c.z, 0.2),
        pool.hovered and imgui.ImVec4(c.x, c.y, c.z, 0.2) or imgui.ImVec4(c.x, c.y, c.z, 0),
        pool.h_start,
        speed
    )

    DL:AddRectFilled(p, imgui.ImVec2(p.x + h, p.y + h), imgui.GetColorU32Vec4(colorHovered), h/15, 15)
    DL:AddRect(p, imgui.ImVec2(p.x + h, p.y + h), imgui.GetColorU32Vec4(color), h/15, 15, 1.5)
    DL:AddLine(pos[1], pos[2], imgui.GetColorU32Vec4(color), h/10)
    DL:AddLine(pos[3], pos[4], imgui.GetColorU32Vec4(color), h/10)

    return clicked
end
Демонстрация:

Grand Theft Auto San Andreas 2023.08.08 - 20.31.03.09 (online-video-cutter.com).gif
 
Последнее редактирование:

sizeoftrickster

…And Megadeth For All?
Проверенный
123
451
Описание: функция позволяет получить номер клавиши, которая указана в gta_sa.set. Номера клавиш можно найди в vkeys.lua, либо же Virtual-Key Codes
Базовые адреса:
Lua:
--[[
На одно действие можно назначить 3 клавиши, но мне лень было искать 3, поэтому будет только 2
 --------- -------- -------- --------
|Действие |   #1   |   #2   |   #3   |
 --------- -------- -------- --------
| Forward |   0x38 |  0x2FC |     =) |
 --------- -------- -------- --------
| Backward|   0x44 |  0x308 |     =) |
 --------- -------- -------- --------
| Left    |   0x50 |  0x314 |     =) |
 --------- -------- -------- --------
| Right   |   0x5C |  0x320 |     =) |
 --------- -------- -------- --------
]]--
Код:
Lua:
--[[
location: string = путь до gta_sa.set
address: number = адрес, по которому будет найдена клавиша
]]--
function GetKeyNumber( location, address )
    local keyNumber = -1
    local file = io.open( location, "rb" )
    if ( file ) then
        file:seek( "cur", address )
        local bytes = file:read( "l" )
        local buffer = ffi.new( "uint8_t[?]", #bytes )
        ffi.copy( buffer, bytes, #bytes )
        keyNumber = tonumber( buffer[0] )
    end
    file:close()
    return keyNumber
end

--[[
location: string = путь до gta_sa.set
addresses: number = массив адресов, по которомым будет найдены клавиши
]]--
function GetKeysNumbers( location, addresses )
    local keysNumbers = {}
    for index = 1, #addresses do
        local file = io.open( location, "rb" )
        if ( file ) then
            file:seek( "cur", addresses[index] )
            local bytes = file:read( "l" )
            local buffer = ffi.new( "uint8_t[?]", #bytes )
            ffi.copy( buffer, bytes, #bytes )
            keysNumbers[#keysNumbers + 1] = tonumber( buffer[0] )
        end
        file:close()
    end
    return keysNumbers
end
Пример кода:

Lua:
require( "moonloader" )
local ffi = require( "ffi" )

function main()
    --В данном случае, я ищу клавиши со второго столбца
    local wsad = { 0x2FC, 0x308, 0x314, 0x320 }
    local addr = GetKeysNumbers( "C:\\Users\\sizeoftrickster\\Documents\\GTA San Andreas User Files\\gta_sa.set", wsad )
    for index = 1, #addr do
        print( addr[index] )
    end
    wait( -1 )
end
--[[
Ouput:
87(0x57) -> VK_W
83(0x53) -> VK_S
65(0x41) -> VK_A
68(0x44) -> VK_D
]]--
 

Lance_Sterling

Известный
801
281
Описание:
функция для поиска элемента в массиве по ключу/значению
Код:
function search(array, text, findKey)
    if (#text > 0) then
        local finded = {};
  
        for k, v in pairs(array) do
            if string.rlower(findKey and k or v):find(string.rlower(text)) then
                finded[k] = v;
            end
        end
  
        return finded;
    else
        return array;
    end
end

local russian_characters = {
    [168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я',
}
function string.rlower(s)
    s = s:lower()
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch + 32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end
Пример использования:
Код:
for k, v in pairs(search(faicons, u8:decode(str(searchLabel)), true)) do
    imgui.Text(v..' | '..k)
    if imgui.IsItemClicked() then
        setClipboardText(k)
        sampAddChatMessage('твой буфер обмена засран', -1)
    end
end
 

DZONE

Известный
183
185
function string.rlower(s) s = s:lower() local strlen = s:len() if strlen == 0 then return s end s = s:lower() local output = '' for i = 1, strlen do local ch = s:byte(i) if ch >= 192 and ch <= 223 then -- upper russian characters output = output .. russian_characters[ch + 32] elseif ch == 168 then -- Ё output = output .. russian_characters[184] else output = output .. string.char(ch) end end return output end
Lua:
function toLowerCase(str)
    return select(1, string.gsub(str, "([A-ZА-ЯЁ])", function(c)
        return string.char(string.byte(c) + (c == "ё" and 16 or 32))
    end))
end
 
  • Нравится
  • Грустно
Реакции: Lance_Sterling и Vespan

Vespan

loneliness
Проверенный
2,105
1,634
Описание:
функция для поиска элемента в массиве по ключу/значению
Код:
function search(array, text, findKey)
    if (#text > 0) then
        local finded = {};
 
        for k, v in pairs(array) do
            if string.rlower(findKey and k or v):find(string.rlower(text)) then
                finded[k] = v;
            end
        end
 
        return finded;
    else
        return array;
    end
end

local russian_characters = {
    [168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я',
}
function string.rlower(s)
    s = s:lower()
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch + 32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end
Пример использования:
Код:
for k, v in pairs(search(faicons, u8:decode(str(searchLabel)), true)) do
    imgui.Text(v..' | '..k)
    if imgui.IsItemClicked() then
        setClipboardText(k)
        sampAddChatMessage('твой буфер обмена засран', -1)
    end
end
Lua:
function returnValueInTable(t,key,value)
    for k,v in pairs(t) do
        if type(t[k]) == 'table' then
            local res = {returnValueInTable(t[k],key,value)}
            if res[1] ~= nil then
                return res[1],res[2]
            end
        else
            if (key == nil and true or tostring(k) == key) and (value == nil and true or (tostring(v) == value)) then
                return v,t
            end
        end
    end
    return nil
end
Lua:
local t = {
    {
        key1 = '123',
    }
    key1 = '12333',
}

local a,b = returnValueInTable(t,key1,'123')
-- return {key = '123'}
оно получше
 

CaJlaT

Овощ
Модератор
2,806
2,609
Описание:
функция для поиска элемента в массиве по ключу/значению
Код:
function search(array, text, findKey)
    if (#text > 0) then
        local finded = {};
 
        for k, v in pairs(array) do
            if string.rlower(findKey and k or v):find(string.rlower(text)) then
                finded[k] = v;
            end
        end
 
        return finded;
    else
        return array;
    end
end

local russian_characters = {
    [168] = 'Ё', [184] = 'ё', [192] = 'А', [193] = 'Б', [194] = 'В', [195] = 'Г', [196] = 'Д', [197] = 'Е', [198] = 'Ж', [199] = 'З', [200] = 'И', [201] = 'Й', [202] = 'К', [203] = 'Л', [204] = 'М', [205] = 'Н', [206] = 'О', [207] = 'П', [208] = 'Р', [209] = 'С', [210] = 'Т', [211] = 'У', [212] = 'Ф', [213] = 'Х', [214] = 'Ц', [215] = 'Ч', [216] = 'Ш', [217] = 'Щ', [218] = 'Ъ', [219] = 'Ы', [220] = 'Ь', [221] = 'Э', [222] = 'Ю', [223] = 'Я', [224] = 'а', [225] = 'б', [226] = 'в', [227] = 'г', [228] = 'д', [229] = 'е', [230] = 'ж', [231] = 'з', [232] = 'и', [233] = 'й', [234] = 'к', [235] = 'л', [236] = 'м', [237] = 'н', [238] = 'о', [239] = 'п', [240] = 'р', [241] = 'с', [242] = 'т', [243] = 'у', [244] = 'ф', [245] = 'х', [246] = 'ц', [247] = 'ч', [248] = 'ш', [249] = 'щ', [250] = 'ъ', [251] = 'ы', [252] = 'ь', [253] = 'э', [254] = 'ю', [255] = 'я',
}
function string.rlower(s)
    s = s:lower()
    local strlen = s:len()
    if strlen == 0 then return s end
    s = s:lower()
    local output = ''
    for i = 1, strlen do
        local ch = s:byte(i)
        if ch >= 192 and ch <= 223 then -- upper russian characters
            output = output .. russian_characters[ch + 32]
        elseif ch == 168 then -- Ё
            output = output .. russian_characters[184]
        else
            output = output .. string.char(ch)
        end
    end
    return output
end
Пример использования:
Код:
for k, v in pairs(search(faicons, u8:decode(str(searchLabel)), true)) do
    imgui.Text(v..' | '..k)
    if imgui.IsItemClicked() then
        setClipboardText(k)
        sampAddChatMessage('твой буфер обмена засран', -1)
    end
end
Для питонистов:
 
  • Нравится
Реакции: MLycoris

Gorskin

{Reverse Developer} ✓
Проверенный
1,251
1,054
Описание: Фиксит овальную луну в игре.
Lua:
 writeMemory(0x70CEEF, 1, 1, true)
sa-mp-054.png
sa-mp-055.png

Описание: Делает идеально круглый радар не зависимо от разрешения экрана.
Используется специальная формула для выявления идеального круга на всех разрешениях экрана.
Примечание: После смены разрешения в игре необходимо опять записать значение в адреса.
Lua:
 --ideal rounded radar
 local screenX = readMemory(0xC17044, 2, true)
 local screenY = readMemory(0xC17048, 2, true)
 local resolution = screenX / screenY
 local idealRound = 0.0015625 / resolution * 1.185185186
 local constMem = 0xFFACEF
 writeMemory(constMem, 4, representFloatAsInt(idealRound), false)
 writeMemory(0x5834BC, 4, constMem, false)
 writeMemory(0x58A443, 4, constMem, false)
 writeMemory(0x58A5DA, 4, constMem, false)
 writeMemory(0x58A6E0, 4, constMem, false)
 writeMemory(0x58A793, 4, constMem, false)
 writeMemory(0x58A830, 4, constMem, false)
 writeMemory(0x58A8E1, 4, constMem, false)
 writeMemory(0x58A984, 4, constMem, false)
 --ideal rounded radar
sa-mp-056.png
 
Последнее редактирование:

why ega

РП игрок
Модератор
2,554
2,246
Описание: Изменяет цвет игроку в формате RGBA.
Код:
Lua:
local ffi = require("ffi")


function setPlayerColor(playerId, color, sampVersion)
    local nColor = tonumber(color)
    local nPlayerId = tonumber(playerId)
    if not nColor or not nPlayerId then return end
    local offsets = {
        setPlayerColor = {
            ["DLR1"] = 0xA6F50,
            ["R1"] = 0xAD550,
            ["R2"] = 0xAD720,
            ["R3"] = 0xA6AD0,
            ["R4"] = 0xA7220,
            ["R5"] = 0xA7210,
        }       
    }
    local samp = getModuleHandle("samp.dll")
    local setPlayerColor = ffi.cast("int(__stdcall*)(unsigned int, int)", (samp + offsets.setPlayerColor[sampVersion]))
    return setPlayerColor(nPlayerId, nColor)
end
Пример использования:
Lua:
print(setPlayerColor(64, 0xFF000000, "R1")) -- изменят цвет игроку с ID 64 на красный
 
  • Нравится
Реакции: ollydbg, MLycoris и ARMOR

Gorskin

{Reverse Developer} ✓
Проверенный
1,251
1,054
Описание: Изменяет цвет игроку в формате RGBA.
Код:
Lua:
local ffi = require("ffi")


function setPlayerColor(playerId, color, sampVersion)
    local nColor = tonumber(color)
    local nPlayerId = tonumber(playerId)
    if not nColor or not nPlayerId then return end
    local offsets = {
        setPlayerColor = {
            ["DLR1"] = 0xA6F50,
            ["R1"] = 0xAD550,
            ["R2"] = 0xAD720,
            ["R3"] = 0xA6AD0,
            ["R4"] = 0xA7220,
            ["R5"] = 0xA7210,
        }      
    }
    local samp = getModuleHandle("samp.dll")
    local setPlayerColor = ffi.cast("int(__stdcall*)(unsigned int, int)", (samp + offsets.setPlayerColor[sampVersion]))
    return setPlayerColor(nPlayerId, nColor)
end
Пример использования:
Lua:
print(setPlayerColor(64, 0xFF000000, "R1")) -- изменят цвет игроку с ID 64 на красный
Цвет ника или скина?
 
  • Нравится
Реакции: PanSeek

why ega

РП игрок
Модератор
2,554
2,246
Цвет ника или скина?
ника

Описание: Включает/отключает отрисовку хп и армора над игроком. Спасибо за помощь @AdCKuY_DpO4uLa
Код:
Lua:
local memory = require("memory")


function toggleHealthBar(toggle, sampVersion)
    local offsets = {
        ["DLR1"] = 0x73CB0,
        ["R1"] = 0x6FC30,
        ["R2"] = 0x6FCD0,
        ["R3"] = 0x73B20,
        ["R4"] = 0x74240,
        ["R5"] = 0x74210,
    }    
    local samp = getModuleHandle("samp.dll")
    local address = (samp + offsets[sampVersion]
    local byte = (toggle and 0x55 or 0xC3)
    memory.write(address, byte, 1, true)    
end
Пример использования:
Lua:
local memory = require("memory")


function main()
    while not isSampAvailable() do wait(0) end
    toggleHealthBar(false, "R3") -- отключает хп бар на R3 версии сампа
end


function toggleHealthBar(toggle, sampVersion)
    local offsets = {
        ["DLR1"] = 0x73CB0,
        ["R1"] = 0x6FC30,
        ["R2"] = 0x6FCD0,
        ["R3"] = 0x73B20,
        ["R4"] = 0x74240,
        ["R5"] = 0x74210,
    }    
    local samp = getModuleHandle("samp.dll")
    local address = (samp + offsets[sampVersion]
    local byte = (toggle and 0x55 or 0xC3)
    memory.write(address, byte, 1, true)    
end
 
Последнее редактирование:

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,731
4,714
Описание:
Получает массив всех моделей и его размер(работает с fastman limit adjuster)
Lua:
ffi.cdef[[
  struct CStreamingInfo {
    short m_nNextIndex; // ms_pArrayBase array index
    short m_nPrevIndex; // ms_pArrayBase array index
    short m_nNextIndexOnCd;
    unsigned char m_nFlags; // see eStreamingFlags
    unsigned char m_nImgId;
    unsigned int m_nCdPosn;
    unsigned int m_nCdSize;
    unsigned char m_nLoadState; // see eStreamingLoadState
    char  __pad[3];
  };
]]

function get_model_info_array()
  return ffi.cast("struct CStreamingInfo**", 0x0040ED3E + 1)[0]
end

function get_model_info_array_size()
  local astart = tonumber(ffi.cast("unsigned int*", 0x40ED49 + 1)[0])
  local aend = tonumber(ffi.cast("unsigned int", get_model_info_array()))
  local len = (aend - astart) / ffi.sizeof(ffi.typeof("struct CStreamingInfo"))
  return len
end

Пример использования:
Получение всех существующих в игре моделей:
Lua:
function get_all_models()
    local result = {}
    local model_arr = get_model_info_array

    for i = 0, get_model_info_array_size() do
        if (model_arr[i].m_nCdSize ~= 0) then
            table.insert(result, i)
        end
    end
  
    return result
end

Описание:
Получение всех загруженных в игре моделей(в порядке самая старая загруженная -> самая последняя загруженная):

Lua:
function get_array_base()
  return ffi.cast("struct CStreamingInfo**", 0x9654B4)[0]
end

function get_start_loaded()
  return ffi.cast("struct CStreamingInfo**", 0x8E4C60)[0]
end

function get_end_loaded()
  return ffi.cast("struct CStreamingInfo**", 0x8E4C5C)[0]
end


function get_loaded_models()
  local result = {}

  local prev_index = get_end_loaded().m_nPrevIndex

  local current = nil

  if (prev_index ~= -1) then
    current = get_array_base() + prev_index
  end

  while (current != get_start_loaded()) do

    prev_index = current.m_nPrevIndex
    if (prev_index ~= -1) then
      current = get_array_base() + prev_index
    end

    table.insert(result, current - get_model_info_array())
  end

  return result
end

Пример использования:
Lua:
for k, v in pairs(get_loaded_models()) do print(k, v) end
 

why ega

РП игрок
Модератор
2,554
2,246
Описание: Проверяет, инициализирован SAMP или нет (без использования SAMPFUNCS.asi). Кому не лень, можете дать оффсеты для других версий.
Код:
Lua:
local ffi = require("ffi")

function isSAMPRunning()
    local handle = getModuleHandle("samp.dll")
    local result = true
    if handle ~= nil then
        local e_lfanew = ffi.cast("long*", handle + 60)[0]
        local nt_header = handle + e_lfanew
        local entry_point_addr = ffi.cast("unsigned int*", nt_header + 40)[0]
        if entry_point_addr == 0x31DF13 then -- R1
            result = result and ffi.cast("unsigned int*", handle + 0x21A0F8)[0] ~= 0x0
        elseif entry_point_addr == 0x3195DD then -- R2
            result = result and ffi.cast("unsigned int*", handle + 0x21A100)[0] ~= 0x0
        elseif entry_point_addr == 0xCC4D0 then -- R3
            result = result and ffi.cast("unsigned int*", handle + 0x26E8DC)[0] ~= 0x0
        elseif entry_point_addr == 0xCBCB0 then -- R4
            result = result and ffi.cast("unsigned int*", handle + 0x26EA0C)[0] ~= 0x0
        elseif entry_point_addr == 0xFDB60 then -- R5
            result = result and ffi.cast("unsigned int*", handle +  0x26EB94)[0] ~= 0x0
        end
    end
    return result
end
Пример использования:
Lua:
--========================================================LIB-========================================================

local ffi = require("ffi")

--========================================================MAIN========================================================

function main()
    while not isSAMPRunning() do wait(100) end

    sampAddChatMessage("ЭТО САМП ДЕТКААА", -1)

    wait(-1)
end

--========================================================FUNCTION========================================

function isSAMPRunning()
    local handle = getModuleHandle("samp.dll")
    local result = true
    if handle ~= nil then
        local e_lfanew = ffi.cast("long*", handle + 60)[0]
        local nt_header = handle + e_lfanew
        local entry_point_addr = ffi.cast("unsigned int*", nt_header + 40)[0]
        if entry_point_addr == 0x31DF13 then -- R1
            result = result and ffi.cast("unsigned int*", handle + 0x21A0F8)[0] ~= 0x0
        elseif entry_point_addr == 0x3195DD then -- R2
            result = result and ffi.cast("unsigned int*", handle + 0x21A100)[0] ~= 0x0
        elseif entry_point_addr == 0xCC4D0 then -- R3
            result = result and ffi.cast("unsigned int*", handle + 0x26E8DC)[0] ~= 0x0
        elseif entry_point_addr == 0xCBCB0 then -- R4
            result = result and ffi.cast("unsigned int*", handle + 0x26EA0C)[0] ~= 0x0
        elseif entry_point_addr == 0xFDB60 then -- R5
            result = result and ffi.cast("unsigned int*", handle +  0x26EB94)[0] ~= 0x0
        end
    end
    return result
end
Описание: Адекватная функция получения текущей версии SAMP (+ проверка на доступность SAMP)
Код:
Lua:
local ffi = require("ffi")


---Retrieves the current version of SAMP: "DLR1", "R1", "R2", "R3", "R4", "R5"
---@return string version SAMP version
function getSampVersion()
    local version = "unknown"
    local versions = {[0xFDB60] = "DLR1",  [0x31DF13] = "R1", [0x3195DD] = "R2", [0xCC4D0] = "R3",  [0xCBCB0] = "R4", [0xCBC90] = "R5"}
    local sampHandle = getModuleHandle("samp.dll")
    if sampHandle then
        local e_lfanew = ffi.cast("long*", (sampHandle + 60))
        local ntHeader = (sampHandle + e_lfanew[0])
        local pEntryPoint = ffi.cast("uintptr_t*", (ntHeader + 40))
        if versions[pEntryPoint[0]] then version = versions[pEntryPoint[0]] end
    end
    return version
end
Пример использования:
Lua:
local ffi = require("ffi")


function main()
    while not isSampAvailable() do wait(0) end
    print("SampLoad!")
end


---Retrieves the current version of SAMP: "DLR1", "R1", "R2", "R3", "R4", "R5"
---@return string version SAMP version
function getSampVersion()
    local version = "unknown"
    local versions = {[0xFDB60] = "DLR1",  [0x31DF13] = "R1", [0x3195DD] = "R2", [0xCC4D0] = "R3",  [0xCBCB0] = "R4", [0xCBC90] = "R5"}
    local sampHandle = getModuleHandle("samp.dll")
    if sampHandle then
        local e_lfanew = ffi.cast("long*", (sampHandle + 60))
        local ntHeader = (sampHandle + e_lfanew[0])
        local pEntryPoint = ffi.cast("uintptr_t*", (ntHeader + 40))
        if versions[pEntryPoint[0]] then version = versions[pEntryPoint[0]] end
    end
    return version
end

---Checks if SAMP functions are available
---@return boolean result is the main structure initialized
function isSampAvailable()
    local sampHandle = getModuleHandle("samp.dll")
    local offsets =  {CNetGame = {["DLR1"] = 0x2ACA24, ["R1"] = 0x21A0F8, ["R2"] = 0x21A100, ["R3"] = 0x26E8DC, ["R4"] = 0x26EA0C, ["R5"] = 0x26EB94}}
    local pNetGame = ffi.cast("uintptr_t*", (sampHandle + offsets.CNetGame[getSampVersion()]))
    return (pNetGame ~= 0)
end
 
Последнее редактирование:

sazzas1978

Известный
124
121
Lua:
local ffi = require("ffi")

ffi.cdef[[
    typedef void* HANDLE;
    typedef uint32_t DWORD;
    typedef int BOOL;
    HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
    int CloseHandle(HANDLE hObject);
    HANDLE GetModuleHandleA(const char* lpModuleName);
    int VirtualQueryEx(HANDLE hProcess, const void* lpAddress, void* lpBuffer, size_t dwLength);
    int ReadProcessMemory(HANDLE hProcess, const void* lpBaseAddress, void* lpBuffer, size_t nSize, size_t* lpNumberOfBytesRead);
    DWORD GetCurrentProcessId(void);

    typedef struct {
        void* BaseAddress;
        void* AllocationBase;
        DWORD AllocationProtect;
        size_t RegionSize;
        DWORD State;
        DWORD Protect;
        DWORD Type;
    } MEMORY_BASIC_INFORMATION;
]]

function findSignatureInModule(signature, moduleName)
    local moduleAddress = ffi.C.GetModuleHandleA(moduleName)
    if moduleAddress == nil then
        return nil, "Module not found"
    end

    local processId = ffi.C.GetCurrentProcessId()
    local hProcess = ffi.C.OpenProcess(0x1F0FFF, 0, processId)

    local moduleInfo = ffi.new("MEMORY_BASIC_INFORMATION")
    local address = moduleAddress

    local signatureBytes = {}
    for byte in signature:gmatch("%S+") do
        if byte == "??" then
            table.insert(signatureBytes, false)
        else
            table.insert(signatureBytes, tonumber(byte, 16))
        end
    end

    while ffi.C.VirtualQueryEx(hProcess, address, moduleInfo, ffi.sizeof(moduleInfo)) ~= 0 do
        if moduleInfo.State == 0x1000 and moduleInfo.Protect == 0x20 then
            local size = tonumber(moduleInfo.RegionSize)
            local buffer = ffi.new("uint8_t[?]", size)
            local bytesRead = ffi.new("size_t[1]")

            ffi.C.ReadProcessMemory(hProcess, address, buffer, size, bytesRead)

            for i = 0, size - #signatureBytes do
                local found = true
                for j = 1, #signatureBytes do
                    local byte = buffer[i + j - 1]
                    if signatureBytes[j] ~= false and byte ~= signatureBytes[j] then
                        found = false
                        break
                    end
                end

                if found then
                    ffi.C.CloseHandle(hProcess)
                    return ffi.cast("intptr_t", address) + i
                end
            end
        end

        address = ffi.cast("void*", ffi.cast("intptr_t", address) + moduleInfo.RegionSize)
    end

    ffi.C.CloseHandle(hProcess)
    return nil, "Signature not found"
end
ищет по сигнатуре адресс в библиотеке.
Пример:
Lua:
local address, error = findSignatureInModule(
"E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 8B F8 89 7C 24 20"
, "samp.dll")
if address then
    print('found')
else
    print(error)
end
 

CaJlaT

Овощ
Модератор
2,806
2,609
Описание: методьі для работьі с "флагами" шрифта

Lua:
local FontFlags = {
      DEFAULT = 0,
      BOLD = 1,
      ITALIC = 2,
      OUTLINE = 4,
      SHADOW = 8,
}

-- parameters = { isBold, isItalic, hasOutline, hasShadow }
function renderBuildFontFlags(parameters)
      local flags = 0

      if parameters.isBold then
            flags = flags + FontFlags.BOLD
      end

      if parameters.isItalic then
            flags = flags + FontFlags.ITALIC
      end

      if parameters.hasOutline then
            flags = flags + FontFlags.OUTLINE
      end

      if parameters.hasShadow then
            flags = flags + FontFlags.SHADOW
      end

      return flags
end
imgui:
function imgui.FontEdit(state)
      local wasStateTouched = false

      if imgui.InputText("Face", state.face, STRING_BUFFER_SIZE) then
            wasStateTouched = true
      end

      if imgui.InputInt("Size", state.size) then
            wasStateTouched = true
      end
     
      if imgui.Checkbox("Shadow", state.hasShadow) then
            wasStateTouched = true
      end

      if imgui.Checkbox("Outline", state.hasOutline) then
            wasStateTouched = true
      end

      if imgui.Checkbox("Italic", state.isItalic) then
            wasStateTouched = true
      end

      if imgui.Checkbox("Bold", state.isBold) then
            wasStateTouched = true
      end

      return wasStateTouched
end

-- somewhere
if imgui.FontEdit(config.font) then
      local flags = renderBuildFontFlags(config.font)
      yourFont = renderCreateFont(config.font.face, config.font.size, flags)
end
no imgui:
local font = renderCreateFont("Arial", 12, FontFlags.BOLD + FontFlags.OUTLINE)

✔️
JVyez83.png



Zc5Kmt0.png
Библиотека, которая идёт из коробки:
Lua:
local flags = require('moonloader').font_flag
1692946527116.png