This commit is contained in:
2026-03-31 23:24:49 +03:00
parent 3f0319016c
commit 09c209c99d
2 changed files with 270 additions and 3 deletions

View File

@@ -7,6 +7,8 @@ surface.CreateFont("ixAdminShopDesc", { font = "Montserrat", size = 14, weight =
surface.CreateFont("ixAdminShopPrice", { font = "Montserrat", size = 18, weight = 900, antialias = true }) surface.CreateFont("ixAdminShopPrice", { font = "Montserrat", size = 18, weight = 900, antialias = true })
surface.CreateFont("ixAdminShopSmall", { font = "Montserrat", size = 14, weight = 600, antialias = true }) surface.CreateFont("ixAdminShopSmall", { font = "Montserrat", size = 14, weight = 600, antialias = true })
surface.CreateFont("ixAdminShopBold", { font = "Montserrat", size = 16, weight = 800, antialias = true }) surface.CreateFont("ixAdminShopBold", { font = "Montserrat", size = 16, weight = 800, antialias = true })
surface.CreateFont("ixAdminShopTableHeader", { font = "Montserrat", size = 15, weight = 800, antialias = true })
surface.CreateFont("ixAdminShopTableCell", { font = "Montserrat", size = 14, weight = 500, antialias = true })
-- Modern Color Palette #00431c -- Modern Color Palette #00431c
local COLOR_BASE = Color(0, 67, 28) local COLOR_BASE = Color(0, 67, 28)
@@ -37,7 +39,7 @@ function PLUGIN:WrapText(text, width, font)
end end
end end
if currentLine != "" then if currentLine ~= "" then
table.insert(lines, currentLine) table.insert(lines, currentLine)
end end
@@ -117,6 +119,10 @@ function PANEL:Init()
CreateNavBtn("Магазин", "shop", 0, COLOR_BASE) CreateNavBtn("Магазин", "shop", 0, COLOR_BASE)
if LocalPlayer():IsSuperAdmin() then
CreateNavBtn("Панель", "panel", 160, Color(120, 0, 180))
end
self.content = self:Add("DScrollPanel") self.content = self:Add("DScrollPanel")
self.content:Dock(FILL) self.content:Dock(FILL)
self.content:DockMargin(40, 100, 40, 40) self.content:DockMargin(40, 100, 40, 40)
@@ -137,7 +143,7 @@ end
function PANEL:Refresh() function PANEL:Refresh()
self.content:Clear() self.content:Clear()
if (self.currentView == "shop") then if self.currentView == "shop" then
local layout = self.content:Add("DIconLayout") local layout = self.content:Add("DIconLayout")
layout:Dock(TOP) layout:Dock(TOP)
layout:SetSpaceX(20) layout:SetSpaceX(20)
@@ -156,7 +162,7 @@ function PANEL:Refresh()
local descLines = PLUGIN:WrapText(item.desc, w - 30, "ixAdminShopDesc") local descLines = PLUGIN:WrapText(item.desc, w - 30, "ixAdminShopDesc")
for i, line in ipairs(descLines) do for i, line in ipairs(descLines) do
if (i > 4) then break end if i > 4 then break end
draw.SimpleText(line, "ixAdminShopDesc", w/2, 185 + (i-1)*18, COLOR_TEXT_DIM, TEXT_ALIGN_CENTER) draw.SimpleText(line, "ixAdminShopDesc", w/2, 185 + (i-1)*18, COLOR_TEXT_DIM, TEXT_ALIGN_CENTER)
end end
end end
@@ -186,11 +192,165 @@ function PANEL:Refresh()
net.SendToServer() net.SendToServer()
end end
end end
elseif self.currentView == "panel" then
-- Запрос данных с сервера
net.Start("ixAdminShopPanelOpen")
net.SendToServer()
-- Заголовок панели
local headerPanel = self.content:Add("DPanel")
headerPanel:Dock(TOP)
headerPanel:SetTall(50)
headerPanel.Paint = function(s, w, h)
draw.SimpleText("Управление очками администраторов", "ixAdminShopBold", 10, h/2, COLOR_TEXT, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
-- Таблица
self.panelTable = self.content:Add("DListView")
self.panelTable:Dock(TOP)
self.panelTable:SetTall(400)
self.panelTable:DockMargin(0, 10, 0, 10)
self.panelTable:SetMultiSelect(false)
self.panelTable.Paint = function(s, w, h)
draw.RoundedBox(6, 0, 0, w, h, COLOR_CARD)
end
local col1 = self.panelTable:AddColumn("Игрок")
local col2 = self.panelTable:AddColumn("SteamID")
local col3 = self.panelTable:AddColumn("Ранг")
local col4 = self.panelTable:AddColumn("Очки")
col1:SetWidth(160)
col2:SetWidth(140)
col3:SetWidth(100)
col4:SetWidth(80)
-- Настройка заголовков таблицы
for _, col in ipairs(self.panelTable.Columns) do
col.Header:SetFont("ixAdminShopTableHeader")
col.Header:SetTextColor(COLOR_TEXT)
col.Header.Paint = function(s, w, h)
draw.RoundedBox(0, 0, 0, w, h, COLOR_BASE)
end
end
-- Панель управления
local controlPanel = self.content:Add("DPanel")
controlPanel:Dock(TOP)
controlPanel:SetTall(120)
controlPanel.Paint = function(s, w, h)
draw.RoundedBox(6, 0, 0, w, h, COLOR_CARD)
end
local selectedSID = nil
-- Поле ввода количества очков
local amountEntry = controlPanel:Add("DTextEntry")
amountEntry:SetSize(200, 40)
amountEntry:SetPos(10, 10)
amountEntry:SetPlaceholderText("Количество очков...")
amountEntry:SetNumeric(true)
amountEntry:SetFont("ixAdminShopBold")
-- Кнопка выдачи очков
local giveBtn = controlPanel:Add("DButton")
giveBtn:SetSize(180, 40)
giveBtn:SetPos(220, 10)
giveBtn:SetText("Выдать очки")
giveBtn:SetFont("ixAdminShopBold")
giveBtn:SetTextColor(COLOR_TEXT)
giveBtn.Paint = function(s, w, h)
draw.RoundedBox(6, 0, 0, w, h, s:IsHovered() and Color(0, 180, 80) or COLOR_ACCENT)
end
giveBtn.DoClick = function()
if not selectedSID then
surface.PlaySound("buttons/button10.wav")
return
end
local amount = tonumber(amountEntry:GetValue()) or 0
if amount < 1 then
surface.PlaySound("buttons/button10.wav")
return
end
surface.PlaySound("ui/buttonclick.wav")
net.Start("ixAdminShopPanelGivePoints")
net.WriteString(selectedSID)
net.WriteUInt(amount, 32)
net.SendToServer()
amountEntry:SetValue("")
end
-- Кнопка забирания очков
local takeBtn = controlPanel:Add("DButton")
takeBtn:SetSize(180, 40)
takeBtn:SetPos(410, 10)
takeBtn:SetText("Забрать очки")
takeBtn:SetFont("ixAdminShopBold")
takeBtn:SetTextColor(COLOR_TEXT)
takeBtn.Paint = function(s, w, h)
draw.RoundedBox(6, 0, 0, w, h, s:IsHovered() and Color(230, 60, 60) or COLOR_DANGER)
end
takeBtn.DoClick = function()
if not selectedSID then
surface.PlaySound("buttons/button10.wav")
return
end
local amount = tonumber(amountEntry:GetValue()) or 0
if amount < 1 then
surface.PlaySound("buttons/button10.wav")
return
end
surface.PlaySound("ui/buttonclick.wav")
net.Start("ixAdminShopPanelTakePoints")
net.WriteString(selectedSID)
net.WriteUInt(amount, 32)
net.SendToServer()
amountEntry:SetValue("")
end
-- Информация о выбранном игроке
local infoLabel = controlPanel:Add("DLabel")
infoLabel:SetSize(400, 30)
infoLabel:SetPos(10, 55)
infoLabel:SetFont("ixAdminShopSmall")
infoLabel:SetTextColor(COLOR_TEXT_DIM)
infoLabel:SetText("Выберите игрока из таблицы")
-- Подсказка
local hintLabel = controlPanel:Add("DLabel")
hintLabel:SetSize(500, 25)
hintLabel:SetPos(10, 85)
hintLabel:SetFont("ixAdminShopSmall")
hintLabel:SetTextColor(COLOR_WARN)
hintLabel:SetText("Вводите только положительные числа. Нажмите строку в таблице для выбора.")
-- Обработчик выбора строки
self.panelTable.OnRowSelected = function(tbl, rowIndex, row)
local data = self.panelPlayers and self.panelPlayers[rowIndex]
if data then
selectedSID = data.steamID
infoLabel:SetText("Выбран: " .. data.name .. " (" .. data.steamID .. ") — Очков: " .. data.points)
end
end
end end
end end
vgui.Register("ixAdminShop", PANEL, "DFrame") vgui.Register("ixAdminShop", PANEL, "DFrame")
net.Receive("ixAdminShopPanelData", function()
local data = net.ReadTable()
if IsValid(ixAdminShop) and ixAdminShop.panelTable then
ixAdminShop.panelTable:Clear()
ixAdminShop.panelPlayers = {}
for i, plyData in ipairs(data) do
ixAdminShop.panelTable:AddLine(plyData.name, plyData.steamID, plyData.rank, plyData.points)
ixAdminShop.panelPlayers[i] = plyData
end
end
end)
net.Receive("ixAdminShopOpen", function() net.Receive("ixAdminShopOpen", function()
if (IsValid(ixAdminShop)) then if (IsValid(ixAdminShop)) then
ixAdminShop:Close() ixAdminShop:Close()

View File

@@ -5,6 +5,10 @@ util.AddNetworkString("ixAdminShopBuy")
util.AddNetworkString("ixAdminShopRetrieve") util.AddNetworkString("ixAdminShopRetrieve")
util.AddNetworkString("ixAdminShopAdminSync") util.AddNetworkString("ixAdminShopAdminSync")
util.AddNetworkString("ixAdminShopAdminAction") util.AddNetworkString("ixAdminShopAdminAction")
util.AddNetworkString("ixAdminShopPanelOpen")
util.AddNetworkString("ixAdminShopPanelData")
util.AddNetworkString("ixAdminShopPanelGivePoints")
util.AddNetworkString("ixAdminShopPanelTakePoints")
function PLUGIN:Initialize() function PLUGIN:Initialize()
self.shopData = ix.data.Get("adminShop", {}) self.shopData = ix.data.Get("adminShop", {})
@@ -182,3 +186,106 @@ local function IsAdminRank(rank)
return false return false
end end
PLUGIN.IsAdminRank = IsAdminRank
-- Сбор данных игроков с доступом к магазину
function PLUGIN:CollectPanelData()
local playersData = {}
for _, ply in ipairs(player.GetAll()) do
local rank = ply:GetUserGroup()
if IsAdminRank(rank) then
table.insert(playersData, {
name = ply:Nick(),
steamID = ply:SteamID(),
rank = rank,
points = ply:GetAdminPoints()
})
end
end
return playersData
end
-- Открытие панели (только superadmin)
net.Receive("ixAdminShopPanelOpen", function(len, client)
if not client:IsSuperAdmin() then
client:Notify("Доступ к панели только у суперадминистраторов!")
return
end
local data = PLUGIN:CollectPanelData()
net.Start("ixAdminShopPanelData")
net.WriteTable(data)
net.Send(client)
end)
-- Выдача очков (только superadmin)
net.Receive("ixAdminShopPanelGivePoints", function(len, client)
if not client:IsSuperAdmin() then
client:Notify("Доступ только у суперадминистраторов!")
return
end
local targetSID = net.ReadString()
local amount = net.ReadUInt(32)
local target = player.GetBySteamID(targetSID)
if not IsValid(target) then
client:Notify("Игрок не найден на сервере!")
return
end
if amount < 1 then
client:Notify("Некорректная сумма!")
return
end
target:GiveAdminPoints(amount)
client:Notify("Выдано " .. amount .. " очков игроку " .. target:Nick())
-- Обновить панель
local data = PLUGIN:CollectPanelData()
net.Start("ixAdminShopPanelData")
net.WriteTable(data)
net.Send(client)
end)
-- Забрать очки (только superadmin)
net.Receive("ixAdminShopPanelTakePoints", function(len, client)
if not client:IsSuperAdmin() then
client:Notify("Доступ только у суперадминистраторов!")
return
end
local targetSID = net.ReadString()
local amount = net.ReadUInt(32)
local target = player.GetBySteamID(targetSID)
if not IsValid(target) then
client:Notify("Игрок не найден на сервере!")
return
end
if amount < 1 then
client:Notify("Некорректная сумма!")
return
end
local current = target:GetAdminPoints()
if current < amount then
client:Notify("У игрока недостаточно очков! (Текущий баланс: " .. current .. ")")
return
end
target:TakeAdminPoints(amount)
client:Notify("Забрано " .. amount .. " очков у игрока " .. target:Nick())
-- Обновить панель
local data = PLUGIN:CollectPanelData()
net.Start("ixAdminShopPanelData")
net.WriteTable(data)
net.Send(client)
end)