Files
wnsrc/lua/sam/menu/tabs/ranks.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

637 lines
16 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
if SAM_LOADED then return end
if SERVER then return end
local sam = sam
local SUI = sam.SUI
local GetColor = SUI.GetColor
local Line = sui.TDLib.LibClasses.Line
local AnimatedSetVisible = sui.TDLib.LibClasses.AnimatedSetVisible
local RANK_NAME = SUI.CreateFont("RankName", "Roboto Bold", 18)
local RANK_INFO = SUI.CreateFont("RankInfo", "Roboto Medium", 12)
local CREATE_RANK = SUI.CreateFont("CreateRank", "Roboto Bold", 16, 200)
local RANK_TITLE = SUI.CreateFont("RankTitle", "Roboto Bold", 20)
local rank_menu = function(rank, data)
local valid = sui.valid_options()
local imm, banlim
if rank then
imm, banlim = data.immunity, data.ban_limit
end
local edit_rank = vgui.Create("SAM.QueryBox")
edit_rank:SetWide(470)
edit_rank:SetTitle(rank and string.format("Edit Rank '%s'", rank) or "Create Rank")
local new_name = rank
if not sam.ranks.is_default_rank(rank) then
local name = edit_rank:Add("SAM.LabelPanel")
name:SetLabel("Rank Name")
local entry = name:Add("SAM.TextEntry")
entry:SetSize(210, 28)
entry:SetNoBar(false)
entry:SetPlaceholder("")
entry:SetValue(rank or "")
entry:SetCheck(function(_name)
new_name = _name
if _name == rank then return end
if _name == "" or sam.ranks.is_rank(_name) then
return false
end
end)
valid.Add(entry)
end
local new_immunity = imm
do
local immunity = edit_rank:Add("SAM.LabelPanel")
immunity:SetLabel("Immunity (2~99)")
immunity:DockMargin(0, 5, 0, 0)
local entry = immunity:Add("SAM.TextEntry")
entry:SetSize(210, 28)
entry:SetNumeric(true)
entry:DisallowFloats(true)
entry:DisallowNegative(true)
entry:SetPlaceholder("")
entry:SetValue(imm or "2")
entry:SetCheck(function(_immunity)
new_immunity = _immunity
if _immunity == "" then
return false
end
_immunity = tonumber(_immunity)
new_immunity = _immunity
if _immunity < 2 or _immunity > 99 then
return false
end
end)
valid.Add(entry)
end
local new_banlimit = banlim
do
local banlimit = edit_rank:Add("SAM.LabelPanel")
banlimit:SetLabel("Ban Limit (1y 1mo 1w 1d 1h 1m)")
banlimit:DockMargin(0, 5, 0, 0)
local entry = banlimit:Add("SAM.TextEntry")
entry:SetSize(210, 28)
entry:SetNoBar(false)
entry:SetPlaceholder("")
entry:SetValue(banlim and sam.reverse_parse_length(banlim) or "2w")
entry:SetCheck(function(_banlimit)
new_banlimit = sam.parse_length(_banlimit)
if not new_banlimit and _banlimit ~= banlim then
return false
end
end)
valid.Add(entry)
end
local inherit = rank and sam.ranks.get_rank(rank).inherit or "user"
local new_inherit = inherit
do
local inherits_from = edit_rank:Add("SAM.LabelPanel")
inherits_from:SetLabel("Inherits From")
inherits_from:DockMargin(0, 5, 0, 0)
local entry = inherits_from:Add("SAM.ComboBox")
entry:SetSize(210, 28)
entry:SetValue(inherit)
for name in SortedPairsByMemberValue(sam.ranks.get_ranks(), "immunity", true) do
if name ~= rank and not sam.ranks.inherits_from(name, rank) then
entry:AddChoice(name)
end
end
function entry:OnSelect(_, value)
new_inherit = value
end
end
edit_rank:Done()
edit_rank.save:SetEnabled(true)
edit_rank.save:SetText("SAVE")
if rank then
edit_rank:SetCallback(function()
local to_run = {}
if new_immunity ~= imm then
table.insert(to_run, {"changerankimmunity", rank, new_immunity})
end
if new_banlimit ~= banlim then
table.insert(to_run, {"changerankbanlimit", rank, new_banlimit})
end
if new_inherit ~= inherit then
table.insert(to_run, {"changeinherit", rank, new_inherit})
end
if new_name ~= rank then
table.insert(to_run, {"renamerank", rank, new_name})
end
sam.command.run_commands(to_run)
end)
else
edit_rank:SetCallback(function()
RunConsoleCommand("sam", "addrank", new_name, new_inherit, new_immunity, new_banlimit)
end)
end
function edit_rank.save:Think()
self:SetEnabled(valid.IsValid())
end
end
sam.menu.add_tab("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/military_rank.png", function(column_sheet)
local current_rank
local parent = column_sheet:Add("Panel")
parent:Dock(FILL)
parent:DockMargin(0, 1, 0, 0)
local title = parent:Add("SAM.Label")
title:Dock(TOP)
title:DockMargin(10, 10, 0, 0)
title:SetFont(SAM_TAB_TITLE_FONT)
title:SetText("Ranks")
title:SetTextColor(GetColor("menu_tabs_title"))
title:SizeToContents()
local total = parent:Add("SAM.Label")
total:Dock(TOP)
total:DockMargin(10, 6, 0, 0)
total:SetFont(SAM_TAB_DESC_FONT)
total:SetText(table.Count(sam.ranks.get_ranks()) .. " total ranks")
total:SetTextColor(GetColor("menu_tabs_title"))
total:SizeToContents()
local search_entry
do
local container = parent:Add("SAM.Panel")
container:Dock(TOP)
container:DockMargin(10, 6, 10, SUI.Scale(15))
container:SetTall(30)
search_entry = container:Add("SAM.TextEntry")
search_entry:Dock(LEFT)
search_entry:SetNoBar(true)
search_entry:SetPlaceholder("Search...")
search_entry:SetRadius(4)
search_entry:SetWide(220)
end
local create_rank = parent:Add("SAM.Button")
create_rank:SetFont(CREATE_RANK)
create_rank:SetText("Create Rank")
create_rank:Dock(BOTTOM)
create_rank:DockMargin(10, 0, 10, 10)
create_rank:On("DoClick", function()
rank_menu()
end)
local right_body = parent:Add("Panel")
right_body:Dock(RIGHT)
right_body:DockMargin(0, 5, 10, 10)
right_body:SetWide(0)
right_body:SetZPos(-1)
local rank_title = right_body:Add("SAM.Label")
rank_title:Dock(TOP)
rank_title:DockMargin(0, 0, 0, 5)
rank_title:SetFont(RANK_TITLE)
rank_title:SetTextColor(GetColor("menu_tabs_title"))
local permissions_body = right_body:Add("SAM.CollapseCategory")
permissions_body:Dock(FILL)
permissions_body:GetCanvas():DockPadding(0, 0, 5, 0)
local function refresh_access()
if not IsValid(current_rank) then return end
for k, v in ipairs(permissions_body.items) do
AnimatedSetVisible(v.img, sam.ranks.has_permission(current_rank.name, v.name))
end
end
for k, v in ipairs({"SAM.ChangedInheritRank", "SAM.RankPermissionGiven", "SAM.RankPermissionTaken"}) do
hook.Add(v, "SAM.Menu.RefreshPermissions ", refresh_access)
end
local function sortFunc(a, b)
if (a.category == b.category) then return a.name < b.name end
return a.category < b.category
end
local function refresh_permissions()
permissions_body:GetCanvas():Clear()
table.Empty(permissions_body.items)
table.Empty(permissions_body.categories)
local item_click = function(s)
local rank = current_rank.name
if not sam.ranks.has_permission(rank, s.name) then
RunConsoleCommand("sam", "givepermission", rank, s.name)
else
RunConsoleCommand("sam", "takepermission", rank, s.name)
end
end
local permissions = sam.permissions.get()
table.sort(permissions, sortFunc)
for k, v in ipairs(permissions) do
local item = permissions_body:add_item(v.name, v.category)
item:SetContentAlignment(4)
item:SetTextInset(6, 0)
item:SizeToContentsY(SUI.Scale(10))
item:SetZPos(k)
item.name = v.name
item.DoClick = item_click
local img = item:Add("SAM.Image")
img:Dock(RIGHT)
img:DockMargin(4, 4, 4, 4)
img:InvalidateParent(true)
img:SetWide(img:GetTall())
img:SetImageColor(Color(52, 161, 224))
img:SetImage("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/check_mark.png")
item.img = img
end
end
local limits_body
do
local permissions_search = right_body:Add("SAM.TextEntry")
permissions_search:Dock(TOP)
permissions_search:DockMargin(0, 0, 5, 10)
permissions_search:SetNoBar(true)
permissions_search:SetPlaceholder("Search...")
permissions_search:SetRadius(4)
permissions_search:SetTall(30)
function permissions_search:OnValueChange(text)
if limits_body and limits_body:IsVisible() then
local children = limits_body:GetCanvas():GetChildren()
for k, v in ipairs(children) do
v:AnimatedSetVisible(v.title:find(text, nil, true) ~= nil)
end
limits_body:InvalidateLayout(true)
else
permissions_body:Search(text)
end
end
Line(right_body):SetZPos(2)
end
local function load_limits()
if sam.limit_types then
if limits_body then return end
else
if limits_body then
limits_body:SetVisible(false)
permissions_body:AnimatedSetVisible(true)
limits_body:Remove()
limits_body = nil
end
return
end
limits_body = right_body:Add("SAM.ScrollPanel")
limits_body:Dock(FILL)
limits_body:GetCanvas():DockPadding(0, 0, 5, 0)
limits_body:SetVisible(false)
local item_enter = function(s)
if not IsValid(current_rank) then return end
local rank = current_rank.name
local limit = math.Clamp(s:GetValue(), -1, 1000)
if limit ~= sam.ranks.get_limit(rank, s.limit_type) then
RunConsoleCommand("sam", "changeranklimit", rank, s.limit_type, limit)
else
s:SetText(tostring(sam.ranks.get_limit(rank, s.limit_type)))
end
end
local not_empty = function(s)
return s and s ~= ""
end
local limit_values = {}
for k, v in ipairs(sam.limit_types) do
local immunity = limits_body:Add("SAM.LabelPanel")
immunity:SetLabel(v)
immunity:DockMargin(5, 0, 0, 5)
local entry = immunity:Add("SAM.TextEntry")
entry:SetSize(60, 26)
entry:SetNumeric(true)
entry:DisallowFloats(true)
entry:SetPlaceholder("")
entry:SetCheck(not_empty)
entry.limit_type = v
entry.OnEnter = item_enter
table.insert(limit_values, entry)
end
function limits_body:Refresh()
if not IsValid(current_rank) then return end
local rank = current_rank.name
for k, v in ipairs(limit_values) do
v:SetValue(tostring(sam.ranks.get_limit(rank, v.limit_type)))
end
end
local right_current_rank = right_body:Add("SAM.Button")
right_current_rank:Dock(BOTTOM)
right_current_rank:DockMargin(0, 5, 0, 0)
right_current_rank:SetFont(CREATE_RANK)
right_current_rank:SetText("Switch to Limits")
right_current_rank:On("DoClick", function()
limits_body:AnimatedToggleVisible()
permissions_body:AnimatedToggleVisible()
if permissions_body:AnimatedIsVisible() then
right_current_rank:SetText("Switch to Limits")
else
right_current_rank:SetText("Switch to Permissions")
end
end)
limits_body:On("OnRemove", function()
right_current_rank:Remove()
end)
limits_body:Refresh()
end
local function refresh_all()
timer.Create("SAM.Menu.Ranks.Refresh", 1, 1, function()
load_limits()
refresh_permissions()
refresh_access()
end)
end
sam.config.hook({"Restrictions.Limits"}, refresh_all)
for k, v in ipairs({"SAM.AddedPermission", "SAM.PermissionModified", "SAM.RemovedPermission"}) do
hook.Add(v, "SAM.Menu.RefreshPermissions", refresh_all)
end
local body = parent:Add("SAM.ScrollPanel")
body:Dock(FILL)
body:DockMargin(10, 0, 5, 10)
body:SetVBarPadding(6)
body:Line():SetZPos(-101)
local select_rank = function(s)
if not IsValid(s) then
current_rank = nil
right_body:SizeTo(0, -1, 0.3)
return
end
if IsValid(current_rank) then
current_rank.Selected = false
if current_rank == s then
current_rank = nil
right_body:SizeTo(0, -1, 0.3)
return
end
end
s.Selected = true
current_rank = s
refresh_access()
if limits_body then
limits_body:Refresh()
end
right_body:SizeTo(SUI.Scale(300), -1, 0.3)
rank_title:SetText(s.name)
rank_title:SizeToContents()
end
local ranks = {}
function search_entry:OnValueChange()
local value = self:GetValue()
for k, v in pairs(ranks) do
local show = k:find(value, nil, true)
show = show ~= nil
v.line:AnimatedSetVisible(show)
v:GetParent():AnimatedSetVisible(show)
end
end
local add_rank = function(rank_name, data)
if rank_name == "superadmin" then return end
if not IsValid(body) then return end
local line = body:Add("SAM.Panel")
line:Dock(TOP)
line:DockMargin(0, 0, 0, 10)
line:SetTall(34)
line:SetZPos(-data.immunity)
line:InvalidateLayout(true)
local container = line:Add("SAM.Button")
container:Dock(FILL)
container:DockMargin(0, 0, 5, 0)
container:DockPadding(5, 5, 0, 5)
container:SetText("")
container:SetContained(false)
container.name = rank_name
ranks[rank_name] = container
container:On("DoClick", select_rank)
function container:DoRightClick()
rank_name = container.name
if rank_name == "user" then return end
local dmenu = vgui.Create("SAM.Menu")
dmenu:SetSize(w, h)
dmenu:SetInternal(container)
dmenu:AddOption("Edit Rank", function()
rank_menu(rank_name, sam.ranks.get_rank(rank_name))
end)
if not sam.ranks.is_default_rank(rank_name) then
dmenu:AddSpacer()
dmenu:AddOption("Remove Rank", function()
local remove_rank = vgui.Create("SAM.QueryBox")
remove_rank:SetWide(350)
local check = remove_rank:Add("SAM.Label")
check:SetText("Are you sure that you want to remove '" .. rank_name .. "'?")
check:SetFont("SAMLine")
check:SetWrap(true)
check:SetAutoStretchVertical(true)
remove_rank:Done()
remove_rank.save:SetEnabled(true)
remove_rank.save:SetText("REMOVE")
remove_rank.save:SetContained(false)
remove_rank.save:SetColors(GetColor("query_box_cancel"), GetColor("query_box_cancel_text"))
remove_rank.cancel:SetContained(true)
remove_rank.cancel:SetColors()
remove_rank:SetCallback(function()
RunConsoleCommand("sam", "removerank", rank_name)
end)
end)
end
dmenu:Open()
dmenu:SetPos(input.GetCursorPos())
end
do
local name = container:Add("SAM.Label")
name:Dock(TOP)
name:DockMargin(0, 0, 0, 2)
name:SetTextColor(GetColor("player_list_names"))
name:SetFont(RANK_NAME)
name:SetText(rank_name)
name:SizeToContents()
local immunity = container:Add("SAM.Label")
immunity:Dock(TOP)
immunity:SetTextColor(GetColor("player_list_steamid"))
immunity:SetFont(RANK_INFO)
immunity:SetText("Immunity: " .. data.immunity)
immunity:SizeToContents()
local banlimit = container:Add("SAM.Label")
banlimit:Dock(TOP)
banlimit:SetTextColor(GetColor("player_list_steamid"))
banlimit:SetFont(RANK_INFO)
banlimit:SetText("Ban limit: " .. sam.reverse_parse_length(sam.parse_length(data.ban_limit)))
banlimit:SizeToContents()
local inherit = container:Add("SAM.Label")
inherit:Dock(TOP)
inherit:SetTextColor(GetColor("player_list_steamid"))
inherit:SetFont(RANK_INFO)
inherit:SetText("Inherits from: " .. (sam.isstring(data.inherit) and data.inherit or "none"))
inherit:SizeToContents()
end
container:InvalidateLayout(true)
container:SizeToChildren(false, true)
line:SizeToChildren(false, true)
local _line = body:Line()
_line:SetZPos(-data.immunity)
container.line = _line
container.data = data
end
for rank_name, v in pairs(sam.ranks.get_ranks()) do
add_rank(rank_name, v)
end
hook.Add("SAM.AddedRank", "SAM.RefreshRanksList", function(name, rank)
add_rank(name, rank)
end)
hook.Add("SAM.RemovedRank", "SAM.RefreshRanksList", function(name)
local line = ranks[name]
if not IsValid(line) then return end
line.line:Remove()
line:GetParent():Remove()
ranks[name] = nil
if line == current_rank then
select_rank()
end
end)
-- This is just better than caching panels for stuff that ain't gonna be called a lot
hook.Add("SAM.RankNameChanged", "SAM.RefreshRanksList", function(name, new_name)
local line = ranks[name]
if not IsValid(line) then return end
-- if current_rank == name then
-- rank_name:SetText(new_name)
-- end
line:GetChildren()[1]:SetText(new_name)
ranks[new_name], ranks[name] = line, nil
line.name = new_name
end)
hook.Add("SAM.RankImmunityChanged", "SAM.RefreshRanksList", function(name, immunity)
local line = ranks[name]
if not IsValid(line) then return end
line:GetChildren()[2]:SetText("Immunity: " .. immunity)
line:GetParent():SetZPos(-immunity)
-- SetZPos is kinda weird to deal with
line.line:SetZPos(-immunity + 1)
line.line:SetZPos(-immunity)
end)
hook.Add("SAM.RankBanLimitChanged", "SAM.RefreshRanksList", function(name, new_limit)
local line = ranks[name]
if IsValid(line) then
line:GetChildren()[3]:SetText("Ban limit: " .. sam.reverse_parse_length(new_limit))
end
end)
hook.Add("SAM.ChangedInheritRank", "SAM.RefreshRanksList", function(name, new_inherit)
local line = ranks[name]
if IsValid(line) then
line:GetChildren()[4]:SetText("Inherits from: " .. new_inherit)
end
end)
return parent
end, function()
return LocalPlayer():HasPermission("manage_ranks")
end, 3)