mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-15 21:03:46 +03:00
456 lines
11 KiB
Lua
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() |