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

chapo

tg/inst: @moujeek
Всефорумный модератор
9,190
12,511
Описание: Диаграмма в виде полосочки
Пример использования:
1761736992925.png

Lua:
local players = {};
local colorsNames = {
    [-1] = u8'Неизвестно',
    [368966908] = u8'Без организации',
    [2566951719] = u8'Grove Street',
    [2580667164] = u8'Los Santos Vagos',
    [2580283596] = u8'East Side Ballas',
    [2566979554] = u8'Varrios Los Aztecas',
    [2573625087] = u8'The Rifa',
    [2157523814] = u8'La Cosa Nostra',
    [2159694877] = u8'Warlock MC',
    [23486046] = u8'Night Wolves',
    [2150852249] = u8'Russian Mafia',
    [2157314562] = u8'Yakuza',
    [2160918272] = u8'Правительство',
    [2152104628] = u8'Страховая компания',
    [2150206647] = u8'Банк',
    [2164221491] = u8'Инструктор',
    [2164227710] = u8'Больница',
    [2157536819] = u8'Армия/ТСР',
    [2164228096] = u8'TV студия',
    [2164212992] = u8'Пожарный',
    [2147502591] = u8'Полиция'
};

local function getPlayersColorsStatistics()
    local function explodeArgb(argb)
        local a = bit.band(bit.rshift(argb, 24), 0xFF)
        local r = bit.band(bit.rshift(argb, 16), 0xFF)
        local g = bit.band(bit.rshift(argb, 8), 0xFF)
        local b = bit.band(argb, 0xFF)
        return a, r, g, b
    end
    local result, colors, totalPlayers = {}, {}, 0;
    for id = 0, 1003 do
        if (sampIsPlayerConnected(id)) then
            totalPlayers = totalPlayers + 1;
            local playerColor = sampGetPlayerColor(id);
            local key = colorsNames[playerColor] and playerColor or -1;
            colors[key] = (colors[key] or 0) + 1;
        end
    end
    for color, playersCount in pairs(colors) do
        local a, r, g, b = explodeArgb(color);
        table.insert(result, {
            label = colorsNames[color] or u8'Неизвестно',
            color = imgui.ImVec4(r / 255, g / 255, b / 255, 1),
            precent = (playersCount / totalPlayers) * 100
        });
    end
    return result;
end

-- Frame
imgui.Text(u8'Игроки в организциях');
imgui.PushStyleColor(imgui.Col.ChildBg, imgui.ImVec4(1, 1, 1, 0.1));
imgui.DiagramBar(
    imgui.GetWindowWidth() - 20,
    10,
    players,
    true
);
imgui.PopStyleColor();
if (imgui.Button('Update')) then
    players = getPlayersColorsStatistics();
end
Код:
Lua:
---@param width number
---@param barHeight number
---@param bars {label: string, precent: number, color: ImVec4}[]
---@param drawLabels boolean
function imgui.DiagramBar(width, barHeight, bars, drawLabels)
    local style = imgui.GetStyle();
    local dl = imgui.GetWindowDrawList();
    local barPos = imgui.GetCursorScreenPos();
    local barSize = imgui.ImVec2(width, barHeight);

    imgui.Dummy(barSize);
    dl:AddRectFilled(barPos, barPos + barSize, imgui.GetColorU32(imgui.Col.FrameBg), style.FrameRounding);

    local currentPrecent, onePrecentSize = 0, width / 100;
    for index, bar in ipairs(bars) do
        local startPos = barPos + imgui.ImVec2(currentPrecent * onePrecentSize, 0);
        local endPos = barPos + imgui.ImVec2((currentPrecent + bar.precent) * onePrecentSize, barHeight);
        local roundingCorners = currentPrecent == 0 and 1 + 4 or (currentPrecent + bar.precent >= 100 and 2 + 8 or 0);
        dl:AddRectFilled(
            startPos,
            endPos,
            imgui.GetColorU32Vec4(bar.color),
            style.FrameRounding,
            roundingCorners
        );
        if (not imgui.IsAnyItemHovered() and imgui.IsMouseHoveringRect(startPos, endPos)) then
            dl:AddRect(startPos, endPos, imgui.GetColorU32(imgui.Col.Border), style.FrameRounding, roundingCorners, 2);
            imgui.BeginTooltip();
            imgui.TextColored(bar.color, ('%s - %d%%%%'):format(bar.label, bar.precent));
            imgui.EndTooltip();
        end
        if (drawLabels) then
            imgui.PushStyleColor(imgui.Col.Text, bar.color);
            imgui.Bullet();
            imgui.PopStyleColor();
            imgui.SameLine();
            local x = imgui.GetCursorPosX() + imgui.CalcTextSize(bar.label).x;
            imgui.Text(bar.label);

            local nextBar = bars[index + 1];
            if (nextBar) then
                local nextLabelSize = imgui.CalcTextSize(nextBar.label).x + 5 + style.ItemSpacing.x * 2;
                if (x + nextLabelSize < imgui.GetContentRegionMax().x - style.WindowPadding.x) then
                    imgui.SameLine();
                end
            end
        end
        currentPrecent = currentPrecent + bar.precent;
    end
end
 

PACKET->HASH

Участник
6
27
Описание: Голографический радар для отображения игроков в радиусе с анимированным сканированием и подсветкой ближайших целей.
Код:
Lua:
local imgui = require("mimgui")

local radarState = {
    currentTime = os.clock(),
    lastUpdateTime = os.clock(),
    rotationAngle = 0,
    sweepProgress = 0
}

local function createColor(red, green, blue, alpha)
    return imgui.ColorConvertFloat4ToU32(imgui.ImVec4(red, green, blue, alpha or 1.0))
end

local function worldToRadarCoordinates(centerX, centerY, radarSize, deltaX, deltaY, maximumRange, rotation)
    local angle = math.atan2(deltaY, deltaX) - rotation
    local normalizedDistance = math.sqrt(deltaX * deltaX + deltaY * deltaY) / maximumRange
    local radarDistance = normalizedDistance * (radarSize * 0.5)
    
    local positionX = centerX + math.cos(angle) * radarDistance
    local positionY = centerY + math.sin(angle) * radarDistance
    
    return positionX, positionY
end

local function drawSoftGlow(drawList, centerX, centerY, baseRadius, red, green, blue, alpha)
    for layer = 0, 2 do
        local currentRadius = baseRadius + layer * 1.5
        local layerAlpha = alpha * (0.6 - layer * 0.2)
        drawList:AddCircleFilled(
            imgui.ImVec2(centerX, centerY),
            currentRadius,
            createColor(red, green, blue, layerAlpha),
            32
        )
    end
end

---@param size number Размер радара в пикселях
---@param players table[] Список игроков {id, name, deltaX, deltaY, distance}
---@param range number Дальность сканирования в метрах
---@param opacity number Прозрачность от 0.0 до 1.0
---@param scale number Масштаб радара
function imgui.HolographicRadar(size, players, range, opacity, scale)
    local io = imgui.GetIO()
    local screenWidth = io.DisplaySize.x
    local screenHeight = io.DisplaySize.y

    local currentTime = os.clock()
    local deltaTime = currentTime - radarState.lastUpdateTime
    radarState.lastUpdateTime = currentTime
    
    radarState.rotationAngle = (radarState.rotationAngle + deltaTime * 0.35) % (math.pi * 2)
    radarState.sweepProgress = (radarState.sweepProgress + deltaTime * 0.85) % 1.0

    local drawList = imgui.GetBackgroundDrawList()
    local radarSize = size * (scale or 1.0)
    local radarCenterX = screenWidth - radarSize / 2 - 40
    local radarCenterY = screenHeight - radarSize / 2 - 40
    local currentOpacity = opacity or 0.95

    drawList:AddCircleFilled(
        imgui.ImVec2(radarCenterX, radarCenterY),
        radarSize / 2 + 12,
        createColor(0.02, 0.03, 0.05, 0.85 * currentOpacity),
        90
    )

    for ringIndex = 1, 3 do
        local ringRadius = (radarSize / 2) * (ringIndex / 3)
        local ringAlpha = 0.08 + (ringIndex * 0.03)
        drawList:AddCircle(
            imgui.ImVec2(radarCenterX, radarCenterY),
            ringRadius,
            createColor(0.1, 0.8, 1.0, ringAlpha * currentOpacity),
            90,
            1.6
        )
    end

    local currentAngle = radarState.rotationAngle
    for beamIndex = 0, 20 do
        local beamAngle = currentAngle + (beamIndex / 20) * 0.8
        local beamEndX = radarCenterX + math.cos(beamAngle) * (radarSize / 2)
        local beamEndY = radarCenterY + math.sin(beamAngle) * (radarSize / 2)
        local beamAlpha = 0.35 - (beamIndex * 0.015)
        
        drawList:AddLine(
            imgui.ImVec2(radarCenterX, radarCenterY),
            imgui.ImVec2(beamEndX, beamEndY),
            createColor(0.1, 0.9, 1.0, beamAlpha * currentOpacity),
            1.4
        )
    end

    local pulseRadius = (radarSize / 2) * radarState.sweepProgress
    local pulseAlpha = 0.25 * (1 - radarState.sweepProgress)
    drawList:AddCircle(
        imgui.ImVec2(radarCenterX, radarCenterY),
        pulseRadius,
        createColor(0.2, 0.9, 1.0, pulseAlpha * currentOpacity),
        80,
        2.5
    )

    local centerPulse = 0.8 + 0.2 * math.sin(currentTime * 3)
    drawList:AddCircleFilled(
        imgui.ImVec2(radarCenterX, radarCenterY),
        4 * centerPulse,
        createColor(0.9, 1.0, 1.0, 0.9 * currentOpacity),
        16
    )
    
    drawList:AddCircle(
        imgui.ImVec2(radarCenterX, radarCenterY),
        6 * centerPulse,
        createColor(0.1, 0.9, 1.0, 0.6 * currentOpacity),
        16,
        1.5
    )

    local nearestPlayerId = players[1] and players[1].id

    for _, player in ipairs(players) do
        local playerX, playerY = worldToRadarCoordinates(
            radarCenterX, radarCenterY, radarSize,
            player.deltaX, player.deltaY,
            range, radarState.rotationAngle
        )

        local glowIntensity = (player.id == nearestPlayerId) and 1.2 or 1.0
        drawSoftGlow(drawList, playerX, playerY, 3 * glowIntensity, 0.2, 0.9, 1.0, 0.7 * currentOpacity)

        drawList:AddCircleFilled(
            imgui.ImVec2(playerX, playerY),
            2.2 * glowIntensity,
            createColor(0.9, 1.0, 1.0, 1.0 * currentOpacity),
            22
        )

        local playerInfo = player.name .. " (" .. math.floor(player.distance) .. "m)"
        drawList:AddText(
            imgui.ImVec2(playerX + 6, playerY - 6),
            createColor(0.9, 1.0, 1.0, 0.95 * currentOpacity),
            playerInfo
        )
    end
end
Пример использования:
Lua:
local radarConfig = {
    isEnabled = imgui.new.bool(true),
    detectionRange = imgui.new.float(180.0),
    interfaceOpacity = imgui.new.float(0.95),
    displayScale = imgui.new.float(1.32)
}

local function getNearbyPlayers(range)
    local players = {}
    local playerX, playerY = getCharCoordinates(PLAYER_PED)
    
    for id = 0, sampGetMaxPlayerId(true) do
        local streamed, ped = sampGetCharHandleBySampPlayerId(id)
        if streamed and not sampIsPlayerPaused(id) and not isCharDead(ped) then
            local targetX, targetY = getCharCoordinates(ped)
            local deltaX = targetX - playerX
            local deltaY = targetY - playerY
            local distance = math.sqrt(deltaX * deltaX + deltaY * deltaY)
            
            if distance <= range then
                table.insert(players, {
                    id = id,
                    name = sampGetPlayerNickname(id),
                    deltaX = deltaX,
                    deltaY = deltaY,
                    distance = distance
                })
            end
        end
    end
    
    table.sort(players, function(a, b)
        return a.distance < b.distance
    end)
    
    return players
end

imgui.OnFrame(function() return radarConfig.isEnabled[0] end, function()
    local players = getNearbyPlayers(radarConfig.detectionRange[0])
    imgui.HolographicRadar(250, players, radarConfig.detectionRange[0], radarConfig.interfaceOpacity[0], radarConfig.displayScale[0])
end)
Как выглядит:
radar_demo.gif
 

kyrtion

Известный
1,280
473
for id = 0, sampGetMaxPlayerId(true) do
local streamed, ped = sampGetCharHandleBySampPlayerId(id)
if streamed and not sampIsPlayerPaused(id) and not isCharDead(ped) then
local targetX, targetY = getCharCoordinates(ped)
local deltaX = targetX - playerX
local deltaY = targetY - playerY
local distance = math.sqrt(deltaX * deltaX + deltaY * deltaY)

if distance <= range then
table.insert(players, {
id = id,
name = sampGetPlayerNickname(id),
deltaX = deltaX,
deltaY = deltaY,
distance = distance
})
end
end
end

table.sort(players, function(a, b)
return a.distance < b.distance
end
Сразу замечу. Для оптимизации достаточно проследить на получение синхронизация и вход/выход в стрим через SAMP.Lua
 
  • Нравится
Реакции: PACKET->HASH