Files
wnsrc/addons/sam-master/lua/sam/command/arguments/player.lua
lifestorm ba1fc01b16 Upload
2024-08-04 23:12:27 +03:00

456 lines
11 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
local sam, command = sam, sam.command
local can_target_player = function(arg, admin, target, cmd, input)
if not IsValid(target) or not target:IsPlayer() or not target:sam_get_nwvar("is_authed") then
if input then
admin:sam_send_message("cant_find_target", {
S = input
})
end
return false
end
if not arg.allow_higher_target and not admin:CanTarget(target) then
if cmd then
admin:sam_send_message("cant_target_player", {
S = target:Name()
})
end
return false
end
if arg.cant_target_self and admin == target then
if cmd then
admin:sam_send_message("cant_target_self", {
S = cmd.name
})
end
return false
end
return true
end
local check_text_match = function(text, ply)
if ply:Name():lower():find(text, 1, true) then return true end
if ply:sam_getrank():lower():find(text, 1, true) then return true end
if team.GetName(ply:Team()):lower():find(text, 1, true) then return true end
if not ply:IsBot() then
return ply:SteamID():lower():find(text, 1, true) or ply:SteamID64():lower():find(text, 1, true)
end
return false
end
command.new_argument("player")
:OnExecute(function(arg, input, ply, cmd, result, n)
if input == nil and arg.optional then
if sam.isconsole(ply) then
ply:sam_send_message("cant_target_self", {
S = cmd.name
})
return false
end
result[n] = {ply, admin = ply, input = input}
return
end
local single_target = arg.single_target
local targets = {admin = ply, input = input}
if input == "*" then
if single_target then
ply:sam_send_message("cant_target_multi_players")
return false
end
local players = player.GetAll()
for i = 1, #players do
local v = players[i]
if can_target_player(arg, ply, v) then
table.insert(targets, v)
end
end
elseif input:sub(1, 1) == "#" and not single_target then
local tmp = {}
for _, v in ipairs(input:sub(2):Trim():Split(",")) do
v = tonumber(v)
if not sam.isnumber(v) then continue end
local target = Entity(v)
if not tmp[target] and IsValid(target) and target:IsPlayer() then
tmp[target] = true
if can_target_player(arg, ply, target) then
table.insert(targets, target)
end
end
end
else
local target
if input == "^" then
target = ply
elseif input == "@" and not sam.isconsole(ply) then
target = ply:GetEyeTrace().Entity
elseif sam.is_steamid(input) then
target = player.GetBySteamID(input)
elseif sam.is_steamid64(input) then
target = player.GetBySteamID64(input)
elseif input:sub(1, 1) == "#" then
local index = input:sub(2):Trim()
index = tonumber(index)
if not isnumber(index) then
ply:sam_send_message("invalid_id", {
S = input
})
return false
end
target = Entity(index)
if not IsValid(target) or not target:IsPlayer() then
ply:sam_send_message("player_id_not_found", {
S = index
})
return false
end
else
if input:sub(1, 1) == "%" and #input > 1 then
input = input:sub(2)
end
target = sam.player.find_by_name(input)
if sam.istable(target) then
if single_target then
ply:sam_send_message("found_multi_players", {T = target})
return false
else
for k, v in ipairs(target) do
if can_target_player(arg, ply, v) then
table.insert(targets, v)
end
end
goto _end
end
end
end
if not can_target_player(arg, ply, target, cmd, input) then
return false
end
table.insert(targets, target)
end
::_end::
if #targets == 0 then
ply:sam_send_message("cant_find_target", {
S = input
})
return false
end
result[n] = targets
end)
-- Do NOT ask me about this code at all please because I feel shit about it but I'm not gonna make
-- a file specially for this one
:Menu(function(set_result, body, buttons, argument, childs)
if body.ply_list then
local ply_list = body.ply_list
ply_list.argument = argument
ply_list.set_result = set_result
ply_list.multi_select = argument.single_target ~= true
if argument.single_target == true and #ply_list:GetSelected() > 1 then
ply_list:ClearSelection()
end
ply_list:OnRowSelected()
ply_list:GetParent():Show()
return
end
local SUI = sam.SUI
local SetVisible = FindMetaTable("Panel").SetVisible
local left_body = body:Add("SAM.Panel")
left_body:Dock(LEFT)
left_body:DockMargin(0, 0, 5, 0)
left_body:SetWide(0)
left_body.no_remove = true
left_body.no_change = "player"
SetVisible(left_body, false)
left_body.SetVisible = function(s, visible)
if visible == s:IsVisible() or visible == s.visible_state then return end
if visible then
SetVisible(s, true)
s:InvalidateLayout(true)
end
s.visible_state = visible
s:Stop()
s:SizeTo(visible and SUI.Scale(320) or 0, -1, 0.2, 0, 0, function()
SetVisible(s, visible)
s:InvalidateParent(true)
end)
end
left_body:Show()
table.insert(childs, left_body)
local ply_list = left_body:Add("SAM.ScrollPanel")
ply_list:Dock(FILL)
ply_list:Background(Color(34, 34, 34), 3)
ply_list.argument = argument
ply_list.set_result = set_result
ply_list.multi_select = argument.single_target ~= true
ply_list.Paint = function(s, w, h)
s:RoundedBox("Background", 3, 0, 0, w, h, SUI.GetColor("text_entry_bg"))
end
local lines = {}
function ply_list:OnClickLine(line, clear)
local multi_select = ply_list.multi_select
if not multi_select and not clear then return end
if multi_select and input.IsKeyDown(KEY_LCONTROL) then
if line.Selected then
line.Selected = false
self.main_selected_line = nil
self:OnRowSelected()
return
end
clear = false
end
if multi_select and input.IsKeyDown(KEY_LSHIFT) then
local selected = self:GetSelectedLine()
if selected then
self.main_selected_line = self.main_selected_line or selected
if clear then
self:ClearSelection()
end
local first = math.min(self.main_selected_line.id, line.id)
local last = math.max(self.main_selected_line.id, line.id)
for id = first, last do
local line_2 = lines[id]
local was_selected = line_2.Selected
line_2.Selected = true
if not was_selected then
self:OnRowSelected(line_2.id, line_2)
end
end
return
end
end
if not multi_select or clear then
self:ClearSelection()
end
line.Selected = true
self.main_selected_line = line
self:OnRowSelected(line.id, line)
end
function ply_list:GetSelected()
local ret = {}
for _, v in ipairs(lines) do
if v.Selected then
table.insert(ret, v)
end
end
return ret
end
function ply_list:GetSelectedLine()
for _, line in ipairs(lines) do
if line.Selected then return line end
end
end
function ply_list:ClearSelection()
for _, line in ipairs(lines) do
line.Selected = false
end
self:OnRowSelected()
end
function ply_list:OnRowSelected()
local plys = {}
for k, v in ipairs(ply_list:GetSelected()) do
plys[k] = v.ply:EntIndex()
end
if #plys == 0 then
self.set_result(nil)
else
self.set_result("#" .. table.concat(plys, ","))
end
end
function ply_list:OnRowRightClick(_, line)
local dmenu = vgui.Create("SAM.Menu")
dmenu:SetInternal(line)
local name = line.ply:Name()
dmenu:AddOption("Copy Name", function()
SetClipboardText(name)
end)
dmenu:AddSpacer()
local steamid = line.ply:SteamID()
dmenu:AddOption("Copy SteamID", function()
SetClipboardText(steamid)
end)
dmenu:AddOption("Copy SteamID64", function()
SetClipboardText(util.SteamIDTo64(steamid))
end)
dmenu:Open()
dmenu:SetPos(input.GetCursorPos())
end
local item_click = function(s)
ply_list:OnClickLine(s, true)
end
local item_rightclick = function(s)
if not s.Selected then
ply_list:OnClickLine(s, true)
end
ply_list:OnRowRightClick(s.id, s)
end
local item_cursor = function(s)
if input.IsMouseDown(MOUSE_LEFT) then
ply_list:OnClickLine(s)
end
end
local added_players = {}
local add_player = function(ply, i)
if can_target_player(ply_list.argument, LocalPlayer(), ply) then
local player_button = ply_list:Add("SAM.Button")
player_button:Dock(TOP)
player_button:DockMargin(0, 0, 0, 2)
player_button:DockPadding(4, 4, 4, 4)
player_button:SetContained(false)
player_button:SetText("")
player_button:SetZPos(i)
player_button.DoClick = item_click
player_button.DoRightClick = item_rightclick
player_button.OnCursorMoved = item_cursor
local line = player_button:Add("SAM.PlayerLine")
line:SetMouseInputEnabled(false)
line:SetInfo({
steamid = ply:IsBot() and "BOT" or ply:SteamID(),
name = ply:Name(),
rank = ply:sam_getrank()
})
player_button:InvalidateLayout(true)
player_button:SizeToChildren(false, true)
player_button.ply = ply
player_button.line = line
player_button.id = table.insert(lines, player_button)
body.search_entry:OnValueChange()
added_players[ply] = true
end
end
ply_list:On("Think", function()
local players = player.GetAll()
for i = 1, #players do
local ply = players[i]
if not added_players[ply] then
add_player(ply, i)
end
end
local argument = ply_list.argument
for i = 1, #lines do
local line = lines[i]
local ply = line.ply
if not can_target_player(argument, LocalPlayer(), ply) then
line:Remove()
table.remove(lines, i)
added_players[ply] = nil
ply_list:OnRowSelected()
break
end
line = line.line
line:SetName(ply:Name())
line:SetRank(ply:sam_getrank())
end
end)
local search_entry = left_body:Add("SAM.TextEntry")
search_entry:Dock(TOP)
search_entry:DockMargin(0, 0, 0, 5)
search_entry:SetPlaceholder("Search... (name/steamid/rank/job)")
search_entry:SetBackground(Color(34, 34, 34))
search_entry:SetTall(25)
search_entry:SetNoBar(true)
function search_entry:OnValueChange(text)
if text == nil then
text = self:GetValue()
end
if text ~= "" then
ply_list:ClearSelection()
end
text = text:lower()
for i, line in ipairs(lines) do
local ply = line.ply
if IsValid(ply) then
line:SetVisible(check_text_match(text, ply))
end
end
ply_list:GetCanvas():InvalidateLayout(true)
end
body.ply_list = ply_list
body.search_entry = search_entry
end)
:AutoComplete(function(arg, result, name)
local ply = LocalPlayer()
for k, v in ipairs(player.GetAll()) do
if can_target_player(arg, ply, v) and v:Name():lower():find(name, 1, true) then
table.insert(result, "%" .. v:Name())
end
end
end)
:End()