--[[ | 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()