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


-- ChatHUD_kdm1eHvH.lua
-- Красивый чат в стиле kdm1eHvH

-- ============================================================
-- Скрываем стандартный чат GMod
-- ============================================================
hook.Add("HUDShouldDraw", "HideDefaultChat", function(name)
    if name == "CHudChat" then return false end
end)

-- ============================================================
-- Настройки
-- ============================================================
local MAX_MESSAGES   = 9       -- сколько сообщений показывать
local FADE_TIME      = 5       -- через сколько секунд исчезнет
local FADE_OUT       = 1       -- время плавного исчезновения
local LINE_HEIGHT    = 26      -- высота строки
local BOX_WIDTH      = 560     -- ширина чата
local MARGIN_X       = 20      -- отступ от левого края
local MARGIN_Y       = 20      -- отступ от низа

local ACCENT  = Color(220, 40, 40)
local BG      = Color(10, 10, 15, 220)
local BG_LINE = Color(20, 20, 28, 200)
local TEXT    = Color(235, 235, 235)

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

-- ============================================================
-- Шрифты
-- ============================================================
surface.CreateFont("chat_hud_text", {
    font = "Montserrat", size = 17, weight = 500, extended = true
})
surface.CreateFont("chat_hud_bold", {
    font = "Montserrat", size = 17, weight = 800, extended = true
})

-- ============================================================
-- Хранилище сообщений
-- ============================================================
local messages = {}       -- список последних сообщений
local lastMessageTime = 0 -- когда пришло последнее

-- ============================================================
-- Добавить сообщение
-- ============================================================
local function AddMessage(data)
    table.insert(messages, data)
    while #messages > MAX_MESSAGES do
        table.remove(messages, 1)
    end
    lastMessageTime = CurTime()
end

-- ============================================================
-- Перехват сообщений чата
-- ============================================================
-- От игроков (с префиксом ранга)
hook.Add("OnPlayerChat", "ChatHUD_kdm1eHvH_PlayerChat", function(ply, text, team, dead)
    if not IsValid(ply) then return end

    local rank = ply:GetNWString("kdm1e_Rank", "user")
    local rankData = RANK_LIST[rank] or RANK_LIST["user"]

    AddMessage({
        type = "player",
        nick = ply:Nick(),
        text = text,
        rankName = (rank ~= "user") and rankData.name or nil,
        rankColor = rankData.color,
        color = ply:GetPlayerColor() and Color(
            ply:GetPlayerColor().x * 255,
            ply:GetPlayerColor().y * 255,
            ply:GetPlayerColor().z * 255
        ) or Color(200, 200, 200)
    })

    return true -- блокируем стандартный чат
end)

-- Системные уведомления (PrintMessage в чат)
hook.Add("PlayerBindPress", "ChatHUD_kdm1eHvH_Focus", function(ply, bind, pressed)
    -- не трогаем
end)

-- ============================================================
-- Отрисовка чата
-- ============================================================
local function DrawChat()
    if #messages == 0 then return end

    local now = CurTime()
    local timeSinceLast = now - lastMessageTime

    -- Если время вышло — не рисуем
    if timeSinceLast > FADE_TIME + FADE_OUT then
        messages = {}
        return
    end

    -- Прозрачность (fade)
    local alpha = 255
    if timeSinceLast > FADE_TIME then
        alpha = 255 * (1 - (timeSinceLast - FADE_TIME) / FADE_OUT)
    end

    local count = #messages
    local totalH = count * LINE_HEIGHT + 16
    local startY = ScrH() - MARGIN_Y - totalH
    local startX = MARGIN_X

    -- Фон всей панели
    surface.SetDrawColor(BG.r, BG.g, BG.b, BG.a * (alpha / 255))
    surface.DrawRect(startX, startY, BOX_WIDTH, totalH)

    -- Красная полоса слева
    surface.SetDrawColor(ACCENT.r, ACCENT.g, ACCENT.b, alpha)
    surface.DrawRect(startX, startY, 3, totalH)

    -- Сообщения
    for i, msg in ipairs(messages) do
        local y = startY + 8 + (i - 1) * LINE_HEIGHT

        local textColor = Color(TEXT.r, TEXT.g, TEXT.b, alpha)

        if msg.type == "player" then
            -- Префикс ранга
            local x = startX + 14

            if msg.rankName then
                local prefix = "[" .. msg.rankName .. "] "
                local prefixColor = Color(msg.rankColor.r, msg.rankColor.g, msg.rankColor.b, alpha)
                surface.SetFont("chat_hud_bold")
                draw.SimpleText(prefix, "chat_hud_bold", x, y, prefixColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
                x = x + surface.GetTextSize(prefix)
            end

            -- Ник
            local nickColor = Color(msg.color.r, msg.color.g, msg.color.b, alpha)
            local nickText = msg.nick .. ": "
            surface.SetFont("chat_hud_bold")
            draw.SimpleText(nickText, "chat_hud_bold", x, y, nickColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
            x = x + surface.GetTextSize(nickText)

            -- Сообщение
            surface.SetFont("chat_hud_text")
            draw.SimpleText(msg.text, "chat_hud_text", x, y, textColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)

        else
            -- Системное уведомление
            local x = startX + 14
            surface.SetFont("chat_hud_bold")
            draw.SimpleText("[!] ", "chat_hud_bold", x, y, ACCENT, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
            x = x + surface.GetTextSize("[!] ")

            surface.SetFont("chat_hud_text")
            draw.SimpleText(msg.text, "chat_hud_text", x, y, textColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
        end
    end
end

hook.Add("HUDPaint", "ChatHUD_kdm1eHvH_Draw", DrawChat)

-- ============================================================
-- Уведомления (от сервера через PrintMessage)
-- ============================================================
-- Перехватываем chat.AddText и PrintMessage
local oldChatAddText = chat.AddText
chat.AddText = function(...)
    local args = { ... }
    local textParts = {}

    for _, arg in ipairs(args) do
        if isstring(arg) then
            table.insert(textParts, arg)
        end
    end

    local fullText = table.concat(textParts, "")
    if fullText ~= "" then
        AddMessage({ type = "system", text = fullText })
    end

    return oldChatAddText(...)
end

-- Стандартный PrintMessage тоже перехватываем
local oldPrintMessage = PrintMessage
PrintMessage = function(...)
    local args = { ... }
    local textParts = {}

    for _, arg in ipairs(args) do
        if isstring(arg) then
            table.insert(textParts, arg)
        end
    end

    local fullText = table.concat(textParts, "")
    if fullText ~= "" and not string.find(fullText, "^ServerLog") and not string.find(fullText, "^%[FAdmin%]") then
        AddMessage({ type = "system", text = fullText })
    end

    return oldPrintMessage(...)
end

-- ============================================================
-- Показываем свой чат при открытии (клавиша Y или T)
-- ============================================================
hook.Add("Think", "ChatHUD_kdm1eHvH_Keyboard", function()
    if gui.IsGameUIVisible() then return end
    if input.IsKeyDown(KEY_Y) or input.IsKeyDown(KEY_T) then
        -- если открыт чат — продлеваем таймер
        if #messages > 0 then
            lastMessageTime = CurTime()
        end
    end
end)

print("[ChatHUD] Кастомный чат загружен")