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

ARMOR

011110000111100101101001
Модератор
4,969
6,890
Описание: Получает указатели на текстуры игровых иконок оружия по ID оружия

Где это можно использовать? Например в кастомных имгуи худах вместо того чтобы подгружать из папки большое количество иконок для оружия просто получать игровые иконки и рендерить их.

Код:
Lua:
local ffi = require("ffi")
ffi.cdef[[
    typedef unsigned char RwUInt8;
    typedef int RwInt32;
    typedef short RwInt16;
    typedef struct RwRaster RwRaster;
    struct RwRaster {
        struct RwRaster*            parent;
        RwUInt8*                    cpPixels;
        RwUInt8*                    palette;
        RwInt32                     width, height, depth;
        RwInt32                     stride;
        RwInt16                     nOffsetX, nOffsetY;
        RwUInt8                     cType;
        RwUInt8                     cFlags;
        RwUInt8                     privateFlags;
        RwUInt8                     cFormat;
        RwUInt8*                    originalPixels;
        RwInt32                     originalWidth;
        RwInt32                     originalHeight;
        RwInt32                     originalStride;
        void*                       texture_ptr;
    };
    typedef struct RwLLLink RwLLLink;
    struct RwLLLink
    {
        void *next;
        void *prev;
    };
    typedef struct RwLinkList RwLinkList;
    struct RwLinkList
    {
        struct RwLLLink link;
    };
    typedef struct RwObject RwObject;
    struct RwObject
    {
      char type;
      char subType;
      char flags;
      char privateFlags;
      struct RwFrame *parent;
    };
    typedef struct RwTexDictionary RwTexDictionary;
    struct RwTexDictionary
    {
        RwObject object;
        RwLinkList texturesInDict;
        RwLLLink lInInstance;
    };
    typedef struct CBaseModelInfo_vtbl CBaseModelInfo_vtbl;
    struct CBaseModelInfo_vtbl {
        void* destructor;
        void* AsAtomicModelInfoPtr;
        void* AsDamageAtomicModelInfoPtr;
        void* AsLodAtomicModelInfoPtr;
        char(__thiscall* GetModelType)(struct CBaseModelInfo*);
    };
    typedef struct CBaseModelInfo CBaseModelInfo;
    struct CBaseModelInfo {
        CBaseModelInfo_vtbl* vtbl;
        unsigned int m_dwKey;
        short m_wUsageCount;
        short m_wTxdIndex;
        char m_nAlpha;
        char m_n2dfxCount;
        short m_w2dfxIndex;
        short m_wObjectInfoIndex;
        unsigned short m_nMdlFlags;
        struct CColModel* m_pColModel;
        float m_fDrawDistance;
        struct RpClump* m_pRwObject;
    };
    typedef struct TxdDef TxdDef;
    struct TxdDef {
        RwTexDictionary *m_pRwDictionary;
        unsigned short m_wRefsCount;
        short m_wParentIndex;
        unsigned int m_hash;
    };
    typedef struct CPool CPool;
    struct CPool
    {
        TxdDef* m_pObjects;
        uint8_t* m_byteMap;
        int m_nSize;
        int top;
        char m_bOwnsAllocations;
        char bLocked;
        short _pad;
    };
    typedef struct RwTexture RwTexture;
    struct RwTexture {
        RwRaster* raster;
    };
    typedef struct CSprite2d CSprite2d;
    struct CSprite2d {
        RwTexture* m_pTexture;
    };
    typedef struct CWeaponInfo CWeaponInfo;
    struct CWeaponInfo
    {
        int m_eFireType;
        float targetRange;
        float m_fWeaponRange;
        int dwModelId1;
        int dwModelId2;
        int nSlot;
        int m_nFlags;
        int AssocGroupId;
        short ammoClip;
        short damage;
        float* fireOffset;
        int skillLevel;
        int reqStatLevelToGetThisWeaponSkilLevel;
        float m_fAccuracy;
        float moveSpeed;
        float animLoopStart;
        float animLoopEnd;
        int animLoopFire;
        int animLoop2Start;
        int animLoop2End;
        int animLoop2Fire;
        float breakoutTime;
        float speed;
        int radius;
        float lifespan;
        float spread;
        char AssocGroupId2;
        char field_6D;
        char baseCombo;
        char m_nNumCombos;
    };
]]

local CWeaponInfo__GetWeaponInfo = ffi.cast("CWeaponInfo*(__cdecl*)(uint8_t, uint8_t)", 0x743C60)
local CKeyGen__AppendStringToKey = ffi.cast("unsigned int(__cdecl*)(unsigned int, char*)", 0x53CF70)
local RwTexDictionaryFindHashNamedTexture = ffi.cast("RwTexture*(__cdecl*)(RwTexDictionary*, unsigned int)", 0x734E50)

function getWeaponIconTexture(nWeaponModelId)
    local pTexture = ffi.new("RwTexDictionary*");
    local pModelInfo = ffi.new("CBaseModelInfo*");
    local pWeaponInfo = CWeaponInfo__GetWeaponInfo(nWeaponModelId, 1);
    if (pWeaponInfo.dwModelId1 > 0) then
        pModelInfo = ffi.cast("CBaseModelInfo**", 0xA9B0C8)[pWeaponInfo.dwModelId1];
        local nTxdIndex = pModelInfo.m_wTxdIndex;
        local pTxdPool = ffi.cast("CPool**", 0xC8800C)[0];
        if ffi.cast("uint8_t", pTxdPool.m_byteMap + nTxdIndex) >= 0 then
            pTexture = pTxdPool.m_pObjects[nTxdIndex].m_pRwDictionary;
        end
        if pTexture ~= nil then
            local nAppended = CKeyGen__AppendStringToKey(pModelInfo.m_dwKey, ffi.cast("char*", "ICON"));
            local texture = RwTexDictionaryFindHashNamedTexture(pTexture, nAppended);
            if texture ~= nil then
                return texture.raster.texture_ptr
            else
            end
        end
    else
        local fistSprite = ffi.cast("CSprite2d*", 0xBAB1FC)[0];
        return fistSprite.m_pTexture.raster.texture_ptr
    end
    return nil;
end

Способ применения:
Lua:
-- В фрейме мимгуи:
local dl = imgui.GetBackgroundDrawList();
local texture = getWeaponIconTexture(getCurrentCharWeapon(PLAYER_PED))
if texture ~= nil then
    dl:AddImage(texture, imgui.ImVec2(400, 400), imgui.ImVec2(600, 600))
end

Скриншот:
1713066362986.png
 
Последнее редактирование:

UBP

Известный
350
204
Grand Theft Auto  San Andreas 2024.04.14 - 12.21.20.01.gif


Lua:
drawAnimatedLoadingIndicator(resX / 2, resY / 2, 50, 8, 0.2)
Lua:
function drawAnimatedLoadingIndicator(centerX, centerY, radius, thickness, speed)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()
    local time = ImGui.GetTime()

    -- Основные параметры
    local start_angle = -math.pi / 2
    local max_angle = 2 * math.pi
    local end_angle = start_angle + max_angle * (time * speed % 1)

    -- Цвета
    local bgColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.2, 0.2, 1))
    local fgColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.4, 0.7, 0.2, 1))

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

    -- Рисуем анимированный прогресс индикатора
    draw_list:PathArcTo(ImGui.ImVec2(centerX, centerY), radius, start_angle, end_angle, 64)
    draw_list:PathStroke(fgColor, false, thickness)
end


Grand Theft Auto  San Andreas 2024.04.14 - 12.31.08.02.gif







Lua:
local totalTime = 15 -- Общее время таймера в секундах
local startTime = os.time() -- Время старта таймера


local currentTime = os.time()
local elapsedTime = os.difftime(currentTime, startTime)
local remainingTime = math.max(0, totalTime - elapsedTime)
drawCircularTimer(resX / 2, resY / 2, 100, remainingTime, totalTime)
Lua:
function drawCircularTimer(x, y, radius, remainingTime, totalTime)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()

    -- Определяем параметры для визуализации таймера
    local start_angle = 3 * math.pi / 2
    local end_angle = start_angle + (2 * math.pi) * (remainingTime / totalTime)

    -- Цвета
    local timerColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.7, 0.3, 1)) -- Зеленый
    local backgroundColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.2, 0.2, 0.3)) -- Темно-серый

    -- Рисуем фон таймера
    draw_list:AddCircleFilled(ImGui.ImVec2(x, y), radius, backgroundColor, 64)

    -- Рисуем оставшееся время таймера
    if remainingTime > 0 then
        draw_list:PathArcTo(ImGui.ImVec2(x, y), radius - 1, start_angle, end_angle, 64)
        draw_list:PathStroke(timerColor, false, 2)
    end

    -- Текст с оставшимся временем
    local timeText = string.format("%.2f", remainingTime)
    local textSize = ImGui.CalcTextSize(timeText)
    draw_list:AddText(ImGui.ImVec2(x - textSize.x / 2, y - textSize.y / 2), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)), timeText)
end
Grand Theft Auto  San Andreas 2024.04.14 - 12.40.11.03.gif


Lua:
local volumeLevel = imgui.new.float(0.5)
drawVerticalVolumeSlider(resX / 2, resY / 2, 30, 200, volumeLevel)
Lua:
function drawVerticalVolumeSlider(x, y, width, height, volumeLevel)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()

    -- Определяем параметры
    local sliderBgColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.25, 0.3, 1))
    local sliderFilledColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.7, 0.3, 1))
    local borderColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 0.5))

    -- Рисуем фон слайдера
    draw_list:AddRectFilled(ImGui.ImVec2(x, y), ImGui.ImVec2(x + width, y + height), sliderBgColor, 4)
    draw_list:AddRect(ImGui.ImVec2(x, y), ImGui.ImVec2(x + width, y + height), borderColor, 4)
    ImGui.SetCursorPos(ImGui.ImVec2(x, y))
    ImGui.InvisibleButton("slider", ImGui.ImVec2(width, height))

    -- Если элемент активен (нажатие и удерживание кнопки мыши), обновляем уровень громкости
    if ImGui.IsItemActive() then
        local mousePos = ImGui.GetMousePos()
        volumeLevel[0] = math.max(0, math.min(1, (mousePos.y - y) / height))
        volumeLevel[0] = 1.0 - volumeLevel[0]  -- Инвертируем значение, так как координаты идут сверху вниз
    end

    -- Рассчитываем высоту заполнения в зависимости от уровня громкости
    local fillHeight = height * volumeLevel[0]
    local fillYStart = y + height - fillHeight

    -- Рисуем заполнение слайдера
    draw_list:AddRectFilled(ImGui.ImVec2(x, fillYStart), ImGui.ImVec2(x + width, y + height), sliderFilledColor, 4)
end


1713088125373.png

1713088138525.png



Lua:
local chargeLevel = 0.75 -- 75% заряда
drawBatteryIndicator(resX / 2, resY / 2, 100, 50, chargeLevel)


Lua:
function drawBatteryIndicator(x, y, width, height, chargeLevel)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()

    -- Определяем цвета в зависимости от уровня заряда
    local chargeColor
    if chargeLevel > 0.5 then
        chargeColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.8, 0.2, 1)) -- Зелёный
    elseif chargeLevel > 0.2 then
        chargeColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.8, 0.8, 0.2, 1)) -- Жёлтый
    else
        chargeColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.8, 0.2, 0.2, 1)) -- Красный
    end

    -- Рисуем контур батареи
    draw_list:AddRect(ImGui.ImVec2(x, y), ImGui.ImVec2(x + width, y + height), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)), 1.0, 0, 2)
    -- Рисуем "наконечник" батареи
    draw_list:AddRectFilled(ImGui.ImVec2(x + width, y + height * 0.3), ImGui.ImVec2(x + width + width * 0.05, y + height * 0.7), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)))
    -- Рисуем уровень заряда
    draw_list:AddRectFilled(ImGui.ImVec2(x + 2, y + 2), ImGui.ImVec2(x + 2 + (width - 4) * chargeLevel, y + height - 2), chargeColor)

    -- Опционально: добавляем текст с процентом заряда
    local text = string.format("%.0f%%", chargeLevel * 100)
    draw_list:AddText(ImGui.ImVec2(x + width / 2 - 10, y + height / 2 - 8), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)), text)
end


Grand Theft Auto  San Andreas 2024.04.14 - 12.51.27.04.gif


Lua:
local activityData = {
    { day = "Пн", value = 30 },
    { day = "Вт", value = 60 },
    { day = "Ср", value = 45 },
    { day = "Чт", value = 80 },
    { day = "Пт", value = 55 },
    { day = "Сб", value = 70 },
    { day = "Вс", value = 20 }
}
drawActivityGraph(resX / 2, resY / 2, 300, 100, activityData)


Lua:
function drawActivityGraph(x, y, width, height, activityData)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()

    -- Определяем цвета
    local bgColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.25, 0.3, 1))
    local barColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.7, 0.3, 1))
    local highlightColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.4, 0.9, 0.4, 1))

    -- Рисуем фон графика
    draw_list:AddRectFilled(ImGui.ImVec2(x, y), ImGui.ImVec2(x + width, y + height), bgColor, 4)

    local barWidth = width / #activityData
    for i, activity in ipairs(activityData) do
        local barHeight = (height * activity.value) / 100
        local barX = x + (i - 1) * barWidth
        local barY = y + height - barHeight

        -- Проверяем, находится ли курсор над столбцом
        local isHovered = ImGui.IsMouseHoveringRect(ImGui.ImVec2(barX, barY), ImGui.ImVec2(barX + barWidth, y + height))
        local color = isHovered and highlightColor or barColor

        -- Рисуем столбец гистограммы
        draw_list:AddRectFilled(ImGui.ImVec2(barX, barY), ImGui.ImVec2(barX + barWidth, y + height), color, 2)

        -- Если курсор над столбцом, отображаем подсказку с значением
        if isHovered then
            ImGui.BeginTooltip()
            ImGui.Text(string.format("%s: %.2f%%", activity.day, activity.value))
            ImGui.EndTooltip()
        end
    end
end
 

g305noobo

Известный
Модератор
307
477
Описание:
- get_current_function_name() возвращает название текущей функции, в которой вызвали
- get_caller_function_name() возвращает функцию, откуда вызвали функцию, в которой вызвана get_caller_function_name() 🤔

Код:
Lua:
function get_current_function_name()
    local info = debug.getinfo(2, "n")
    if info then return info.name or "unknown" end
    return "main"
end

function get_caller_function_name()
    local info = debug.getinfo(3, "n")
    if info then return info.name or "unknown" end
    return "main"
end

Способы применения:
Эти функции полезны в объёмных скриптах, чтобы вывод был более приятным и информативным

- get_current_function_name():
Lua:
function a()
    print("Сейчас я нахожусь в функции ", get_current_function_name())
    -- выведет "Сейчас я нахожусь в функции a"
end
- get_caller_function_name():
Lua:
function b()
    print("Меня вызвали из функции ", get_caller_function_name())
    -- выведет "Меня вызвали из функции caller"
end

function caller()
    b()
end
 

UBP

Известный
350
204
Описание:
- get_current_function_name() возвращает название текущей функции, в которой вызвали
- get_caller_function_name() возвращает функцию, откуда вызвали функцию, в которой вызвана get_caller_function_name() 🤔

Код:
Lua:
function get_current_function_name()
    local info = debug.getinfo(2, "n")
    if info then return info.name or "unknown" end
    return "main"
end

function get_caller_function_name()
    local info = debug.getinfo(3, "n")
    if info then return info.name or "unknown" end
    return "main"
end

Способы применения:
Эти функции полезны в объёмных скриптах, чтобы вывод был более приятным и информативным

- get_current_function_name():
Lua:
function a()
    print("Сейчас я нахожусь в функции ", get_current_function_name())
    -- выведет "Сейчас я нахожусь в функции a"
end
- get_caller_function_name():
Lua:
function b()
    print("Меня вызвали из функции ", get_caller_function_name())
    -- выведет "Меня вызвали из функции caller"
end

function caller()
    b()
end
nahui eto nado?
1713200574111.png


Lua:
drawAnimatedGradientProgressBar(resX / 2, resY / 2, 300, 15, 0.4)

Lua:
function drawAnimatedGradientProgressBar(x, y, width, height, progress)
    local ImGui = imgui
    local draw_list = ImGui.GetWindowDrawList()

    -- Определение цветов для градиента
    local startColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.4, 0.9, 0.4, 1)) -- Зеленый
    local endColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.9, 0.4, 0.4, 1)) -- Красный

    -- Рисуем фон прогресс-бара
    draw_list:AddRectFilled(ImGui.ImVec2(x, y), ImGui.ImVec2(x + width, y + height), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(0.2, 0.2, 0.2, 1)), 4)

    -- Рисуем градиентную заливку в зависимости от прогресса
    local filledWidth = width * progress
    draw_list:AddRectFilledMultiColor(
        ImGui.ImVec2(x, y),
        ImGui.ImVec2(x + filledWidth, y + height),
        startColor, endColor, endColor, startColor
    )

    -- Добавляем анимацию мерцания на переднем крае прогресс-бара
    local flickerWidth = 5 -- ширина мерцания
    local flickerX = x + filledWidth - flickerWidth / 2
    local time = os.clock()
    local flickerAlpha = 0.5 + 0.5 * math.sin(time * 10) -- анимация мерцания
    local flickerColor = ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, flickerAlpha))

    if progress > 0 and progress < 1 then
        draw_list:AddRectFilled(ImGui.ImVec2(flickerX, y), ImGui.ImVec2(flickerX + flickerWidth, y + height), flickerColor)
    end

    -- Текст с процентом заполнения
    local text = string.format("%.0f%%", progress * 100)
    local text_size = ImGui.CalcTextSize(text)
    draw_list:AddText(ImGui.ImVec2(x + (width - text_size.x) / 2, y + (height - text_size.y) / 2), ImGui.ColorConvertFloat4ToU32(ImGui.ImVec4(1, 1, 1, 1)), text)
end

1713201517812.png

только английские буквы
Lua:
function displayActiveOptionsWithColors(selectedIndices, options)
    if DisplayActiveOptions == false then return end
    imgui.BeginChild('ActiveOptionsColors', imgui.ImVec2(300, 500), true)
    for key, index in pairs(selectedIndices) do
        local optionValue = options[key][index]
        if optionValue ~= 'Off' then
            local text = (key)
            local textSize = imgui.CalcTextSize(text)
            local cursorPos = imgui.GetCursorScreenPos()
            local drawList = imgui.GetWindowDrawList()

            -- Добавляем текст поверх прямоугольника
            if enableTextGradient then
                -- Создаем переливающийся текст
                imgui.PushFont(Font[19])
                displayRainbowText(text, 0.5, 255, 0)
                imgui.PopFont()
            else
                -- Обычный белый текст
                drawList:AddText(cursorPos, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(1, 1, 1, 1)), text)
            end
            
            -- Сдвигаем курсор вниз для следующего элемента
            imgui.SetCursorPosY(imgui.GetCursorPosY() + textSize.y + 9)
        end
    end
    
    imgui.EndChild()
end
или более простой пример
Lua:
displayRainbowText(u8('Print'), 0.5, 255, 0)

Lua:
-- Функция для отображения переливающегося текста
function displayRainbowText(text, speed, alpha, offset)
    local drawList = imgui.GetWindowDrawList()
    local cursorPos = imgui.GetCursorScreenPos()
    
    for i = 1, #text do
        local char = text:sub(i, i)
        local charSize = imgui.CalcTextSize(char)
        
        -- Получаем цвет для текущей буквы
        local r, g, b = rainbow(speed, alpha, offset + i * 0.1) -- Смещаем цвет для каждой буквы
        local color = join_argb(alpha, r, g, b)
        
        -- Рисуем букву
        drawList:AddText(cursorPos, color, char)
        -- Сдвигаем позицию курсора для следующей буквы
        cursorPos.x = cursorPos.x + charSize.x
    end
end
function join_argb(a, r, g, b)
    local argb = b
    argb = bit.bor(argb, bit.lshift(g, 8))
    argb = bit.bor(argb, bit.lshift(r, 16))
    argb = bit.bor(argb, bit.lshift(a, 24))
    return argb
end

function rainbow(speed, alpha, offset) -- by rraggerr
    local clock = os.clock() + offset
    local r = math.floor(math.sin(clock * speed) * 127 + 128)
    local g = math.floor(math.sin(clock * speed + 2) * 127 + 128)
    local b = math.floor(math.sin(clock * speed + 4) * 127 + 128)
    return r,g,b,alpha
end
 

Gorskin

♥ Love Lua ♥
Проверенный
1,339
1,178
Описание: Узнаем инфу о процессоре, ОЗУ, и видеокарте.
Lua:
local ffi = require("ffi")

ffi.cdef[[
    typedef unsigned long DWORD;
    typedef unsigned long DWORD_PTR;
    typedef unsigned short WORD;
    typedef void *LPVOID;

    typedef struct _SYSTEM_INFO {
        union {
            DWORD  dwOemId;
            struct {
                WORD wProcessorArchitecture;
                WORD wReserved;
            };
        };
        DWORD     dwPageSize;
        LPVOID    lpMinimumApplicationAddress;
        LPVOID    lpMaximumApplicationAddress;
        DWORD_PTR dwActiveProcessorMask;
        DWORD     dwNumberOfProcessors;
        DWORD     dwProcessorType;
        DWORD     dwAllocationGranularity;
        WORD      wProcessorLevel;
        WORD      wProcessorRevision;
    } SYSTEM_INFO;

    void GetSystemInfo(SYSTEM_INFO *lpSystemInfo);
    typedef unsigned long DWORD_PTR;

    typedef struct _MEMORYSTATUSEX {
        DWORD dwLength;
        DWORD dwMemoryLoad;
        unsigned long long ullTotalPhys;
        unsigned long long ullAvailPhys;
        unsigned long long ullTotalPageFile;
        unsigned long long ullAvailPageFile;
        unsigned long long ullTotalVirtual;
        unsigned long long ullAvailVirtual;
        unsigned long long ullAvailExtendedVirtual;
    } MEMORYSTATUSEX;

    int GlobalMemoryStatusEx(MEMORYSTATUSEX* lpBuffer);

    typedef wchar_t WCHAR;

    typedef struct {
        DWORD cb;
        WCHAR DeviceName[32];
        WCHAR DeviceString[128];
        DWORD StateFlags;
        WCHAR DeviceID[128];
        WCHAR DeviceKey[128];
    } DISPLAY_DEVICEW;

    bool EnumDisplayDevicesW(const WCHAR*, DWORD, DISPLAY_DEVICEW*, DWORD);
]]

local mySystem_Info = {
    processor_Name = "",
}

-- Определяем название CPU
local function getProcessorName()
    local function getProcessorName_code(n)
        local qwords = ffi.typeof("uint64_t[?]")
        local dwords = ffi.typeof("uint32_t *")
        local cpuid_EAX_EDX = ffi.cast("__cdecl uint64_t (*)(uint32_t)", "\x53\x0F\xA2\x5B\xC3")
        local cpuid_EBX_ECX = ffi.cast("__cdecl uint64_t (*)(uint32_t)", "\x53\x0F\xA2\x91\x92\x93\x5B\xC3")
     
        local arr = ffi.cast(dwords, qwords(2, cpuid_EAX_EDX(n), cpuid_EBX_ECX(n)))
        return ffi.string(arr, 4), ffi.string(arr + 2, 4), ffi.string(arr + 3, 4), ffi.string(arr + 1, 4)
    end

    local s1 = ""
    for n = 0x80000002, 0x80000004 do
        local eax, ebx, ecx, edx = getProcessorName_code(n)
        s1 = s1..eax..ebx..ecx..edx
    end
    s1 = s1:gsub("^%s+", ""):gsub("%z+$", "")
    return s1
end

-- Определяем кол-во ядер CPU
local function getProcessorCores()
    local sysInfo = ffi.new("SYSTEM_INFO")
    ffi.C.GetSystemInfo(sysInfo)
    return tonumber(sysInfo.dwNumberOfProcessors)
end

-- Определяем кол-во ОЗУ
local function getSystemMemory()
    local memStatus = ffi.new("MEMORYSTATUSEX")
    memStatus.dwLength = ffi.sizeof("MEMORYSTATUSEX")
    ffi.C.GlobalMemoryStatusEx(memStatus)
    return tonumber(memStatus.ullTotalPhys)
end

-- Определяем доступную ОЗУ
local function getFreeMemory()
    local memStatus = ffi.new("MEMORYSTATUSEX")
    memStatus.dwLength = ffi.sizeof("MEMORYSTATUSEX")
    ffi.C.GlobalMemoryStatusEx(memStatus)
    return tonumber(memStatus.ullAvailPhys)
end

-- Преобразование wchar_t в строку Lua
local function wcharToString(wstr)
    local str = {}
    local i = 0
    while wstr[i] ~= 0 do
        str[i+1] = string.char(wstr[i])
        i = i + 1
    end
    return table.concat(str)
end

-- Получаем название графического адаптера
local function getGraphicsCardName()
    local user32 = ffi.load("user32")

    local iDevNum = 0
    local dd = ffi.new("DISPLAY_DEVICEW")
    dd.cb = ffi.sizeof(dd)
    dd.DeviceName = ffi.new("WCHAR[32]")
    dd.DeviceString = ffi.new("WCHAR[128]")
    dd.DeviceID = ffi.new("WCHAR[128]")
    dd.DeviceKey = ffi.new("WCHAR[128]")

    while user32.EnumDisplayDevicesW(nil, iDevNum, dd, 0) ~= 0 do
        if bit.band(dd.StateFlags, 0x00000001) ~= 0 then
            return wcharToString(dd.DeviceString)
        end
        iDevNum = iDevNum + 1
    end

    return nil
end

-- Получаем информацию о системе
function getSystemInfo()
    mySystem_Info.processor_Name = getProcessorName()
    mySystem_Info.processor_Cores = getProcessorCores()
    mySystem_Info.total_Memory = getSystemMemory() / (1024 * 1024 * 1024)
    mySystem_Info.free_Memory = getFreeMemory() / (1024 * 1024 * 1024)
    mySystem_Info.graphics_Card = getGraphicsCardName()
    return mySystem_Info
end

-- Выводим информацию о системе
function printSystemInfo()
    local info = getSystemInfo()
   
    sampfuncsLog("CPU: "..info.processor_Name)
    sampfuncsLog("Кол-во ядер: "..info.processor_Cores)
    sampfuncsLog("ОЗУ: "..string.format("%.2f GB", info.total_Memory))
    sampfuncsLog("Доступно ОЗУ: "..string.format("%.2f GB", info.free_Memory))
    if info.graphics_Card then
        sampfuncsLog("GPU: "..info.graphics_Card)
    end
end

-- Выводим информацию о системе
printSystemInfo()

Screenshot_2.png
 
Последнее редактирование:

Corenale

луашер типа
Проверенный
167
339
высру сюда че нють, мб кому пригодится...

Описание: получает (вроде как) реальные координаты камеры, отличается от getActiveCameraCoordinates()
если SA Memory:
samemory:
local samem = require("samemory")
function getRealCameraCoordinates()
    return samem.camera.vecGameCamPos.x, samem.camera.vecGameCamPos.y, samem.camera.vecGameCamPos.z
end
--ебитесь сами с этим кодом
если ффи (только пк):
ffi:
local ffi = require("ffi")
function getRealCameraCoordinates()
    local CCamera = ffi.cast("float*", 0xB6F028)
    return CCamera[0x20F], CCamera[0x210], CCamera[0x211]
end
--тут тоже ебитесь, хоть require в функу запихайте, мне похуй
а, ну еще эта хуйня будет быстрее, чем использование дефолтной муновской функи, около в 400 раз
 
Последнее редактирование:

Corenale

луашер типа
Проверенный
167
339
высер намбер 2

Описание: разрешает/запрещает смену оружия, отличается от setPlayerWeaponsScrollable() тем, что не багуется (дефолт функа иногда ломается и не дает изменять значение и скроллить вообще)
Код:
луа:
function setWeaponsScrollable(bool)
    ffi.copy(ffi.cast("void*", 0x60D8C6), bool and "\x0F\x84\xB0\x01\x00\x00" or "\xE9\xF3\x00\x00\x00\x90", 6)
end
 

ARMOR

011110000111100101101001
Модератор
4,969
6,890
Такой прогрессбар, идея спизжена с RDR2

Screen:
1715118653611.png
1715118756995.png


Code:
Lua:
function imgui.CircleProcessBar(dl, value, color, center, radius, num_segments)
    if value > 100.0 then
        value = 100.0;
    elseif value < 0.0 then
        value = 0.0;
    end
    local segment_rad = 2 * (value / 31.4) / num_segments;
    dl:AddCircleFilled(center, radius, 0xCC101010, num_segments);
    dl:AddCircle(center, radius, 0xFF757371, num_segments, 4);
    for i = 0, num_segments do
        local a = imgui.ImVec2(center.x - radius * math.sin(segment_rad * i),
        center.y - radius * math.cos(segment_rad * i));
        local b = imgui.ImVec2(center.x - radius * math.sin(segment_rad * (i + 1)),
        center.y - radius * math.cos(segment_rad * (i + 1)));
        dl:AddLine(a, b, color, 4);
    end
end

Пример исользования:
Lua:
-- В фрейме
local dl = imgui.GetBackgroundDrawList();
imgui.CircleProcessBar(dl, getCharHealth(playerPed), 0xFFFFFFFF, imgui.ImVec2(300, 300), 20, 100);
 

Rice.

Известный
Модератор
1,756
1,622
Описание: Спиздил Переписал превью картинок с Ozon
Пример использования:
Lua:
-- // Сори за такую реализацию
imgui.OnInitialize(function()
    imageLeft = {
        imgui.CreateTextureFromFile(u8(getWorkingDirectory() .. '/photo1.jpg')),
        imgui.CreateTextureFromFile(u8(getWorkingDirectory() .. '/photo2.jpg')),
        imgui.CreateTextureFromFile(u8(getWorkingDirectory() .. '/photo3.jpg')),
        imgui.CreateTextureFromFile(u8(getWorkingDirectory() .. '/photo4.jpg'))
    }

    imageRight = {
        imgui.CreateTextureFromFile(u8(getWorkingDirectory() .. '/photo5.jpg')),
        imgui.CreateTextureFromFile(u8(getWorkingDirectory() .. '/photo6.jpg'))
    }
end)

-- // Фрейм
imgui.SetCursorPos(imgui.ImVec2((imgui.GetWindowWidth() - 655) / 2, (imgui.GetWindowHeight() - 250) / 2))
imgui.SwitchableImages(imageLeft, imgui.ImVec2(400, 250), imgui.ImVec4(rainbow))
imgui.SameLine()
imgui.SwitchableImages(imageRight, imgui.ImVec2(250, 250), imgui.ImVec4(rainbow))
Код:
Lua:
function imgui.SwitchableImages(images, size, border)
    local dl = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()
    local cx, cy = getCursorPos()

    local colors = {
        ['ActiveCircle'] = imgui.ImVec4(0.00, 0.36, 1.00, 0.75),
        ['DefaultCircle'] = imgui.ImVec4(0.50, 0.50, 0.50, 0.75)
    }

    local countSections = #images
    local sizeSections = size.x / countSections
    local currentHovered = 0

    for i = 1, countSections do
        -- // Определяем на какой секции находится курсор
        -- // Мог бы сделать в одну строчку, но так более читабельнее
        if (cx >= p.x) and (cx <= (p.x + size.x)) and (cy >= p.y) and (cy <= (p.y + size.y)) then
            if ((cx >= (p.x + (i - 1) * sizeSections)) and (cx <= (p.x + sizeSections * i)) and (cy >= p.y) and (cy <= (p.y + size.y))) then
                currentHovered = i
            end
        else
            currentHovered = 1
        end
    end

    -- // Рисуем картинку
    dl:AddImageRounded(images[currentHovered], p, imgui.ImVec2(p.x + size.x, p.y + size.y), imgui.ImVec2(0, 0), imgui.ImVec2(1, 1), 0xFFFFFFFF, imgui.GetStyle().FrameRounding)

    for i = 1, countSections do
        -- // Рисуем круги под картинкой
        local pStart = imgui.ImVec2(p.x + (size.x + 10 - ((countSections * 10) + ((countSections - 1) * 5))) / 2 + (i - 1) * 15, p.y + size.y - 10)
        dl:AddCircleFilled(pStart, 5, imgui.GetColorU32Vec4((currentHovered == i and colors['ActiveCircle'] or colors['DefaultCircle'])), 50)
    end

    -- // Обводка
    if border then
        dl:AddRect(p, imgui.ImVec2(p.x + size.x, p.y + size.y), imgui.GetColorU32Vec4(border), imgui.GetStyle().FrameRounding)
    end

    -- // Занимаем область в фрейме
    imgui.Dummy(imgui.ImVec2(size.x, size.y))
end
 

Smeruxa

Известный
1,371
726
Описание: Аналог https://www.blast.hk/threads/10970/post-1498243 но на луа
Пример использования:
Lua:
local num = 5000000000
print(separateDigits(num))
Код:
Lua:
function separateDigits(number)
    local number = tonumber(number)
    local formattedNumber = tostring(math.abs(number))
    local separatedNumber = ""

    for i = 1, #formattedNumber do
        separatedNumber = separatedNumber .. formattedNumber:sub(i, i)
        if (#formattedNumber - i) % 3 == 0 and i ~= #formattedNumber then
            separatedNumber = separatedNumber .. "."
        end
    end

    if number < 0 then
        separatedNumber = "-" .. separatedNumber
    end

    return separatedNumber
end
 

Fott

Простреленный
3,461
2,378
Описание: Аналог https://www.blast.hk/threads/10970/post-1498243 но на луа
Пример использования:
Lua:
local num = 5000000000
print(separateDigits(num))
Код:
Lua:
function separateDigits(number)
    local number = tonumber(number)
    local formattedNumber = tostring(math.abs(number))
    local separatedNumber = ""

    for i = 1, #formattedNumber do
        separatedNumber = separatedNumber .. formattedNumber:sub(i, i)
        if (#formattedNumber - i) % 3 == 0 and i ~= #formattedNumber then
            separatedNumber = separatedNumber .. "."
        end
    end

    if number < 0 then
        separatedNumber = "-" .. separatedNumber
    end

    return separatedNumber
end
Lua:
tostring(num):reverse():gsub("(%d%d%d)", "%1 "):reverse()
 

ARMOR

011110000111100101101001
Модератор
4,969
6,890
Возвращает название транспорта по ID его модели. ( getNameOfVehicleModel() возвращает только 8 символов названия транспорта )

Lua:
local ffi = require("ffi")

ffi.cdef[[
    struct CKeyArray
    {
        int data;
        int size;
    };
    struct CData
    {
        int data;
        int size;
    };
    struct TablEntry
    {
        char name[8];
        int offset;
    };
    struct CText__Tabl
    {
        struct TablEntry data[200];
        int16_t size;
        int16_t __pad;
    };
    struct CText
    {
        struct CKeyArray tkeyMain;
        struct CData tdatMain;
        struct CKeyArray tkeyMission;
        struct CData tdatMission;
        char field_20;
        char haveTabl;
        char cderrorInitialized;
        char missionLoaded;
        char missionName[8];
        char cderrorText[256];
        struct CText__Tabl tabl;
    };
]]

function getVehicleName(nId)
    local CText__Get = ffi.cast("char*(__thiscall*)(struct CText*, char*)", 0x6A0050);
    local modelInfoPtr = ffi.cast("void**", 0xA9B0C8)[nId];
    local szGameText = ffi.cast("char*", ffi.cast("uint32_t", modelInfoPtr) + 0x32);
    local pText = ffi.cast("struct CText*", 0xC1B340)[0];
    local szName = CText__Get(pText, szGameText);
    return ffi.string(szName);
end

Пример использования:
Lua:
local nHandle = storeCarCharIsInNoSave(playerPed);
local nModelId = getCarModel(nHandle);
local szVehicleName = getVehicleName(nModelId);
sampAddChatMessage("Вы находитесь в транспорте: " .. szVehicleName, -1);

PS: Для других моделей, по типу скинов, объектов и т.д как я понял не получится такое сделать, ведь GTA хэширует названия моделей, и потом уже сравнивает хэш каждой модели на равенство, тем самым получая нужную ей модель для использования
 
Последнее редактирование:

fakelag46

Участник
21
20
Описание: открывает диалог сохранения/выбора файла
Код:
Lua:
local ffi = require('ffi');
local bit = require('bit');

ffi.cdef([[
    static const int OFN_FILEMUSTEXIST             = 0x1000;
    static const int OFN_NOCHANGEDIR               = 8;
    static const int OFN_PATHMUSTEXIST             = 0x800;

    typedef bool BOOL;
    typedef char CHAR;

    typedef unsigned short WORD;
    typedef unsigned long DWORD;

    typedef void *PVOID;
    typedef void *LPVOID;
    typedef void *LPOFNHOOKPROC;

    typedef unsigned long HANDLE;
    typedef HANDLE HWND;
    typedef HANDLE HINSTANCE;

    typedef const char *LPCSTR;
    typedef const char *LPCTSTR;

    typedef char *LPSTR;
    typedef char *LPTSTR;

    typedef unsigned long LPARAM;

    typedef struct {
        DWORD         lStructSize;
        HWND          hwndOwner;
        HINSTANCE     hInstance;
        LPCTSTR       lpstrFilter;
        LPTSTR        lpstrCustomFilter;
        DWORD         nMaxCustFilter;
        DWORD         nFilterIndex;
        LPTSTR        lpstrFile;
        DWORD         nMaxFile;
        LPTSTR        lpstrFileTitle;
        DWORD         nMaxFileTitle;
        LPCTSTR       lpstrInitialDir;
        LPCTSTR       lpstrTitle;
        DWORD         flags;
        WORD          nFileOffset;
        WORD          nFileExtension;
        LPCTSTR       lpstrDefExt;
        LPARAM        lCustData;
        LPOFNHOOKPROC lpfnHook;
        LPCTSTR       lpTemplateName;

        LPVOID        pvReserved;
        DWORD         dwReserved;
        DWORD         flagsEx;

    } OPENFILENAME;

    BOOL GetSaveFileNameA( OPENFILENAME *lpofn );
    BOOL GetOpenFileNameA( OPENFILENAME *lpofn );
    DWORD GetLastError(void);
]]);
local com = ffi.load("comdlg32");
local krnl = ffi.load("kernel32");

---@param saveDialog boolean true - save, false - open
---@param fileExtension string?
---@param defaultDir string?
---@return boolean status
---@return string result
function FileDialog(saveDialog, fileExtension, defaultDir)
    local Ofn = ffi.new("OPENFILENAME")
    ffi.fill(Ofn,ffi.sizeof(Ofn))
    local szFile = ffi.new("char[260]","\0");
    local hwnd = ffi.new("HWND",0);
    Ofn.lStructSize = ffi.sizeof(Ofn);
    Ofn.hwndOwner = hwnd;
    Ofn.lpstrFile = szFile;
    Ofn.nMaxFile = ffi.sizeof(szFile);
    Ofn.lpstrFilter = fileExtension;
    Ofn.nFilterIndex = 1;
    Ofn.lpstrFileTitle = nil;
    Ofn.nMaxFileTitle = 0;
    Ofn.lpstrInitialDir = defaultDir or getGameDirectory();
    Ofn.flags = bit.bor(com.OFN_PATHMUSTEXIST, com.OFN_FILEMUSTEXIST, com.OFN_NOCHANGEDIR);

    if (com[saveDialog and 'GetSaveFileNameA' or 'GetOpenFileNameA'](Ofn)) then
        return true, ffi.string(Ofn.lpstrFile, Ofn.nMaxFile);
    end
    return false, krnl.GetLastError();
end
Пример использования:
Lua:
local status, path = FileDialog(false, nil, getWorkingDirectory());
if (status) then
    sampAddChatMessage('Ты выбрал файл ' .. path, -1);
end
Посмотреть вложение 214983
Параметры:
saveDialog (boolean)тип диалогаtrue - открытие файла, false - сохранение
fileExtension (string | nil)фильтры файловуказатель на статический буфер, в котором находится пара ноль-терминированных(null-terminated) строк для определения шаблона пользователя. Первая строка описывает шаблон, вторая - сам шаблон. Первый раз, когда Ваше приложение создает диалоговое окно, вы определяет первую строку(не должна быть пустой). Когда пользователь выбирает файл, диалог копирует текущий шаблон фильтра во вторую строку. Этот шаблон может быть как одним из шаблонов, определенных в буфере lpstrFilter, так и может быть введен пользователем. Система использует эти строки для определения шаблона, указанного пользователем, в следующий раз, когда диалог будет вызван. Если параметр nFilterIndex равен нулю, то диалог использует пользовательский шаблон. Если этот параметр имеет значение NULL, то диалог не поддерживает использование пользовательского шаблона. Если значение этого параметра не равно NULL, то параметр nMaxCustFilter должен указывать размер буфера lpstrCustomFilter: для ANSI в байтах, а для Unicode - в символах.
defaultDir (string | nil)начальная директория
источник
Для тех у кого не работает (cannot convert 'number' to 'void *') вот исправленный код:
cdef code and fix function:
ffi.cdef([[
    static const int OFN_FILEMUSTEXIST             = 0x1000;
    static const int OFN_NOCHANGEDIR               = 8;
    static const int OFN_PATHMUSTEXIST             = 0x800;

    typedef bool BOOL;
    typedef char CHAR;

    typedef unsigned short WORD;
    typedef unsigned long DWORD;

    typedef void *PVOID;
    typedef void *LPVOID;
    typedef void *LPOFNHOOKPROC;

    typedef unsigned long HANDLE;
    typedef HANDLE HWND;
    typedef HANDLE HINSTANCE;

    typedef const char *LPCSTR;
    typedef const char *LPCTSTR;

    typedef char *LPSTR;
    typedef char *LPTSTR;

    typedef unsigned long LPARAM;

    typedef struct {
        DWORD         lStructSize;
        HWND          hwndOwner;
        HINSTANCE     hInstance;
        LPCTSTR       lpstrFilter;
        LPTSTR        lpstrCustomFilter;
        DWORD         nMaxCustFilter;
        DWORD         nFilterIndex;
        LPTSTR        lpstrFile;
        DWORD         nMaxFile;
        LPTSTR        lpstrFileTitle;
        DWORD         nMaxFileTitle;
        LPCTSTR       lpstrInitialDir;
        LPCTSTR       lpstrTitle;
        DWORD         flags;
        WORD          nFileOffset;
        WORD          nFileExtension;
        LPCTSTR       lpstrDefExt;
        LPARAM        lCustData;
        LPOFNHOOKPROC lpfnHook;
        LPCTSTR       lpTemplateName;

        LPVOID        pvReserved;
        DWORD         dwReserved;
        DWORD         flagsEx;

    } OPENFILENAME;

    BOOL GetSaveFileNameA( OPENFILENAME *lpofn );
    BOOL GetOpenFileNameA( OPENFILENAME *lpofn );
    DWORD GetLastError(void);
    typedef void* HWND;
]]);
local com = ffi.load("comdlg32");
local krnl = ffi.load("kernel32");
local hwnd = ffi.cast("HWND", 0)

---@param saveDialog boolean true - save, false - open
---@param fileExtension string?
---@param defaultDir string?
---@return boolean status
---@return string result
function FileDialog(saveDialog, fileExtension, defaultDir)
    local Ofn = ffi.new("OPENFILENAME")
    ffi.fill(Ofn, ffi.sizeof(Ofn))
    local szFile = ffi.new("char[260]", "\0")
    local hwnd = ffi.cast("HWND", 0) -- Use ffi.cast() to convert the number to a pointer

    Ofn.lStructSize = ffi.sizeof(Ofn)
    Ofn.hwndOwner = hwnd
    Ofn.lpstrFile = szFile
    Ofn.nMaxFile = ffi.sizeof(szFile)
    Ofn.lpstrFilter = fileExtension
    Ofn.nFilterIndex = 1
    Ofn.lpstrFileTitle = nil
    Ofn.nMaxFileTitle = 0
    Ofn.lpstrInitialDir = defaultDir or getGameDirectory()
    Ofn.flags = bit.bor(com.OFN_PATHMUSTEXIST, com.OFN_FILEMUSTEXIST, com.OFN_NOCHANGEDIR)

    if (saveDialog and com.GetSaveFileNameA or com.GetOpenFileNameA)(Ofn) then
        return true, ffi.string(Ofn.lpstrFile, Ofn.nMaxFile)
    end

    return false, krnl.GetLastError()
end
 
  • Нравится
Реакции: Winstаl

ARMOR

011110000111100101101001
Модератор
4,969
6,890
Описание: Убирает отключение смены одежды, мышц и жира в SAMP ( Калькор отключал их почему-то ).

Lua:
memory.setuint8(0x5A82C0, 0x56, true) -- Одежда
memory.setuint8(0x55A070, 0xD9, true) -- Статистика ( жир, мышцы )

Для тех кто не понял зачем это:
В MoonAPI есть функции givePlayerClothesOutsideShop, givePlayerClothes, но одежда не изменится если не использовать buildPlayerModel(), но в мультиплеере эта функция нопнута и не работает.