add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,384 @@
local menuFrame = nil
local factions = {}
local function GetPlayerBySteamID(steamID)
for _, ply in ipairs(player.GetAll()) do
if ply:SteamID() == steamID then
return ply
end
end
return nil
end
local function GetDisplayName(input)
if isstring(input) then
return input
elseif istable(input) then
return input[1] or tostring(input)
else
return tostring(input)
end
end
local selectedPlayer = nil
local selectedFaction = nil
local selectedPodr = nil
local selectedSpec = nil
local selectedRank = nil
local playerButtons = {}
local factionButtons = {}
local podrButtons = {}
local specButtons = {}
local rankButtons = {}
local originalPlayers = {}
net.Receive("ixWhitelistMenuOpen", function()
if menuFrame and menuFrame:IsValid() then menuFrame:Close() end
net.Start("ixWhitelistMenuDataRequest")
net.SendToServer()
end)
net.Receive("ixWhitelistMenuData", function()
if menuFrame and menuFrame:IsValid() then menuFrame:Close() end
originalPlayers = net.ReadTable()
factions = net.ReadTable()
selectedPlayer = nil
selectedFaction = nil
selectedPodr = nil
selectedSpec = nil
selectedRank = nil
playerButtons = {}
factionButtons = {}
podrButtons = {}
specButtons = {}
rankButtons = {}
local scrW, scrH = ScrW(), ScrH()
menuFrame = vgui.Create("DFrame")
menuFrame:SetSize(900, 650)
menuFrame:SetPos(scrW/2 - 450, scrH/2 - 325)
menuFrame:SetTitle("")
menuFrame:SetDraggable(false)
menuFrame:ShowCloseButton(false)
menuFrame:MakePopup()
menuFrame.Paint = function(s, w, h)
-- Фон
surface.SetDrawColor(Color(13, 13, 13, 240))
surface.DrawRect(0, 0, w, h)
-- Обводка
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 2)
-- Верхняя панель
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawRect(0, 0, w, 40)
-- Заголовок
draw.SimpleText("МЕНЕДЖЕР ВАЙТЛИСТА", "ixMenuButtonFont", w/2, 20, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
local closeBtn = vgui.Create("DButton", menuFrame)
closeBtn:SetText("")
closeBtn:SetSize(30, 30)
closeBtn:SetPos(menuFrame:GetWide() - 40, 5)
closeBtn.Paint = function(s, w, h)
surface.SetDrawColor(Color(200, 50, 50))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(29, 29, 29))
surface.DrawOutlinedRect(0, 0, w, h, 2)
draw.SimpleText("×", "ixSmallFont", w/2, h/2, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if s:IsHovered() then
surface.SetDrawColor(Color(255, 255, 255, 30))
surface.DrawRect(0, 0, w, h)
end
end
closeBtn.DoClick = function()
menuFrame:Close()
end
local function CreateRow(parent, text, onSelect, data, buttonGroup)
local btn = parent:Add("DButton")
btn:SetText("")
btn:SetTall(30)
btn:SetFont("ixSmallFont")
btn.Paint = function(s, w, h)
if s.isSelected then
surface.SetDrawColor(Color(1, 67, 29, 200))
surface.DrawRect(0, 0, w, h)
else
surface.SetDrawColor(Color(23, 23, 23))
surface.DrawRect(0, 0, w, h)
end
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 1)
local textColor = s.isSelected and color_white or Color(200, 200, 200)
draw.SimpleText(text, "ixSmallFont", 8, h/2, textColor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
if s:IsHovered() and not s.isSelected then
surface.SetDrawColor(Color(255, 255, 255, 20))
surface.DrawRect(0, 0, w, h)
end
end
btn.DoClick = function()
for _, otherBtn in ipairs(buttonGroup) do
if otherBtn ~= btn then
otherBtn.isSelected = false
end
end
btn.isSelected = true
if onSelect then onSelect(data) end
end
btn:DockMargin(2, 2, 2, 2)
btn:Dock(TOP)
table.insert(buttonGroup, btn)
return btn
end
local colWidth = 160
local colSpacing = 10
local colX = 20
local headerHeight = 30
local scrollHeight = 500
local totalHeight = headerHeight + scrollHeight
local startY = 60
local buttonHeight = 40
local function CreateColumnPanel(name, x)
local panel = vgui.Create("DPanel", menuFrame)
panel:SetSize(colWidth, totalHeight)
panel:SetPos(x, startY)
panel.Paint = function(s, w, h)
surface.SetDrawColor(Color(23, 23, 23))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 1)
end
local header = vgui.Create("DLabel", panel)
header:SetText(name)
header:SetPos(0, 5)
header:SetSize(colWidth, 20)
header:SetFont("ixSmallFont")
header:SetTextColor(color_white)
header:SetContentAlignment(5)
local scroll = vgui.Create("DScrollPanel", panel)
scroll:SetSize(colWidth - 4, scrollHeight)
scroll:SetPos(2, headerHeight)
return scroll
end
-- Панель игроков с поиском
local playerPanel = vgui.Create("DPanel", menuFrame)
playerPanel:SetSize(colWidth, totalHeight)
playerPanel:SetPos(colX, startY)
playerPanel.Paint = function(s, w, h)
surface.SetDrawColor(Color(23, 23, 23))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 1)
end
local playerHeader = vgui.Create("DLabel", playerPanel)
playerHeader:SetText("ИГРОКИ")
playerHeader:SetPos(0, 5)
playerHeader:SetSize(colWidth, 20)
playerHeader:SetFont("ixSmallFont")
playerHeader:SetTextColor(color_white)
playerHeader:SetContentAlignment(5)
local searchBox = vgui.Create("DTextEntry", playerPanel)
searchBox:SetPos(5, 30)
searchBox:SetSize(colWidth - 10, 25)
searchBox:SetPlaceholderText("Поиск...")
searchBox:SetFont("ixSmallFont")
searchBox:SetUpdateOnType(true)
searchBox.Paint = function(s, w, h)
surface.SetDrawColor(Color(23, 23, 23))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawOutlinedRect(0, 0, w, h, 1)
s:DrawTextEntryText(color_white, Color(30, 130, 255), color_white)
end
local playerScroll = vgui.Create("DScrollPanel", playerPanel)
playerScroll:SetSize(colWidth - 4, scrollHeight - 40)
playerScroll:SetPos(2, 60)
-- Создаем колонки
local factionScroll = CreateColumnPanel("ФРАКЦИИ", colX + (colWidth + colSpacing) * 1)
local podrScroll = CreateColumnPanel("ПОДРАЗДЕЛЕНИЯ", colX + (colWidth + colSpacing) * 2)
local specScroll = CreateColumnPanel("СПЕЦИАЛИЗАЦИИ", colX + (colWidth + colSpacing) * 3)
local rankScroll = CreateColumnPanel("ЗВАНИЯ", colX + (colWidth + colSpacing) * 4)
local function UpdatePlayerList(filterText)
playerScroll:Clear()
playerButtons = {}
local lowerFilter = string.lower(filterText or "")
for _, p in ipairs(originalPlayers) do
if filterText == "" or string.find(string.lower(p.name), lowerFilter, 1, true) then
CreateRow(playerScroll, p.name, function(data)
selectedPlayer = data
factionScroll:Clear()
podrScroll:Clear()
specScroll:Clear()
rankScroll:Clear()
selectedFaction = nil
selectedPodr = nil
selectedSpec = nil
selectedRank = nil
factionButtons = {}
podrButtons = {}
specButtons = {}
rankButtons = {}
for id, f in pairs(factions) do
CreateRow(factionScroll, GetDisplayName(f.name), function(factionData)
selectedFaction = factionData
local f = factions[factionData.id]
podrScroll:Clear()
specScroll:Clear()
rankScroll:Clear()
selectedPodr = nil
selectedSpec = nil
selectedRank = nil
podrButtons = {}
specButtons = {}
rankButtons = {}
for podId, podr in pairs(f.Podr) do
CreateRow(podrScroll, podr.name, function(podrData)
selectedPodr = podrData
local f2 = factions[selectedFaction.id]
-- Update specialties
specScroll:Clear()
selectedSpec = nil
specButtons = {}
for specId, spec in pairs(f2.Spec) do
if spec.podr == podrData.id then
CreateRow(specScroll, spec.name, function(specData)
selectedSpec = specData
end, { id = specId }, specButtons)
end
end
-- Update ranks based on subdivision
rankScroll:Clear()
selectedRank = nil
rankButtons = {}
local targetRanks = (f2.Podr[podrData.id] and f2.Podr[podrData.id].ranks) or f2.Ranks
if targetRanks then
local keys = {}
for k in pairs(targetRanks) do table.insert(keys, k) end
table.sort(keys)
for _, rankId in ipairs(keys) do
local rank = targetRanks[rankId]
CreateRow(rankScroll, GetDisplayName(rank[1]), function(rankData)
selectedRank = rankData
end, { id = rankId }, rankButtons)
end
end
end, { id = podId }, podrButtons)
end
local factionRanks = f.Ranks
if factionRanks then
local keys = {}
for k in pairs(factionRanks) do table.insert(keys, k) end
table.sort(keys)
for _, rankId in ipairs(keys) do
local rank = factionRanks[rankId]
CreateRow(rankScroll, GetDisplayName(rank[1]), function(rankData)
selectedRank = rankData
end, { id = rankId }, rankButtons)
end
end
end, { id = id }, factionButtons)
end
end, { steamID = p.steamID }, playerButtons)
end
end
end
searchBox.OnValueChange = function(_, value)
UpdatePlayerList(value)
end
UpdatePlayerList("")
-- Кнопка назначения
local applyBtn = vgui.Create("DButton", menuFrame)
applyBtn:SetText("")
applyBtn:SetSize(200, 40)
applyBtn:SetPos(menuFrame:GetWide()/2 - 100, startY + totalHeight + 10)
applyBtn.Paint = function(s, w, h)
surface.SetDrawColor(Color(1, 67, 29))
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(Color(29, 29, 29))
surface.DrawOutlinedRect(0, 0, w, h, 2)
draw.SimpleText("НАЗНАЧИТЬ", "ixSmallFont", w/2, h/2, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
if s:IsHovered() then
surface.SetDrawColor(Color(255, 255, 255, 30))
surface.DrawRect(0, 0, w, h)
end
end
applyBtn.DoClick = function()
if not (selectedPlayer and selectedFaction and selectedPodr and selectedSpec and selectedRank) then
LocalPlayer():Notify("Выберите все поля!")
return
end
net.Start("ixWhitelistMenuApply")
net.WriteString(selectedPlayer.steamID)
net.WriteUInt(selectedFaction.id, 16)
net.WriteUInt(selectedPodr.id, 8)
net.WriteUInt(selectedSpec.id, 8)
net.WriteUInt(selectedRank.id, 8)
net.SendToServer()
menuFrame:Close()
LocalPlayer():Notify("Вайтлист успешно назначен!")
end
-- Статус выбора
local statusPanel = vgui.Create("DPanel", menuFrame)
statusPanel:SetSize(400, 30)
statusPanel:SetPos(menuFrame:GetWide()/2 - 200, startY + totalHeight - 553.5)
statusPanel.Paint = function(s, w, h)
local statusText = "Выберите игрока и все параметры"
local statusColor = Color(200, 200, 200)
if selectedPlayer and selectedFaction and selectedPodr and selectedSpec and selectedRank then
statusText = "Готово к назначению"
statusColor = Color(84, 147, 90)
end
draw.SimpleText(statusText, "ixSmallFont", w/2, h/2, statusColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
menuFrame.OnCursorEntered = function(s)
s:MoveToFront()
end
end)

View File

@@ -0,0 +1,63 @@
PLUGIN.name = "Whitelist Menu"
PLUGIN.author = "Refosel"
PLUGIN.description = "Меню для выдачи фракции, подразделения, специализации и звания."
-- Регистрация CAMI-привилегии при загрузке
function PLUGIN:Load()
CAMI.RegisterPrivilege({
Name = "WhitelistMenu - Open",
Description = "Может открывать меню назначения роли (фракция, подразделение, специализация, звание).",
MinAccess = "user"
})
end
PLUGIN.AllowedGroups = {
["superadmin"] = true,
["super admin"] = true,
["projectteam"] = true,
["teh.admin"] = true,
["curator"] = true,
["sudo-curator"] = true,
["asist-sudo"] = true,
["admin"] = true,
["st.admin"] = true,
["ivent"] = true,
["st.event"] = true,
["event"] = true,
["disp"] = true,
["assistant"] = true,
["specadmin"] = true,
["sponsor"] = true,
["prem"] = true,
["cmd"] = true,
["inst"] = true
}
function PLUGIN:HasAccess(client)
local character = client:GetCharacter()
if (character and (character:HasFlags("W") or character:HasFlags("w"))) then
return true
end
local userGroup = string.lower(client:GetUserGroup() or "user")
return self.AllowedGroups[userGroup] or client:IsAdmin() or client:IsSuperAdmin()
end
ix.util.Include("cl_plugin.lua")
ix.util.Include("sv_plugin.lua")
-- Команда без аргументов
ix.command.Add("wl", {
description = "Открыть меню назначения роли",
arguments = {},
CanRun = function(self, client)
return PLUGIN:HasAccess(client)
end,
OnRun = function(self, client)
if not client:Alive() then
return "@notAlive"
end
net.Start("ixWhitelistMenuOpen")
net.Send(client)
end
})

View File

@@ -0,0 +1,105 @@
local PLUGIN = PLUGIN
util.AddNetworkString("ixWhitelistMenuOpen")
util.AddNetworkString("ixWhitelistMenuDataRequest")
util.AddNetworkString("ixWhitelistMenuData")
util.AddNetworkString("ixWhitelistMenuApply")
local function GetFactionData()
local data = {}
for k, v in pairs(ix.faction.indices) do
if v.Podr and v.Spec and v.Ranks then
data[k] = {
name = v.name,
Podr = v.Podr,
Spec = v.Spec,
Ranks = v.Ranks
}
end
end
return data
end
net.Receive("ixWhitelistMenuDataRequest", function(_, client)
if not PLUGIN:HasAccess(client) then
return
end
local players = {}
for _, ply in ipairs(player.GetAll()) do
if ply:Alive() and ply:GetCharacter() then
table.insert(players, {
steamID = ply:SteamID(),
name = ply:Name()
})
end
end
net.Start("ixWhitelistMenuData")
net.WriteTable(players)
net.WriteTable(GetFactionData())
net.Send(client)
end)
net.Receive("ixWhitelistMenuApply", function(_, client)
if not PLUGIN:HasAccess(client) then
return
end
local targetSteamID = net.ReadString()
local factionID = net.ReadUInt(16)
local podrID = net.ReadUInt(8)
local specID = net.ReadUInt(8)
local rankID = net.ReadUInt(8)
local target = nil
for _, ply in ipairs(player.GetAll()) do
if ply:SteamID() == targetSteamID then
target = ply
break
end
end
if not target or not target:GetCharacter() then
client:Notify("Игрок не найден.")
return
end
local faction = ix.faction.indices[factionID]
if not faction then
client:Notify("Фракция не найдена.")
return
end
if not faction.Podr[podrID] then
client:Notify("Подразделение не найдено.")
return
end
if not faction.Spec[specID] then
client:Notify("Специализация не найдена.")
return
end
local targetRanks = (faction.Podr[podrID] and faction.Podr[podrID].ranks) or faction.Ranks
if not (targetRanks and targetRanks[rankID]) then
client:Notify("Звание не найдено.")
return
end
if faction.Spec[specID].podr ~= podrID then
client:Notify("Специализация не соответствует подразделению.")
return
end
local char = target:GetCharacter()
char:SetFaction(factionID)
char:SetPodr(podrID)
char:SetSpec(specID)
char:SetRank(rankID)
-- Респавн игрока для применения изменений
target:Spawn()
client:Notify("Роль назначена: " .. target:Name())
target:Notify("Вам назначена новая роль!")
end)