Files
wnsrc/lua/sam/reports/cl_reports.lua
lifestorm 9c918c46e5 Upload
2024-08-04 23:12:27 +03:00

480 lines
10 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 = sam
local netstream = sam.netstream
local SUI = sam.SUI
local config = sam.config
local Trim = string.Trim
local muted_var = CreateClientConVar("sam_mute_reports", "0", false, false, "", 0, 1)
local position = config.get_updated("Reports.Position", "Left")
local max_reports = config.get_updated("Reports.MaxReports", 4)
local always_show = config.get_updated("Reports.AlwaysShow", true)
local pad_x = config.get_updated("Reports.XPadding", 5)
local pad_y = config.get_updated("Reports.YPadding", 5)
local duty_jobs = {}
config.hook({"Reports.DutyJobs"}, function()
local jobs = config.get("Reports.DutyJobs", ""):Split(",")
for i = #jobs, 1, -1 do
local v = Trim(jobs[i])
if v ~= "" then
jobs[v] = true
end
jobs[i] = nil
end
duty_jobs = jobs
end)
local commands = {}
config.hook({"Reports.Commands"}, function()
local cmds = config.get("Reports.Commands", ""):Split(",")
for i = 1, #cmds do
local v = Trim(cmds[i])
if v ~= "" then
cmds[i] = {
name = v,
func = function(_, ply)
if IsValid(ply) then
RunConsoleCommand("sam", v, "#" .. ply:EntIndex())
end
end
}
end
end
commands = cmds
end)
local reports = {}
local queued_reports = {}
local new_report, remove_report, check_queued, get_report, append_report
get_report = function(ply, index)
for i = 1, #reports do
local v = reports[i]
local _ply = index and v.index or v.ply
if _ply == ply then return v end
end
for i = 1, #queued_reports do
local v = queued_reports[i]
local _ply = index and v.index or v.ply
if _ply == ply then return v, i end
end
end
remove_report = function(ply)
local report, delayed_i = get_report(ply)
if delayed_i then
return table.remove(queued_reports, delayed_i)
end
local panel = report.panel
panel:MoveToNewX(position.value == "Right" and ScrW() or -panel:GetWide(), function()
for i = report.pos + 1, #reports do
local v = reports[i]
v.pos = v.pos - 1
v.panel:MoveToNewY(v.panel:GetY())
end
panel:Remove()
table.remove(reports, report.pos)
check_queued()
end)
end
check_queued = function()
while (max_reports.value - #reports > 0 and #queued_reports > 0) do
new_report(table.remove(queued_reports, 1))
end
end
append_report = function(ply, text)
local report, delayed = get_report(ply)
if delayed then
table.insert(report.comments, text)
else
report.panel:AddComment(text)
end
end
new_report = function(report)
if #reports >= max_reports.value then
return table.insert(queued_reports, report)
end
report.pos = table.insert(reports, report)
local panel = vgui.Create("SAM.Report")
panel:SetReport(report)
for k, v in ipairs(commands) do
panel:AddButton(v.name:gsub("^%l", string.upper), v.func)
end
local claim = panel:AddButton("Claim", function(self, ply)
if panel:HasReport() then
return LocalPlayer():sam_send_message("You have an active case, close it first.")
end
self.DoClick = function()
end
local claim_query = netstream.async.Start("ClaimReport", nil, ply)
claim_query:done(function(claimed)
if not IsValid(panel) then return end
if claimed then
panel:SetHasReport(ply)
self:SetText("Close")
self.background = Color(231, 76, 60, 200)
self.hover = Color(255, 255, 255, 25)
panel:FixWide()
for k, v in ipairs(panel:GetChildren()[3]:GetChildren()) do
v:SetDisabled(false)
v:SetCursor("hand")
end
self.DoClick = function()
panel:Close()
end
else
panel:SetClaimed()
end
end)
end)
local dismiss = panel:AddButton("Dismiss", function(self, ply)
self.DoClick = function()
end
panel:Close()
netstream.Start("DismissReport", ply)
end)
panel.claim = claim
claim:SetCursor("hand")
claim:SetDisabled(false)
claim.background = Color(39, 174, 96, 200)
claim.hover = Color(255, 255, 255, 25)
panel.dismiss = dismiss
dismiss:SetCursor("hand")
dismiss:SetDisabled(false)
dismiss.background = Color(231, 76, 60, 200)
dismiss.hover = Color(255, 255, 255, 25)
panel:FixWide()
local x = pad_x.value
if position.value == "Right" then
x = (ScrW() - panel:GetWide()) - x
end
panel:MoveToNewX(x)
panel:MoveToNewY(panel:GetY())
panel.new = true
for k, v in ipairs(report.comments) do
panel:AddComment(v)
end
panel.new = nil
end
netstream.Hook("Report", function(ply, comment)
if not IsValid(ply) then return end
if muted_var:GetBool() then return end
local report = get_report(ply)
if not report then
report = {
ply = ply,
index = ply:EntIndex(),
comments = {comment}
}
system.FlashWindow()
if not always_show.value and not duty_jobs[team.GetName(LocalPlayer():Team())] then
LocalPlayer():sam_send_message("({S Blue}) {S_2 Red}: {S_3}", {
S = "Report", S_2 = ply:Name(), S_3 = comment
})
else
new_report(report)
end
else
append_report(ply, comment)
end
end)
netstream.Hook("ReportClaimed", function(ply)
local report, delayed = get_report(ply)
if not report then return end
if delayed then
table.remove(queued_reports, delayed)
else
report.panel:SetClaimed()
end
end)
netstream.Hook("ReportClosed", function(index)
local report, delayed = get_report(index, true)
if not report then return end
if delayed then
table.remove(queued_reports, delayed)
else
report.panel:SetClosed()
end
end)
do
local REPORTS_HEADER = SUI.CreateFont("ReportHeader", "Roboto", 14, 540)
local REPORT_COMMENT = SUI.CreateFont("ReportComment", "Roboto", 13, 540)
local REPORT_BUTTONS = SUI.CreateFont("ReportButtons", "Roboto", 13, 550)
local Panel = {}
function Panel:Init()
sui.TDLib.Start()
self:Blur()
:Background(Color(30, 30, 30, 240))
local p_w, p_h = SUI.Scale(350), SUI.Scale(145)
self:SetSize(p_w, p_h)
local x = p_w * 2
if position.value == "Right" then
x = ScrW() + x
else
x = -x
end
self:SetPos(x, -p_h)
local top_panel = self:Add("Panel")
top_panel:Dock(TOP)
top_panel:SetTall(SUI.Scale(24))
top_panel:Background(Color(60, 60, 60, 200))
local ply_name = top_panel:Add("DLabel")
ply_name:Dock(LEFT)
ply_name:DockMargin(5, 0, 0, 0)
ply_name:SetTextColor(Color(200, 200, 200))
ply_name:SetFont(REPORTS_HEADER)
self.ply_name = ply_name
local scroll = self:Add("SAM.ScrollPanel")
scroll:Dock(FILL)
scroll:DockMargin(5, 5, 5, 5)
scroll.Paint = nil
self.scroll = scroll
local comment = scroll:Add("DLabel")
comment:Dock(TOP)
comment:SetText("")
comment:SetTextColor(Color(200, 200, 200))
comment:SetFont(REPORT_COMMENT)
comment:SetMultiline(true)
comment:SetWrap(true)
comment:SetAutoStretchVertical(true)
self.comment = comment
local bottom = self:Add("Panel")
bottom:Dock(BOTTOM)
bottom:SetTall(SUI.Scale(24))
self.bottom = bottom
sui.TDLib.End()
end
function Panel:GetY()
return (self:GetTall() + 5) * (self.report.pos - 1) + pad_y.value
end
function Panel:Close()
remove_report(self.report.ply)
end
local change_state = function(self, text)
self.claim:SetText(text)
self.claim.DoClick = function() end
self.claim:SUI_TDLib()
:Background(Color(41, 128, 185, 200))
timer.Simple(5, function()
if IsValid(self) then
self:Close()
end
end)
if self:HasReport() == self.report.ply then
self:SetHasReport()
end
self:FixWide()
end
function Panel:SetClaimed()
change_state(self, "Case clamied!")
end
function Panel:SetClosed()
change_state(self, "Case closed!")
end
function Panel:SetReport(report)
surface.PlaySound("garrysmod/balloon_pop_cute.wav")
report.panel = self
self.report = report
self.ply_name:SetText(report.ply:Name() .. " (" .. report.ply:SteamName() .. ")")
self.ply_name:SetWide(self:GetWide())
end
local disabled = Color(60, 60, 60, 200)
local click = Color(255, 255, 255, 30)
local button_paint = function(self, w, h)
draw.RoundedBox(0, 0, 0, w, h, self.background)
if self:GetDisabled() then
draw.RoundedBox(0, 0, 0, w, h, disabled)
else
if self:IsHovered() then
draw.RoundedBox(0, 0, 0, w, h, self.hover)
end
if self.Depressed then
draw.RoundedBox(0, 0, 0, w, h, click)
end
end
end
local button_click = function(self)
self.cb(self, self.report.ply)
end
local background = Color(60, 60, 60, 200)
local hover = Color(14, 134, 204, 100)
function Panel:AddButton(text, cb)
local button = self.bottom:Add("DButton")
button:Dock(LEFT)
button:SetText(text)
button:SetTextColor(Color(200, 200, 200))
button:SetFont(REPORT_BUTTONS)
button:SetDisabled(true)
button:SetCursor("arrow")
button.Paint = button_paint
button.DoClick = button_click
button.background = background
button.hover = hover
button.cb = cb
button.report = self.report
return button
end
function Panel:FixWide()
local wide = 0
for _, v in ipairs(self.bottom:GetChildren()) do
v:SizeToContents()
v:SetWide(v:GetWide() + 6)
wide = wide + v:GetWide()
end
self:SetWide(wide)
return wide
end
function Panel:OnRemove()
local reporter = self:HasReport()
if reporter then
netstream.Start("CloseReport", reporter)
self:SetHasReport()
end
end
function Panel:AddComment(text)
local comment = self.comment
local old_text = comment:GetText()
if old_text ~= "" then
old_text = old_text .. "\n"
end
if not self.new then
surface.PlaySound("ambient/water/drip4.wav")
end
comment:SetText(old_text .. "- " .. text)
comment:SizeToContents()
self.scroll:ScrollToBottom()
end
function Panel:HasReport()
return LocalPlayer().sam_has_report
end
function Panel:SetHasReport(v)
LocalPlayer().sam_has_report = v
end
local new_animation = function(panel, name)
local new_name = "anim_" .. name
panel["MoveToNew" .. name:upper()] = function(self, new, cb)
if self[new_name] then
table.RemoveByValue(self.m_AnimList, self[new_name])
end
self[new_name] = self:NewAnimation(0.2, 0, -1, function()
self[new_name] = nil
if cb then cb() end
end)
self[new_name].Think = function(_, _, frac)
self[name] = Lerp(frac, self[name], new)
end
end
end
new_animation(Panel, "x")
new_animation(Panel, "y")
vgui.Register("SAM.Report", Panel, "EditablePanel")
end