Загрузка данных


-- Tab_kdm1eHvH.lua
-- Полный таб со всем: аватарки, ранги, пинг, убийства

-- ============================================================
-- Блокировка таба FAdmin / DarkRP
-- ============================================================
hook.Add("ScoreboardShow", "kdm1eHvH_BlockScoreboard", function() return true end)
hook.Add("ScoreboardHide", "kdm1eHvH_BlockScoreboard", function() return true end)

hook.Add("InitPostEntity", "kdm1eHvH_BlockGM", function()
    timer.Simple(3, function()
        if not GAMEMODE then return end
        GAMEMODE.ScoreboardShow  = function() end
        GAMEMODE.ScoreboardHide  = function() end
        GAMEMODE.ScoreboardPaint = function() end
        GAMEMODE.ScoreboardOpen  = function() end
        GAMEMODE.ScoreboardClose = function() end
    end)
end)

hook.Add("Think", "kdm1eHvH_HideVGUI", function()
    if not input.IsKeyDown(KEY_TAB) then return end
    for _, pnl in ipairs(vgui.GetAll()) do
        if not IsValid(pnl) then continue end
        local cls = string.lower(pnl:GetClassName() or "")
        if string.find(cls, "scoreboard") or string.find(cls, "playerlist") then
            pnl:SetVisible(false)
        end
    end
end)

-- ============================================================
-- Дубликат рангов для клиента
-- ============================================================
local RANK_LIST = {
    ["user"]         = { level = 0, color = Color(180, 180, 180), name = "User" },
    ["beta_tester"]  = { level = 1, color = Color(80, 220, 220),  name = "Beta Tester" },
    ["vip"]          = { level = 2, color = Color(255, 200, 50),  name = "VIP" },
    ["moderator"]    = { level = 3, color = Color(80, 150, 255),  name = "Moderator" },
    ["admin"]        = { level = 4, color = Color(255, 70, 70),   name = "Admin" },
    ["senior_admin"] = { level = 5, color = Color(200, 30, 30),   name = "Senior Admin" },
    ["manager"]      = { level = 6, color = Color(180, 80, 255),  name = "Manager" },
    ["superadmin"]   = { level = 7, color = Color(255, 130, 0),   name = "Superadmin" },
}

-- ============================================================
-- Настройки
-- ============================================================
local ACCENT = Color(220, 40, 40)
local TEXT   = Color(235, 235, 235)
local DIM    = Color(150, 150, 160)
local BG     = Color(10, 10, 15, 245)
local HEAD   = Color(35, 35, 48, 255)
local ROW    = Color(22, 22, 30, 220)
local ROW2   = Color(28, 28, 36, 220)

-- ============================================================
-- Шрифты
-- ============================================================
surface.CreateFont("tab_title",  { font = "Montserrat", size = 30, weight = 900, extended = true })
surface.CreateFont("tab_header", { font = "Montserrat", size = 15, weight = 700, extended = true })
surface.CreateFont("tab_nick",   { font = "Montserrat", size = 18, weight = 600, extended = true })
surface.CreateFont("tab_value",  { font = "Montserrat", size = 18, weight = 700, extended = true })
surface.CreateFont("tab_small",  { font = "Montserrat", size = 14, weight = 500, extended = true })

-- ============================================================
-- Утилиты
-- ============================================================
local function pingColor(ping)
    if ping < 60  then return Color(80, 220, 120) end
    if ping < 120 then return Color(240, 200, 60) end
    return Color(240, 80, 80)
end

local function getColorFromNick(nick)
    local hash = 0
    for i = 1, #nick do
        hash = (hash * 31 + string.byte(nick, i)) % 360
    end
    return HSVToColor(hash, 0.55, 0.75)
end

local function sortedPlayers()
    local tbl = {}
    for _, ply in ipairs(player.GetAll()) do
        if IsValid(ply) and not ply:IsBot() then
            table.insert(tbl, ply)
        end
    end
    table.sort(tbl, function(a, b)
        -- 1. По рангу (выше — выше)
        local ra = RANK_LIST[a:GetNWString("kdm1e_Rank", "user")] or RANK_LIST["user"]
        local rb = RANK_LIST[b:GetNWString("kdm1e_Rank", "user")] or RANK_LIST["user"]
        if ra.level ~= rb.level then return ra.level > rb.level end

        -- 2. По убийствам
        local ka = a:GetNWInt("PersistentKills", a:Frags())
        local kb = b:GetNWInt("PersistentKills", b:Frags())
        if ka ~= kb then return ka > kb end

        -- 3. По нику
        return a:Nick() < b:Nick()
    end)
    return tbl
end

local function drawAvatar(ply, x, y, size)
    local av = nil
    if ply.GetAvatar then
        pcall(function() av = ply:GetAvatar() end)
    end

    if av then
        surface.SetDrawColor(255, 255, 255)
        surface.SetMaterial(av)
        surface.DrawTexturedRect(x, y, size, size)
    else
        -- Красивая заглушка: цветной фон + первая буква
        local nick = ply:Nick() or "?"
        local color = getColorFromNick(nick)
        local letter = string.upper(string.sub(nick, 1, 1))

        surface.SetDrawColor(color.r, color.g, color.b, 255)
        surface.DrawRect(x, y, size, size)

        surface.SetDrawColor(0, 0, 0, 60)
        surface.DrawRect(x, y + size - 6, size, 6)
        surface.DrawRect(x + size - 6, y, 6, size)

        surface.SetFont("tab_nick")
        draw.SimpleText(letter, "tab_nick",
            x + size / 2, y + size / 2,
            Color(255, 255, 255),
            TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end

    surface.SetDrawColor(pingColor(ply:Ping()))
    surface.DrawOutlinedRect(x - 1, y - 1, size + 2, size + 2, 2)
end

-- ============================================================
-- Отрисовка таба
-- ============================================================
local function drawScoreboard()
    local players = sortedPlayers()
    local count = #players

    local panelW = math.min(860, ScrW() - 200)
    local rowH = 54
    local headH = 48
    local panelH = headH + math.max(1, count) * rowH + 30

    local x = (ScrW() - panelW) / 2
    local y = (ScrH() - panelH) / 2

    -- Заголовок kdm1eHvH
    surface.SetFont("tab_title")
    local t1, t2 = "kdm1e", "HvH"
    local w1 = surface.GetTextSize(t1)
    local w2 = surface.GetTextSize(t2)
    local totalW = w1 + w2
    draw.SimpleText(t1, "tab_title", x + panelW / 2 - totalW / 2,      y - 46, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
    draw.SimpleText(t2, "tab_title", x + panelW / 2 - totalW / 2 + w1, y - 46, ACCENT,      TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)

    -- Тень + фон
    surface.SetDrawColor(0, 0, 0, 200)
    surface.DrawRect(x + 5, y + 5, panelW, panelH)
    surface.SetDrawColor(BG)
    surface.DrawRect(x, y, panelW, panelH)

    -- Красная полоса сверху
    surface.SetDrawColor(ACCENT)
    surface.DrawRect(x, y, panelW, 4)

    -- Шапка
    surface.SetDrawColor(HEAD)
    surface.DrawRect(x, y + 4, panelW, headH)

    local colAvatar = x + 20
    local colNick   = x + 88
    local colKills  = x + panelW - 260
    local colPing   = x + panelW - 160
    local colID     = x + panelW - 70

    local hy = y + 4 + headH / 2
    draw.SimpleText("ИГРОК",    "tab_header", colNick,  hy, DIM, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
    draw.SimpleText("УБИЙСТВА", "tab_header", colKills, hy, DIM, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
    draw.SimpleText("ПИНГ",     "tab_header", colPing,  hy, DIM, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
    draw.SimpleText("ID",       "tab_header", colID,    hy, DIM, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)

    -- Строки
    local startY = y + 4 + headH
    for i = 1, count do
        local ply = players[i]
        local ry = startY + (i - 1) * rowH
        local isMe = (ply == LocalPlayer())

        surface.SetDrawColor(i % 2 == 1 and ROW or ROW2)
        surface.DrawRect(x, ry, panelW, rowH)

        if isMe then
            surface.SetDrawColor(ACCENT)
            surface.DrawRect(x, ry, 3, rowH)
        end

        surface.SetDrawColor(0, 0, 0, 100)
        surface.DrawRect(x, ry + rowH - 1, panelW, 1)

        local cy = ry + rowH / 2
        local avSize = rowH - 14
        drawAvatar(ply, colAvatar, ry + 7, avSize)

        -- ===== Ранг + ник =====
        local rank = ply:GetNWString("kdm1e_Rank", "user")
        local rankData = RANK_LIST[rank] or RANK_LIST["user"]

        local rankPrefix = ""
        if rank ~= "user" then
            rankPrefix = "[" .. rankData.name .. "] "
        end

        surface.SetFont("tab_nick")
        local rankW = surface.GetTextSize(rankPrefix)

        if rankW > 0 then
            draw.SimpleText(rankPrefix, "tab_nick", colNick, cy,
                rankData.color, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
        end

        draw.SimpleText(ply:Nick(), "tab_nick", colNick + rankW, cy,
            isMe and Color(255, 220, 220) or TEXT,
            TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)

        -- Убийства
        draw.SimpleText(tostring(ply:GetNWInt("PersistentKills", ply:Frags())),
            "tab_value", colKills, cy, ACCENT,
            TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)

        -- Пинг
        draw.SimpleText(ply:Ping() .. " ms", "tab_value", colPing, cy,
            pingColor(ply:Ping()), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)

        -- ID
        draw.SimpleText(tostring(ply:UserID()), "tab_small", colID, cy, DIM,
            TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
    end

    -- Футер
    local fy = y + panelH - 22
    draw.SimpleText("Игроков: " .. count, "tab_small", x + 20, fy, DIM, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
    draw.SimpleText(GetHostName() or "", "tab_small", x + panelW - 20, fy, DIM, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
end

-- ============================================================
-- Хуки
-- ============================================================
hook.Add("HUDPaint", "Tab_kdm1eHvH", function()
    if not input.IsKeyDown(KEY_TAB) then return end
    drawScoreboard()
end)

hook.Add("HUDShouldDraw", "Tab_kdm1eHvH_HideDefault", function(name)
    if name == "CHudPlayerList" then return false end
end)

print("[kdm1eHvH] Таб загружен с рангами!")