707 lines
30 KiB
Lua
707 lines
30 KiB
Lua
local PLUGIN = PLUGIN
|
||
|
||
local COLOR_BG_DARK = Color(3, 5, 4)
|
||
local COLOR_BG_MEDIUM = Color(8, 12, 10)
|
||
local COLOR_BG_LIGHT = Color(12, 18, 14)
|
||
local COLOR_PRIMARY = Color(27, 94, 32)
|
||
local COLOR_PRIMARY_DARK = Color(15, 60, 18)
|
||
local COLOR_ACCENT = Color(56, 102, 35)
|
||
local COLOR_TEXT_PRIMARY = Color(165, 214, 167)
|
||
local COLOR_TEXT_SECONDARY = Color(102, 187, 106)
|
||
local COLOR_DANGER = Color(136, 14, 14)
|
||
local COLOR_WARNING = Color(191, 130, 0)
|
||
local COLOR_BORDER = Color(15, 60, 18, 60)
|
||
|
||
if not draw.Circle then
|
||
function draw.Circle(x, y, radius, color)
|
||
local segmentCount = math.max(16, radius)
|
||
surface.SetDrawColor(color or color_white)
|
||
|
||
local circle = {}
|
||
for i = 0, segmentCount do
|
||
local angle = math.rad((i / segmentCount) * 360)
|
||
table.insert(circle, {
|
||
x = x + math.cos(angle) * radius,
|
||
y = y + math.sin(angle) * radius
|
||
})
|
||
end
|
||
surface.DrawPoly(circle)
|
||
end
|
||
end
|
||
|
||
if not surface.DrawCircle then
|
||
function surface.DrawCircle(x, y, radius, color)
|
||
draw.Circle(x, y, radius, color)
|
||
end
|
||
end
|
||
local COLOR_TEXT_SECONDARY = Color(174, 213, 129)
|
||
local COLOR_DANGER = Color(229, 57, 53)
|
||
local COLOR_WARNING = Color(255, 193, 7)
|
||
local COLOR_BORDER = Color(46, 125, 50, 100)
|
||
|
||
net.Receive("ixArsenalOpen", function()
|
||
local supply = net.ReadUInt(32)
|
||
local factionID = net.ReadUInt(8)
|
||
local weaponsData = net.ReadTable()
|
||
local weaponHas = net.ReadTable()
|
||
local armorData = net.ReadTable()
|
||
local freeRemain = net.ReadUInt(32)
|
||
|
||
if not weaponsData or type(weaponsData) ~= "table" then weaponsData = {} end
|
||
if not weaponHas or type(weaponHas) ~= "table" then weaponHas = {} end
|
||
|
||
if IsValid(PLUGIN.menu) then
|
||
PLUGIN.menu:Remove()
|
||
end
|
||
|
||
local scrW, scrH = ScrW(), ScrH()
|
||
local frame = vgui.Create("DFrame")
|
||
frame:SetSize(scrW, scrH)
|
||
frame:SetPos(0, 0)
|
||
frame:SetTitle("")
|
||
frame:SetDraggable(false)
|
||
frame:ShowCloseButton(false)
|
||
frame:MakePopup()
|
||
|
||
frame.Paint = function(s, w, h)
|
||
surface.SetDrawColor(COLOR_BG_DARK)
|
||
surface.DrawRect(0, 0, w, h)
|
||
|
||
local gradHeight = 300
|
||
for i = 0, gradHeight do
|
||
local alpha = (1 - i/gradHeight) * 40
|
||
surface.SetDrawColor(COLOR_PRIMARY.r, COLOR_PRIMARY.g, COLOR_PRIMARY.b, alpha)
|
||
surface.DrawRect(0, i, w, 1)
|
||
end
|
||
|
||
surface.SetDrawColor(COLOR_BG_MEDIUM)
|
||
surface.DrawRect(0, 0, w, 100)
|
||
|
||
surface.SetDrawColor(COLOR_PRIMARY)
|
||
surface.DrawRect(0, 100, w, 3)
|
||
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
for i = 0, w, 200 do
|
||
surface.DrawRect(i, 0, 1, 100)
|
||
end
|
||
|
||
draw.SimpleText("◆ ВОЕННЫЙ АРСЕНАЛ ◆", "ixMenuButtonFont", w/2, 35, COLOR_ACCENT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
draw.SimpleText("СИСТЕМА СНАБЖЕНИЯ", "ixSmallFont", w/2, 68, COLOR_TEXT_SECONDARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
end
|
||
|
||
local closeBtn = vgui.Create("DButton", frame)
|
||
closeBtn:SetText("")
|
||
closeBtn:SetSize(42, 42)
|
||
closeBtn:SetPos(scrW - 60, 18)
|
||
closeBtn.Paint = function(s, w, h)
|
||
local col = s:IsHovered() and COLOR_DANGER or Color(COLOR_DANGER.r * 0.7, COLOR_DANGER.g * 0.7, COLOR_DANGER.b * 0.7)
|
||
|
||
draw.RoundedBox(4, 0, 0, w, h, col)
|
||
|
||
surface.SetDrawColor(COLOR_BG_DARK)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
|
||
surface.SetDrawColor(COLOR_TEXT_PRIMARY)
|
||
surface.DrawLine(w*0.3, h*0.3, w*0.7, h*0.7)
|
||
surface.DrawLine(w*0.7, h*0.3, w*0.3, h*0.7)
|
||
|
||
if s:IsHovered() then
|
||
surface.SetDrawColor(255, 255, 255, 30)
|
||
draw.RoundedBox(4, 0, 0, w, h, Color(255, 255, 255, 30))
|
||
end
|
||
end
|
||
closeBtn.DoClick = function() frame:Close() end
|
||
|
||
local infoPanel = vgui.Create("DPanel", frame)
|
||
infoPanel:SetSize(scrW - 80, 70)
|
||
infoPanel:SetPos(40, 115)
|
||
infoPanel.Paint = function(s, w, h)
|
||
draw.RoundedBox(8, 0, 0, w, h, COLOR_BG_LIGHT)
|
||
surface.SetDrawColor(COLOR_PRIMARY)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
end
|
||
|
||
local supplyBox = vgui.Create("DPanel", infoPanel)
|
||
supplyBox:SetSize(infoPanel:GetWide() / 2 - 10, infoPanel:GetTall())
|
||
supplyBox:SetPos(5, 0)
|
||
supplyBox.Paint = function(s, w, h)
|
||
draw.SimpleText("ОЧКИ СНАБЖЕНИЯ", "ixSmallFont", 20, 12, COLOR_TEXT_SECONDARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||
draw.SimpleText(tostring(supply), "ixMenuButtonFont", 20, 32, COLOR_ACCENT, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||
|
||
surface.SetDrawColor(COLOR_PRIMARY)
|
||
draw.NoTexture()
|
||
surface.DrawCircle(w - 35, h/2, 12, COLOR_PRIMARY)
|
||
end
|
||
|
||
local currencySymbol = "$"
|
||
if PLUGIN and PLUGIN.config and PLUGIN.config.currencySymbol and factionID then
|
||
currencySymbol = PLUGIN.config.currencySymbol[factionID] or currencySymbol
|
||
end
|
||
|
||
local function formatTime(seconds)
|
||
seconds = math.max(0, tonumber(seconds) or 0)
|
||
if seconds <= 0 then return "Готово" end
|
||
local h = math.floor(seconds / 3600)
|
||
local m = math.floor((seconds % 3600) / 60)
|
||
local s = seconds % 60
|
||
if h > 0 then
|
||
return string.format("%02d:%02d:%02d", h, m, s)
|
||
else
|
||
return string.format("%02d:%02d", m, s)
|
||
end
|
||
end
|
||
|
||
local cooldownBox = vgui.Create("DPanel", infoPanel)
|
||
cooldownBox:SetSize(infoPanel:GetWide() / 2 - 10, infoPanel:GetTall())
|
||
cooldownBox:SetPos(infoPanel:GetWide() / 2 + 5, 0)
|
||
cooldownBox.Paint = function(s, w, h)
|
||
draw.SimpleText("БЕСПЛАТНОЕ СНАРЯЖЕНИЕ", "ixSmallFont", 20, 12, COLOR_TEXT_SECONDARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||
|
||
local timeText = formatTime(freeRemain)
|
||
local timeColor = freeRemain <= 0 and COLOR_PRIMARY or COLOR_WARNING
|
||
draw.SimpleText(timeText, "ixMenuButtonFont", 20, 32, timeColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||
|
||
if freeRemain > 0 then
|
||
surface.SetDrawColor(COLOR_WARNING)
|
||
draw.NoTexture()
|
||
surface.DrawCircle(w - 35, h/2, 12, COLOR_WARNING)
|
||
else
|
||
surface.SetDrawColor(COLOR_PRIMARY)
|
||
draw.NoTexture()
|
||
surface.DrawCircle(w - 35, h/2, 12, COLOR_PRIMARY)
|
||
end
|
||
end
|
||
|
||
local colWidth = (scrW - 120) / 2
|
||
local startY = 205
|
||
|
||
-- Панель оружия
|
||
local weaponsPanel = vgui.Create("DPanel", frame)
|
||
weaponsPanel:SetSize(colWidth, scrH - startY - 40)
|
||
weaponsPanel:SetPos(40, startY)
|
||
weaponsPanel.Paint = function(s, w, h)
|
||
draw.RoundedBox(8, 0, 0, w, h, COLOR_BG_MEDIUM)
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
end
|
||
|
||
local weaponsHeader = vgui.Create("DPanel", weaponsPanel)
|
||
weaponsHeader:SetSize(weaponsPanel:GetWide(), 45)
|
||
weaponsHeader:SetPos(0, 0)
|
||
weaponsHeader.Paint = function(s, w, h)
|
||
draw.RoundedBoxEx(8, 0, 0, w, h, COLOR_PRIMARY_DARK, true, true, false, false)
|
||
|
||
draw.SimpleText("▣ ОРУЖИЕ", "ixSmallFont", 15, h/2, COLOR_TEXT_PRIMARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||
|
||
-- Декоративная линия
|
||
surface.SetDrawColor(COLOR_ACCENT)
|
||
surface.DrawRect(0, h-2, w, 2)
|
||
end
|
||
|
||
local weaponsScroll = vgui.Create("DScrollPanel", weaponsPanel)
|
||
weaponsScroll:SetSize(weaponsPanel:GetWide() - 20, weaponsPanel:GetTall() - 60)
|
||
weaponsScroll:SetPos(10, 50)
|
||
|
||
local sbar = weaponsScroll:GetVBar()
|
||
sbar:SetHideButtons(true)
|
||
function sbar:Paint(w, h)
|
||
draw.RoundedBox(4, 0, 0, w, h, COLOR_BG_DARK)
|
||
end
|
||
function sbar.btnGrip:Paint(w, h)
|
||
draw.RoundedBox(4, 0, 0, w, h, COLOR_PRIMARY)
|
||
end
|
||
|
||
-- Функция для создания окна выбора оружия из категории
|
||
local function OpenCategoryWeapons(categoryName, categoryIcon, categoryWeapons)
|
||
local catFrame = vgui.Create("DFrame")
|
||
catFrame:SetSize(800, 600)
|
||
catFrame:Center()
|
||
catFrame:SetTitle("")
|
||
catFrame:SetDraggable(true)
|
||
catFrame:ShowCloseButton(false)
|
||
catFrame:MakePopup()
|
||
|
||
catFrame.Paint = function(s, w, h)
|
||
draw.RoundedBox(8, 0, 0, w, h, COLOR_BG_DARK)
|
||
surface.SetDrawColor(COLOR_PRIMARY)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 3)
|
||
|
||
-- Заголовок
|
||
draw.RoundedBoxEx(8, 0, 0, w, 60, COLOR_PRIMARY_DARK, true, true, false, false)
|
||
draw.SimpleText(categoryIcon .. " " .. categoryName, "ixMenuButtonFont", w/2, 30, COLOR_TEXT_PRIMARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
|
||
surface.SetDrawColor(COLOR_ACCENT)
|
||
surface.DrawRect(0, 60, w, 2)
|
||
end
|
||
|
||
-- Кнопка закрытия
|
||
local catCloseBtn = vgui.Create("DButton", catFrame)
|
||
catCloseBtn:SetText("")
|
||
catCloseBtn:SetSize(35, 35)
|
||
catCloseBtn:SetPos(catFrame:GetWide() - 45, 12)
|
||
catCloseBtn.Paint = function(s, w, h)
|
||
local col = s:IsHovered() and COLOR_DANGER or Color(COLOR_DANGER.r * 0.7, COLOR_DANGER.g * 0.7, COLOR_DANGER.b * 0.7)
|
||
draw.RoundedBox(4, 0, 0, w, h, col)
|
||
surface.SetDrawColor(COLOR_TEXT_PRIMARY)
|
||
surface.DrawLine(w*0.3, h*0.3, w*0.7, h*0.7)
|
||
surface.DrawLine(w*0.7, h*0.3, w*0.3, h*0.7)
|
||
end
|
||
catCloseBtn.DoClick = function() catFrame:Close() end
|
||
|
||
-- Скролл с оружием
|
||
local catScroll = vgui.Create("DScrollPanel", catFrame)
|
||
catScroll:SetSize(catFrame:GetWide() - 30, catFrame:GetTall() - 85)
|
||
catScroll:SetPos(15, 70)
|
||
|
||
local catSbar = catScroll:GetVBar()
|
||
catSbar:SetHideButtons(true)
|
||
function catSbar:Paint(w, h)
|
||
draw.RoundedBox(4, 0, 0, w, h, COLOR_BG_DARK)
|
||
end
|
||
function catSbar.btnGrip:Paint(w, h)
|
||
draw.RoundedBox(4, 0, 0, w, h, COLOR_PRIMARY)
|
||
end
|
||
|
||
-- Создаем карточки оружия
|
||
for class, data in SortedPairsByMemberValue(categoryWeapons, "name", true) do
|
||
local has = weaponHas[class]
|
||
local row = vgui.Create("DPanel", catScroll)
|
||
row:SetSize(catScroll:GetWide() - 10, 110)
|
||
row:Dock(TOP)
|
||
row:DockMargin(0, 0, 0, 10)
|
||
|
||
local isHovered = false
|
||
row.Paint = function(s, w, h)
|
||
local bgColor = has and Color(45, 25, 20) or COLOR_BG_LIGHT
|
||
if isHovered then
|
||
bgColor = Color(bgColor.r + 10, bgColor.g + 15, bgColor.b + 10)
|
||
end
|
||
draw.RoundedBox(6, 0, 0, w, h, bgColor)
|
||
|
||
local statusColor = has and Color(205, 127, 50) or COLOR_PRIMARY
|
||
draw.RoundedBoxEx(6, 0, 0, 5, h, statusColor, true, false, true, false)
|
||
|
||
surface.SetDrawColor(has and Color(205, 127, 50, 80) or COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
|
||
if isHovered then
|
||
surface.SetDrawColor(COLOR_ACCENT)
|
||
surface.DrawRect(5, h-3, w-10, 3)
|
||
end
|
||
end
|
||
|
||
row.OnCursorEntered = function() isHovered = true end
|
||
row.OnCursorExited = function() isHovered = false end
|
||
|
||
-- Название
|
||
local nameLabel = vgui.Create("DLabel", row)
|
||
nameLabel:SetText(data.name or class)
|
||
nameLabel:SetFont("ixSmallFont")
|
||
nameLabel:SetTextColor(COLOR_TEXT_PRIMARY)
|
||
nameLabel:SetPos(15, 10)
|
||
nameLabel:SizeToContents()
|
||
|
||
-- Цена
|
||
local money = data.moneyPrice or 0
|
||
local supply = data.supplyPrice or 0
|
||
local priceLabel = vgui.Create("DLabel", row)
|
||
local priceText = ""
|
||
if (money or 0) <= 0 and (supply or 0) <= 0 then
|
||
priceText = "★ БЕСПЛАТНО"
|
||
else
|
||
local parts = {}
|
||
if money > 0 then table.insert(parts, currencySymbol .. tostring(money)) end
|
||
if supply > 0 then table.insert(parts, tostring(supply) .. " ОС") end
|
||
priceText = table.concat(parts, " • ")
|
||
end
|
||
priceLabel:SetText(priceText)
|
||
priceLabel:SetFont("ixSmallFont")
|
||
priceLabel:SetTextColor(money <= 0 and supply <= 0 and COLOR_ACCENT or COLOR_TEXT_PRIMARY)
|
||
priceLabel:SetPos(15, 40)
|
||
priceLabel:SizeToContents()
|
||
|
||
-- Донат метка
|
||
if data.donate then
|
||
local donateLabel = vgui.Create("DLabel", row)
|
||
donateLabel:SetText("★ ПРЕМИУМ")
|
||
donateLabel:SetFont("ixSmallFont")
|
||
donateLabel:SetTextColor(COLOR_WARNING)
|
||
donateLabel:SetPos(15, 70)
|
||
donateLabel:SizeToContents()
|
||
end
|
||
|
||
-- Кнопка действия
|
||
local btn = vgui.Create("DButton", row)
|
||
btn:SetSize(120, 40)
|
||
btn:SetPos(row:GetWide() - 130, 35)
|
||
btn:SetText("")
|
||
|
||
local btnText = has and "◄ ВЕРНУТЬ" or "ВЗЯТЬ ►"
|
||
local btnColor = has and Color(165, 85, 60) or COLOR_PRIMARY
|
||
local btnColorHover = has and Color(205, 105, 70) or COLOR_ACCENT
|
||
|
||
btn.Paint = function(s, w, h)
|
||
local col = s:IsHovered() and btnColorHover or btnColor
|
||
draw.RoundedBox(6, 0, 0, w, h, col)
|
||
|
||
if s:IsHovered() then
|
||
surface.SetDrawColor(255, 255, 255, 30)
|
||
draw.RoundedBox(6, 2, 2, w-4, h-4, Color(255, 255, 255, 30))
|
||
end
|
||
|
||
surface.SetDrawColor(COLOR_BG_DARK)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
|
||
draw.SimpleText(btnText, "ixSmallFont", w/2, h/2, COLOR_TEXT_PRIMARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
end
|
||
|
||
btn.DoClick = function()
|
||
if has then
|
||
Derma_Query("Вернуть снаряжение? Фракция получит 80% стоимости.", "Возврат", "Подтвердить", function()
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("return_weapon")
|
||
net.WriteString(class)
|
||
net.SendToServer()
|
||
catFrame:Close()
|
||
frame:Close()
|
||
end, "Отмена", function() end)
|
||
else
|
||
local options = {}
|
||
if (data.moneyPrice or 0) > 0 then table.insert(options, {text = "Купить за деньги", method = "money"}) end
|
||
if (data.supplyPrice or 0) >= 0 then table.insert(options, {text = "Купить за очки", method = "supply"}) end
|
||
|
||
if #options == 0 then
|
||
Derma_Message("Невозможно приобрести это оружие", "Ошибка", "OK")
|
||
return
|
||
end
|
||
|
||
if #options == 1 then
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("buy_weapon")
|
||
net.WriteString(class)
|
||
net.WriteString(options[1].method)
|
||
net.SendToServer()
|
||
catFrame:Close()
|
||
frame:Close()
|
||
else
|
||
local query = Derma_Query("Выберите способ оплаты:", "Оплата", options[1].text, function()
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("buy_weapon")
|
||
net.WriteString(class)
|
||
net.WriteString(options[1].method)
|
||
net.SendToServer()
|
||
catFrame:Close()
|
||
frame:Close()
|
||
end, options[2].text, function()
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("buy_weapon")
|
||
net.WriteString(class)
|
||
net.WriteString(options[2].method)
|
||
net.SendToServer()
|
||
catFrame:Close()
|
||
frame:Close()
|
||
end, "Отмена", function() end)
|
||
|
||
if IsValid(query) then
|
||
query:ShowCloseButton(true)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Панель брони
|
||
local armorPanel = vgui.Create("DPanel", frame)
|
||
armorPanel:SetSize(colWidth, scrH - startY - 40)
|
||
armorPanel:SetPos(scrW - colWidth - 40, startY)
|
||
armorPanel.Paint = function(s, w, h)
|
||
draw.RoundedBox(8, 0, 0, w, h, COLOR_BG_MEDIUM)
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
end
|
||
|
||
local armorHeader = vgui.Create("DPanel", armorPanel)
|
||
armorHeader:SetSize(armorPanel:GetWide(), 45)
|
||
armorHeader:SetPos(0, 0)
|
||
armorHeader.Paint = function(s, w, h)
|
||
draw.RoundedBoxEx(8, 0, 0, w, h, COLOR_PRIMARY_DARK, true, true, false, false)
|
||
|
||
draw.SimpleText("⬢ ЗАЩИТА", "ixSmallFont", 15, h/2, COLOR_TEXT_PRIMARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||
|
||
-- Декоративная линия
|
||
surface.SetDrawColor(COLOR_ACCENT)
|
||
surface.DrawRect(0, h-2, w, 2)
|
||
end
|
||
|
||
local armorScroll = vgui.Create("DScrollPanel", armorPanel)
|
||
armorScroll:SetSize(armorPanel:GetWide() - 20, armorPanel:GetTall() - 60)
|
||
armorScroll:SetPos(10, 50)
|
||
|
||
local sbar2 = armorScroll:GetVBar()
|
||
sbar2:SetHideButtons(true)
|
||
function sbar2:Paint(w, h)
|
||
draw.RoundedBox(4, 0, 0, w, h, COLOR_BG_DARK)
|
||
end
|
||
function sbar2.btnGrip:Paint(w, h)
|
||
draw.RoundedBox(4, 0, 0, w, h, COLOR_PRIMARY)
|
||
end
|
||
|
||
-- Группировка оружия по категориям
|
||
local categories = {
|
||
{name = "Основное оружие", icon = "▣", key = "primary", weapons = {}},
|
||
{name = "Пистолеты", icon = "▢", key = "secondary", weapons = {}},
|
||
{name = "Гранаты", icon = "◆", key = "grenades", weapons = {}},
|
||
{name = "Холодное оружие", icon = "▸", key = "melee", weapons = {}},
|
||
{name = "Прочее", icon = "◇", key = "other", weapons = {}}
|
||
}
|
||
|
||
-- Распределяем оружие по категориям
|
||
for class, data in pairs(weaponsData) do
|
||
if type(data) == "table" then
|
||
local cat = data.category or "other"
|
||
local added = false
|
||
|
||
if cat == "primary" then
|
||
table.insert(categories[1].weapons, {class = class, data = data})
|
||
added = true
|
||
elseif cat == "secondary" then
|
||
table.insert(categories[2].weapons, {class = class, data = data})
|
||
added = true
|
||
elseif cat == "grenade1" or cat == "grenade2" or cat == "grenade" then
|
||
table.insert(categories[3].weapons, {class = class, data = data})
|
||
added = true
|
||
elseif cat == "melee" then
|
||
table.insert(categories[4].weapons, {class = class, data = data})
|
||
added = true
|
||
end
|
||
|
||
if not added then
|
||
table.insert(categories[5].weapons, {class = class, data = data})
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Создаем кнопки категорий
|
||
local totalWeapons = 0
|
||
for _, category in ipairs(categories) do
|
||
if #category.weapons > 0 then
|
||
totalWeapons = totalWeapons + #category.weapons
|
||
|
||
local catButton = vgui.Create("DPanel", weaponsScroll)
|
||
catButton:SetSize(weaponsScroll:GetWide() - 10, 80)
|
||
catButton:Dock(TOP)
|
||
catButton:DockMargin(0, 0, 0, 10)
|
||
catButton:SetCursor("hand")
|
||
|
||
local isHovered = false
|
||
catButton.Paint = function(s, w, h)
|
||
local bgColor = COLOR_BG_LIGHT
|
||
if isHovered then
|
||
bgColor = Color(bgColor.r + 15, bgColor.g + 20, bgColor.b + 15)
|
||
end
|
||
draw.RoundedBox(6, 0, 0, w, h, bgColor)
|
||
|
||
-- Боковая полоска
|
||
draw.RoundedBoxEx(6, 0, 0, 6, h, COLOR_PRIMARY, true, false, true, false)
|
||
|
||
-- Рамка
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
|
||
-- Акцентная линия при наведении
|
||
if isHovered then
|
||
surface.SetDrawColor(COLOR_ACCENT)
|
||
surface.DrawRect(6, h-3, w-12, 3)
|
||
end
|
||
|
||
-- Иконка категории
|
||
draw.SimpleText(category.icon, "ixMenuButtonFont", 30, h/2, COLOR_ACCENT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
|
||
-- Название категории
|
||
draw.SimpleText(category.name, "ixSmallFont", 60, h/2 - 12, COLOR_TEXT_PRIMARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||
|
||
-- Количество оружия
|
||
draw.SimpleText(#category.weapons .. " ед.", "ixSmallFont", 60, h/2 + 12, COLOR_TEXT_SECONDARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||
|
||
-- Стрелка
|
||
draw.SimpleText("►", "ixSmallFont", w - 25, h/2, COLOR_PRIMARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
end
|
||
|
||
catButton.OnCursorEntered = function() isHovered = true end
|
||
catButton.OnCursorExited = function() isHovered = false end
|
||
catButton.OnMousePressed = function()
|
||
-- Подготовка данных для окна категории
|
||
local categoryWeapons = {}
|
||
for _, wpn in ipairs(category.weapons) do
|
||
categoryWeapons[wpn.class] = wpn.data
|
||
end
|
||
OpenCategoryWeapons(category.name, category.icon, categoryWeapons)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Если нет оружия вообще
|
||
if totalWeapons == 0 then
|
||
local emptyLabel = vgui.Create("DPanel", weaponsScroll)
|
||
emptyLabel:SetSize(weaponsScroll:GetWide(), 100)
|
||
emptyLabel:Dock(TOP)
|
||
emptyLabel:DockMargin(0, 20, 0, 0)
|
||
emptyLabel.Paint = function(s, w, h)
|
||
draw.RoundedBox(6, 0, 0, w, h, COLOR_BG_LIGHT)
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 1)
|
||
|
||
draw.SimpleText("⚠ НЕТ ДОСТУПНОГО ОРУЖИЯ", "ixSmallFont", w/2, h/2 - 10, COLOR_TEXT_SECONDARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
draw.SimpleText("Обратитесь к командованию", "ixSmallFont", w/2, h/2 + 15, Color(COLOR_TEXT_SECONDARY.r * 0.7, COLOR_TEXT_SECONDARY.g * 0.7, COLOR_TEXT_SECONDARY.b * 0.7), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
end
|
||
end
|
||
|
||
-- Заполнение брони
|
||
if not armorData or type(armorData) ~= "table" then armorData = {} end
|
||
if table.Count(armorData) > 0 then
|
||
for class, data in SortedPairsByMemberValue(armorData, "name", true) do
|
||
local row = vgui.Create("DPanel", armorScroll)
|
||
row:SetSize(armorScroll:GetWide() - 10, 100)
|
||
row:Dock(TOP)
|
||
row:DockMargin(0, 0, 0, 10)
|
||
|
||
local isHovered = false
|
||
row.Paint = function(s, w, h)
|
||
local bgColor = COLOR_BG_LIGHT
|
||
if isHovered then
|
||
bgColor = Color(bgColor.r + 10, bgColor.g + 15, bgColor.b + 10)
|
||
end
|
||
draw.RoundedBox(6, 0, 0, w, h, bgColor)
|
||
|
||
-- Боковая полоска
|
||
draw.RoundedBoxEx(6, 0, 0, 5, h, COLOR_ACCENT, true, false, true, false)
|
||
|
||
-- Рамка
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
|
||
-- Акцентная линия при наведении
|
||
if isHovered then
|
||
surface.SetDrawColor(COLOR_ACCENT)
|
||
surface.DrawRect(5, h-3, w-10, 3)
|
||
end
|
||
end
|
||
|
||
row.OnCursorEntered = function() isHovered = true end
|
||
row.OnCursorExited = function() isHovered = false end
|
||
|
||
-- Название брони
|
||
local nameLabel = vgui.Create("DLabel", row)
|
||
nameLabel:SetText(data.name or class)
|
||
nameLabel:SetFont("ixSmallFont")
|
||
nameLabel:SetTextColor(COLOR_TEXT_PRIMARY)
|
||
nameLabel:SetPos(15, 10)
|
||
nameLabel:SizeToContents()
|
||
|
||
-- Параметры брони
|
||
local amountLabel = vgui.Create("DLabel", row)
|
||
amountLabel:SetText("⬢ Защита: " .. tostring(data.amount or 0) .. " ед.")
|
||
amountLabel:SetFont("ixSmallFont")
|
||
amountLabel:SetTextColor(COLOR_TEXT_SECONDARY)
|
||
amountLabel:SetPos(15, 35)
|
||
amountLabel:SizeToContents()
|
||
|
||
-- Цена
|
||
local moneyP = data.moneyPrice or 0
|
||
local supplyP = data.supplyPrice or 0
|
||
local priceText = ""
|
||
if (moneyP or 0) <= 0 and (supplyP or 0) <= 0 then
|
||
priceText = "★ БЕСПЛАТНО"
|
||
else
|
||
local parts = {}
|
||
if moneyP > 0 then table.insert(parts, currencySymbol .. tostring(moneyP)) end
|
||
if supplyP > 0 then table.insert(parts, tostring(supplyP) .. " ОС") end
|
||
priceText = table.concat(parts, " • ")
|
||
end
|
||
local priceLabel = vgui.Create("DLabel", row)
|
||
priceLabel:SetText(priceText)
|
||
priceLabel:SetFont("ixSmallFont")
|
||
priceLabel:SetTextColor(moneyP <= 0 and supplyP <= 0 and COLOR_ACCENT or COLOR_TEXT_PRIMARY)
|
||
priceLabel:SetPos(15, 58)
|
||
priceLabel:SizeToContents()
|
||
|
||
-- Кнопка покупки
|
||
local btn = vgui.Create("DButton", row)
|
||
btn:SetSize(120, 40)
|
||
btn:SetPos(row:GetWide() - 130, 30)
|
||
btn:SetText("")
|
||
|
||
btn.Paint = function(s, w, h)
|
||
local col = s:IsHovered() and COLOR_ACCENT or COLOR_PRIMARY
|
||
draw.RoundedBox(6, 0, 0, w, h, col)
|
||
|
||
if s:IsHovered() then
|
||
surface.SetDrawColor(255, 255, 255, 30)
|
||
draw.RoundedBox(6, 2, 2, w-4, h-4, Color(255, 255, 255, 30))
|
||
end
|
||
|
||
surface.SetDrawColor(COLOR_BG_DARK)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 2)
|
||
|
||
draw.SimpleText("КУПИТЬ ►", "ixSmallFont", w/2, h/2, COLOR_TEXT_PRIMARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
end
|
||
|
||
btn.DoClick = function()
|
||
local options = {}
|
||
if (data.moneyPrice or 0) > 0 then table.insert(options, {text = "Купить за деньги", method = "money"}) end
|
||
if (data.supplyPrice or 0) >= 0 then table.insert(options, {text = "Купить за очки", method = "supply"}) end
|
||
|
||
if #options == 0 then
|
||
Derma_Message("Невозможно приобрести эту броню", "Ошибка", "OK")
|
||
return
|
||
end
|
||
|
||
if #options == 1 then
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("buy_armor")
|
||
net.WriteString(class)
|
||
net.WriteString(options[1].method)
|
||
net.SendToServer()
|
||
frame:Close()
|
||
else
|
||
local query = Derma_Query("Выберите способ оплаты:", "Оплата", options[1].text, function()
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("buy_armor")
|
||
net.WriteString(class)
|
||
net.WriteString(options[1].method)
|
||
net.SendToServer()
|
||
frame:Close()
|
||
end, options[2].text, function()
|
||
net.Start("ixArsenalAction")
|
||
net.WriteString("buy_armor")
|
||
net.WriteString(class)
|
||
net.WriteString(options[2].method)
|
||
net.SendToServer()
|
||
frame:Close()
|
||
end, "Отмена", function() end)
|
||
|
||
if IsValid(query) then
|
||
query:ShowCloseButton(true)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
else
|
||
local emptyLabel = vgui.Create("DPanel", armorScroll)
|
||
emptyLabel:SetSize(armorScroll:GetWide(), 100)
|
||
emptyLabel:Dock(TOP)
|
||
emptyLabel:DockMargin(0, 20, 0, 0)
|
||
emptyLabel.Paint = function(s, w, h)
|
||
draw.RoundedBox(6, 0, 0, w, h, COLOR_BG_LIGHT)
|
||
surface.SetDrawColor(COLOR_BORDER)
|
||
surface.DrawOutlinedRect(0, 0, w, h, 1)
|
||
|
||
draw.SimpleText("⚠ НЕТ ДОСТУПНОЙ ЗАЩИТЫ", "ixSmallFont", w/2, h/2 - 10, COLOR_TEXT_SECONDARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
draw.SimpleText("Обратитесь к командованию", "ixSmallFont", w/2, h/2 + 15, Color(COLOR_TEXT_SECONDARY.r * 0.7, COLOR_TEXT_SECONDARY.g * 0.7, COLOR_TEXT_SECONDARY.b * 0.7), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||
end
|
||
end
|
||
|
||
PLUGIN.menu = frame
|
||
end)
|