Files
VnUtest/garrysmod/gamemodes/militaryrp/plugins/military_id/cl_plugin.lua
2026-03-31 10:27:04 +03:00

358 lines
12 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
-- Открытие опроса
net.Receive("ixMilitaryID_OpenQuiz", function()
PLUGIN:OpenQuizMenu()
end)
-- Просмотр документа
net.Receive("ixMilitaryID_ViewDocument", function()
local data = net.ReadTable()
PLUGIN:ShowDocument(data)
end)
-- UI для опроса
function PLUGIN:OpenQuizMenu()
if IsValid(self.quizFrame) then
self.quizFrame: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 contentPanel = vgui.Create("DPanel", frame)
contentPanel:SetSize(1000, scrH - 240)
contentPanel:SetPos((scrW - 1000) / 2, 140)
contentPanel.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 currentQuestion = 1
local answers = {}
-- Панель прогресса
local progressPanel = vgui.Create("DPanel", contentPanel)
progressPanel:Dock(TOP)
progressPanel:DockMargin(0, 0, 0, 10)
progressPanel:SetTall(60)
progressPanel.Paint = function(s, w, h)
draw.RoundedBox(6, 0, 0, w, h, COLOR_BG_LIGHT)
surface.SetDrawColor(COLOR_PRIMARY)
surface.DrawOutlinedRect(0, 0, w, h, 2)
-- Прогресс бар
local progress = currentQuestion / #self.quizQuestions
local barWidth = (w - 40) * progress
draw.RoundedBox(4, 20, h - 15, w - 40, 8, COLOR_BG_DARK)
draw.RoundedBox(4, 20, h - 15, barWidth, 8, COLOR_ACCENT)
-- Текст прогресса
draw.SimpleText("ВОПРОС " .. currentQuestion .. " ИЗ " .. #self.quizQuestions, "ixSmallFont", w/2, 20, COLOR_TEXT_PRIMARY, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
-- Панель вопроса
local questionPanel = vgui.Create("DPanel", contentPanel)
questionPanel:Dock(TOP)
questionPanel:DockMargin(0, 0, 0, 20)
questionPanel:SetTall(100)
questionPanel.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, 2)
end
local questionLabel = vgui.Create("DLabel", questionPanel)
questionLabel:Dock(FILL)
questionLabel:DockMargin(20, 20, 20, 20)
questionLabel:SetFont("DermaLarge")
questionLabel:SetTextColor(COLOR_TEXT_PRIMARY)
questionLabel:SetWrap(true)
questionLabel:SetContentAlignment(5)
-- Панель ответов
local answersScroll = vgui.Create("DScrollPanel", contentPanel)
answersScroll:Dock(FILL)
answersScroll:DockMargin(0, 0, 0, 0)
local sbar = answersScroll: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 ShowQuestion(index)
if index > #self.quizQuestions then
-- Все вопросы пройдены
net.Start("ixMilitaryID_SubmitQuiz")
net.WriteTable(answers)
net.SendToServer()
frame:Close()
return
end
local question = self.quizQuestions[index]
questionLabel:SetText(question.question)
answersScroll:Clear()
for i, answer in ipairs(question.answers) do
local btn = vgui.Create("DButton", answersScroll)
btn:Dock(TOP)
btn:DockMargin(20, 10, 20, 10)
btn:SetTall(60)
btn:SetText("")
local isHovered = false
btn.Paint = function(s, w, h)
local bgColor = isHovered and COLOR_PRIMARY_DARK or COLOR_BG_LIGHT
draw.RoundedBox(6, 0, 0, w, h, bgColor)
-- Рамка
surface.SetDrawColor(isHovered and COLOR_ACCENT or COLOR_BORDER)
surface.DrawOutlinedRect(0, 0, w, h, 2)
-- Акцентная линия слева
draw.RoundedBoxEx(6, 0, 0, 5, h, COLOR_PRIMARY, true, false, true, false)
-- Номер ответа
draw.SimpleText(tostring(i), "DermaLarge", 30, h/2, COLOR_ACCENT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
-- Текст ответа
draw.SimpleText(answer, "ixSmallFont", 60, h/2, COLOR_TEXT_PRIMARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
if isHovered then
surface.SetDrawColor(255, 255, 255, 20)
draw.RoundedBox(6, 0, 0, w, h, Color(255, 255, 255, 20))
end
end
btn.OnCursorEntered = function() isHovered = true end
btn.OnCursorExited = function() isHovered = false end
btn.DoClick = function()
answers[index] = i
currentQuestion = currentQuestion + 1
ShowQuestion(currentQuestion)
end
end
end
ShowQuestion(1)
self.quizFrame = frame
end
-- UI для просмотра документа
function PLUGIN:ShowDocument(data)
if IsValid(self.documentFrame) then
self.documentFrame:Remove()
end
-- Отладка: выводим полученные данные
print("[MilitaryID] ShowDocument called with data:")
PrintTable(data or {})
local frame = vgui.Create("DFrame")
frame:SetSize(500, 400)
frame:SetTitle("")
frame:Center()
frame:ShowCloseButton(false)
frame:MakePopup()
frame.Paint = function(s, w, h)
-- Фон документа
draw.RoundedBox(8, 0, 0, w, h, Color(230, 220, 200))
-- Рамка
surface.SetDrawColor(100, 50, 0)
surface.DrawOutlinedRect(5, 25, w - 10, h - 30, 3)
-- Заголовок
draw.SimpleText("ВОЕННЫЙ БИЛЕТ", "DermaLarge", w/2, 40, Color(100, 50, 0), TEXT_ALIGN_CENTER)
end
local infoPanel = vgui.Create("DPanel", frame)
infoPanel:SetPos(30, 80)
infoPanel:SetSize(440, 280)
infoPanel.Paint = nil
local yPos = 0
local fields = {
{"Имя:", data and data.name or "Не указано"},
{"Фракция:", data and data.faction or "Не указано"},
{"Подразделение:", data and data.subdivision or "Не указано"},
{"Специализация:", data and data.specialization or "Не указано"},
{"Звание:", data and data.rank or "Не указано"},
{"Розыск:", (data and data.wanted_fsb and data.wanted_sbu) and "В РОЗЫСКЕ ФСБ И СБУ" or (data and data.wanted_fsb) and "В РОЗЫСКЕ ФСБ" or (data and data.wanted_sbu) and "В РОЗЫСКЕ СБУ" or "Чист"}
}
for _, field in ipairs(fields) do
local label = vgui.Create("DLabel", infoPanel)
label:SetPos(0, yPos)
label:SetFont("DermaDefaultBold")
label:SetText(field[1])
label:SetTextColor(Color(50, 50, 50))
label:SizeToContents()
local value = vgui.Create("DLabel", infoPanel)
value:SetPos(150, yPos)
value:SetFont("DermaDefault")
value:SetText(field[2])
-- Make the "Wanted" value red if wanted
if field[1] == "Розыск:" and data and (data.wanted_fsb or data.wanted_sbu) then
value:SetTextColor(Color(200, 0, 0))
value:SetFont("DermaDefaultBold")
else
value:SetTextColor(Color(0, 0, 0))
end
value:SizeToContents()
yPos = yPos + 35
end
-- Visual Wanted Stamp
if data and (data.wanted_fsb or data.wanted_sbu) then
local stamp = vgui.Create("DPanel", frame)
stamp:SetSize(180, 60)
stamp:SetPos(300, 280)
stamp.Paint = function(s, w, h)
local x, y = s:LocalToScreen(0, 0)
local matrix = Matrix()
matrix:Translate(Vector(x + w / 2, y + h / 2, 0))
matrix:Rotate(Angle(0, 15, 0))
matrix:Translate(Vector(-(x + w / 2), -(y + h / 2), 0))
cam.PushModelMatrix(matrix)
surface.SetDrawColor(200, 0, 0, 150)
surface.DrawOutlinedRect(x, y, w, h, 4)
draw.SimpleText("В РОЗЫСКЕ", "DermaLarge", x + w / 2, y + h / 2, Color(200, 0, 0, 200), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
cam.PopModelMatrix()
end
end
local closeBtn = vgui.Create("DButton", frame)
closeBtn:SetPos(175, 350)
closeBtn:SetSize(150, 30)
closeBtn:SetText("Закрыть")
closeBtn.DoClick = function()
frame:Close()
end
frame.OnRemove = function()
net.Start("ixMilitaryID_StopView")
net.SendToServer()
end
self.documentFrame = frame
end