add sborka
This commit is contained in:
357
garrysmod/gamemodes/militaryrp/plugins/military_id/cl_plugin.lua
Normal file
357
garrysmod/gamemodes/militaryrp/plugins/military_id/cl_plugin.lua
Normal file
@@ -0,0 +1,357 @@
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user