mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
486 lines
12 KiB
Lua
486 lines
12 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
|
|
|
|
-- DONT EVER TALK TO ME ABOUT THIS CODE
|
|
|
|
local sam, command = sam, sam.command
|
|
|
|
command.set_category("Voting")
|
|
|
|
local start_vote, end_vote
|
|
if SERVER then
|
|
local vote_on = false
|
|
local options, players_voted
|
|
|
|
local shuffle = function(tbl) -- https://gist.github.com/Uradamus/10323382
|
|
for i = #tbl, 2, -1 do
|
|
local j = math.random(i)
|
|
tbl[i], tbl[j] = tbl[j], tbl[i]
|
|
end
|
|
return tbl
|
|
end
|
|
|
|
end_vote = function(ply, callback)
|
|
if not vote_on then
|
|
return ply:sam_add_text(color_white, "There is no vote to end.")
|
|
end
|
|
|
|
vote_on = false
|
|
|
|
sam.set_global("Vote", nil)
|
|
|
|
if callback then
|
|
local tbl = {}
|
|
local total_count = 0
|
|
|
|
for i = 1, #options do
|
|
local count = sam.get_global("Votings" .. i)
|
|
total_count = total_count + count
|
|
table.insert(tbl, {i, count})
|
|
sam.set_global("Votings" .. i, nil)
|
|
end
|
|
|
|
if total_count == 0 then
|
|
return sam.player.add_text(nil, color_white, "The vote have been canceled because nobody voted.")
|
|
end
|
|
|
|
table.sort(shuffle(tbl), function(a,b) return a[2] > b[2] end)
|
|
|
|
local v = tbl[1]
|
|
local winner, count = v[1], v[2]
|
|
|
|
callback(winner, options[winner], count, total_count)
|
|
else
|
|
for i = 1, #options do
|
|
sam.set_global("Votings" .. i, nil)
|
|
end
|
|
end
|
|
|
|
options, players_voted = nil, nil
|
|
|
|
timer.Remove("SAM.Vote")
|
|
end
|
|
|
|
start_vote = function(ply, callback, title, ...)
|
|
if vote_on then
|
|
return ply:sam_add_text(color_white, "There is an active vote, wait for it to finish.")
|
|
end
|
|
|
|
vote_on = true
|
|
|
|
options, players_voted = {}, {}
|
|
|
|
local args, n = {...}, select("#", ...)
|
|
for i = 1, n do
|
|
local v = args[i]
|
|
if v then
|
|
table.insert(options, v)
|
|
end
|
|
end
|
|
|
|
sam.set_global("Vote", {title, options, CurTime()})
|
|
|
|
for k in ipairs(options) do
|
|
sam.set_global("Votings" .. k, 0)
|
|
end
|
|
|
|
timer.Create("SAM.Vote", 25, 1, function()
|
|
end_vote(ply, callback)
|
|
end)
|
|
|
|
return true
|
|
end
|
|
|
|
sam.netstream.Hook("Vote", function(ply, index)
|
|
if not sam.isnumber(index) or index > 5 then return end
|
|
|
|
local votings = sam.get_global("Votings" .. index)
|
|
if not votings then return end
|
|
|
|
local old_index = players_voted[ply:AccountID()]
|
|
if old_index == index then return end
|
|
|
|
if old_index then
|
|
sam.set_global("Votings" .. old_index, sam.get_global("Votings" .. old_index) - 1)
|
|
end
|
|
|
|
sam.set_global("Votings" .. index, votings + 1)
|
|
|
|
players_voted[ply:AccountID()] = index
|
|
end)
|
|
end
|
|
|
|
if CLIENT then
|
|
local SUI = sam.SUI
|
|
-- https://github.com/Facepunch/garrysmod/blob/master/garrysmod/lua/includes/extensions/client/player.lua
|
|
|
|
local VOTING_TITLE = SUI.CreateFont("VotingTitle", "Roboto Bold", 15)
|
|
local VOTING_OPTION = SUI.CreateFont("VotingTitle", "Roboto Medium", 14)
|
|
|
|
local bind_translation = {}
|
|
for i = 0, 9 do
|
|
bind_translation["slot" .. i] = i
|
|
end
|
|
|
|
local voting_frame
|
|
|
|
end_vote = function()
|
|
if IsValid(voting_frame) then
|
|
voting_frame:Remove()
|
|
end
|
|
hook.Remove("PlayerBindPress", "SAM.Voting")
|
|
hook.Remove("SAM.ChangedGlobalVar", "SAM.VotingCount")
|
|
end
|
|
|
|
hook.Add("SAM.ChangedGlobalVar", "Voting", function(key, value)
|
|
if key ~= "Vote" then return end
|
|
|
|
if not value then
|
|
end_vote()
|
|
return
|
|
end
|
|
|
|
local title, options, start_time = value[1], value[2], value[3]
|
|
|
|
sui.TDLib.Start()
|
|
|
|
voting_frame = vgui.Create("EditablePanel")
|
|
voting_frame:SetSize(SUI.Scale(165), SUI.Scale(230))
|
|
voting_frame:SetPos(5, ScrH() * 0.25)
|
|
voting_frame:DockPadding(4, 4, 4, 4)
|
|
voting_frame:Blur()
|
|
:Background(Color(30, 30, 30, 240))
|
|
|
|
local voting_title = voting_frame:Add("SAM.Label")
|
|
voting_title:Dock(TOP)
|
|
voting_title:SetFont(VOTING_TITLE)
|
|
voting_title:TextColor(Color(220, 220, 220))
|
|
voting_title:SetText(title)
|
|
voting_title:SetWrap(true)
|
|
voting_title:SetAutoStretchVertical(true)
|
|
|
|
local line = voting_frame:Add("SAM.Label")
|
|
line:Dock(TOP)
|
|
line:TextColor(Color(220, 220, 220))
|
|
line:SetText("-")
|
|
|
|
local options_added = {}
|
|
for i, v in ipairs(options) do
|
|
local option = voting_frame:Add("SAM.Label")
|
|
option:Dock(TOP)
|
|
option:SetFont(VOTING_OPTION)
|
|
option:TextColor(Color(220, 220, 220), true)
|
|
option:SetText(i .. ". " .. v .. " (0)")
|
|
option:SetWrap(true)
|
|
option:SetAutoStretchVertical(true)
|
|
|
|
options_added[i] = option
|
|
end
|
|
|
|
function voting_frame:Think() -- fucking gmod
|
|
self:SizeToChildren(false, true)
|
|
|
|
local time_left = math.floor(25 - (CurTime() - start_time))
|
|
if time_left <= 0 then
|
|
end_vote()
|
|
voting_frame.Think = nil
|
|
return
|
|
end
|
|
|
|
voting_title:SetText(title .. " (" .. time_left .. ")")
|
|
end
|
|
|
|
line = voting_frame:Add("SAM.Label")
|
|
line:Dock(TOP)
|
|
line:TextColor(Color(220, 220, 220))
|
|
line:SetText("-")
|
|
|
|
local option = voting_frame:Add("SAM.Label")
|
|
option:Dock(TOP)
|
|
option:SetFont(VOTING_OPTION)
|
|
option:TextColor(Color(220, 220, 220), true)
|
|
option:SetText("0. Close")
|
|
option:SetWrap(true)
|
|
option:SetAutoStretchVertical(true)
|
|
|
|
sui.TDLib.End()
|
|
|
|
local current_index
|
|
hook.Add("PlayerBindPress", "SAM.Voting", function(_, bind, down)
|
|
if not down then return end
|
|
|
|
local index = bind_translation[bind]
|
|
if not index then return end
|
|
|
|
if index == 0 then
|
|
end_vote()
|
|
return true
|
|
end
|
|
|
|
if not options[index] then return true end
|
|
|
|
if current_index then
|
|
options_added[current_index]:TextColor(Color(220, 220, 220), true)
|
|
end
|
|
|
|
options_added[index]:TextColor(Color(65, 185, 255), true)
|
|
current_index = index
|
|
|
|
sam.netstream.Start("Vote", index)
|
|
|
|
return true
|
|
end)
|
|
|
|
hook.Add("SAM.ChangedGlobalVar", "SAM.VotingCount", function(key2, count)
|
|
if key2:sub(1, 7) ~= "Votings" then return end
|
|
if not count then return end
|
|
|
|
local index = tonumber(key2:sub(8))
|
|
options_added[index]:SetText(index .. ". " .. options[index] .. " (" .. count .. ")")
|
|
end)
|
|
end)
|
|
end
|
|
|
|
local vote_check = function(str)
|
|
return str:match("%S") ~= nil
|
|
end
|
|
|
|
command.new("vote")
|
|
:SetPermission("vote", "admin")
|
|
|
|
:AddArg("text", {hint = "title", check = vote_check})
|
|
:AddArg("text", {hint = "option", check = vote_check})
|
|
:AddArg("text", {hint = "option", check = vote_check})
|
|
:AddArg("text", {hint = "option", optional = true, check = vote_check})
|
|
:AddArg("text", {hint = "option", optional = true, check = vote_check})
|
|
:AddArg("text", {hint = "option", optional = true, check = vote_check})
|
|
|
|
:Help("Start a vote!")
|
|
|
|
:OnExecute(function(ply, title, ...)
|
|
local callback = function(_, option, count, total_count)
|
|
sam.player.send_message(nil, "Vote {V} for {V_2} has been passed. ({V_3}/{V_4})", {
|
|
V = title, V_2 = option, V_3 = count, V_4 = total_count
|
|
})
|
|
end
|
|
|
|
if start_vote(ply, callback, title, ...) then
|
|
sam.player.send_message(nil, "{A} started a vote with title {V}.", {
|
|
A = ply, V = title
|
|
})
|
|
end
|
|
end)
|
|
:End()
|
|
|
|
command.new("endvote")
|
|
:SetPermission("endvote", "admin")
|
|
|
|
:Help("End current vote.")
|
|
|
|
:OnExecute(function(ply)
|
|
end_vote(ply)
|
|
end)
|
|
:End()
|
|
|
|
command.new("votekick")
|
|
:SetPermission("votekick", "admin")
|
|
|
|
:AddArg("player", {single_target = true})
|
|
:AddArg("text", {hint = "reason", optional = true})
|
|
|
|
:GetRestArgs()
|
|
|
|
:Help("Start a vote to kick a player.")
|
|
|
|
:OnExecute(function(ply, targets, reason)
|
|
local target = targets[1]
|
|
local target_name = target:Name()
|
|
|
|
local callback = function(index, option, count, total_count)
|
|
if not IsValid(ply) then
|
|
sam.player.send_message(nil, "Vote was canceled because {T} left.", {
|
|
T = target_name
|
|
})
|
|
return
|
|
end
|
|
|
|
if index == 1 then
|
|
target:Kick("Vote was successful (" .. (reason or "none") .. ")")
|
|
|
|
sam.player.send_message(nil, "Vote was successful, {T} has been kicked. ({V})", {
|
|
T = targets, V = reason
|
|
})
|
|
else
|
|
sam.player.send_message(nil, "Vote was unsuccessful, {T} won't be kicked.", {
|
|
T = target_name
|
|
})
|
|
end
|
|
end
|
|
|
|
local title = "Kick " .. target_name .. "?"
|
|
if reason then
|
|
title = title .. " (" .. reason .. ")"
|
|
end
|
|
|
|
if start_vote(ply, callback, title, "Yes", "No") then
|
|
if reason then
|
|
sam.player.send_message(nil, "{A} started a votekick against {T} ({V})", {
|
|
A = ply, T = targets, V = reason
|
|
})
|
|
else
|
|
sam.player.send_message(nil, "{A} started a votekick against {T}", {
|
|
A = ply, T = targets
|
|
})
|
|
end
|
|
end
|
|
end)
|
|
:End()
|
|
|
|
command.new("voteban")
|
|
:SetPermission("voteban", "admin")
|
|
|
|
:AddArg("player", {single_target = true})
|
|
:AddArg("length", {optional = true, default = 60, min = 30, max = 120})
|
|
:AddArg("text", {hint = "reason", optional = true})
|
|
|
|
:GetRestArgs()
|
|
|
|
:Help("Start a vote to ban a player.")
|
|
|
|
:OnExecute(function(ply, targets, length, reason)
|
|
local target = targets[1]
|
|
local target_steamid, target_name = target:SteamID(), target:Name()
|
|
local ply_steamid = ply:SteamID()
|
|
|
|
local callback = function(index, option, count, total_count)
|
|
if index == 1 then
|
|
sam.player.ban_id(target_steamid, length, "Vote was successful (" .. (reason or "none") .. ")", ply_steamid)
|
|
|
|
sam.player.send_message(nil, "Vote was successful, {T} has been banned. ({V})", {
|
|
T = target_name, V = reason
|
|
})
|
|
else
|
|
sam.player.send_message(nil, "Vote was unsuccessful, {T} won't be banned.", {
|
|
T = target_name
|
|
})
|
|
end
|
|
end
|
|
|
|
local title = "Ban " .. target_name .. "?"
|
|
if reason then
|
|
title = title .. " (" .. reason .. ")"
|
|
end
|
|
|
|
if start_vote(ply, callback, title, "Yes", "No") then
|
|
if reason then
|
|
sam.player.send_message(nil, "{A} started a voteban against {T} for {V} ({V_2})", {
|
|
A = ply, T = targets, V = sam.format_length(length), V_2 = reason
|
|
})
|
|
else
|
|
sam.player.send_message(nil, "{A} started a voteban against {T} for {V}", {
|
|
A = ply, T = targets, V = sam.format_length(length)
|
|
})
|
|
end
|
|
end
|
|
end)
|
|
:End()
|
|
|
|
command.new("votemute")
|
|
:SetPermission("votemute", "admin")
|
|
|
|
:AddArg("player", {single_target = true})
|
|
:AddArg("text", {hint = "reason", optional = true})
|
|
|
|
:GetRestArgs()
|
|
|
|
:Help("Start a vote to mute and gag a player.")
|
|
|
|
:OnExecute(function(ply, targets, reason)
|
|
local _reason = reason and (" (" .. reason .. ")") or ""
|
|
|
|
local target = targets[1]
|
|
local target_name = target:Name()
|
|
|
|
local callback = function(index, option, count, total_count)
|
|
if not IsValid(target) then
|
|
sam.player.send_message(nil, "Vote was canceled because {T} left.", {
|
|
T = target_name
|
|
})
|
|
return
|
|
end
|
|
|
|
if index == 1 then
|
|
RunConsoleCommand("sam", "mute", "#" .. target:EntIndex(), 0, "votemute" .. _reason)
|
|
RunConsoleCommand("sam", "gag", "#" .. target:EntIndex(), 0, "votemute" .. _reason)
|
|
|
|
sam.player.send_message(nil, "Vote was successful, {T} has been muted. ({V})", {
|
|
T = target_name, V = reason
|
|
})
|
|
else
|
|
sam.player.send_message(nil, "Vote was unsuccessful, {T} won't be muted.", {
|
|
T = target_name
|
|
})
|
|
end
|
|
end
|
|
|
|
local title = "Mute " .. target_name .. "?" .. _reason
|
|
if start_vote(ply, callback, title, "Yes", "No") then
|
|
if reason then
|
|
sam.player.send_message(nil, "{A} started a votemute against {T} ({V}).", {
|
|
A = ply, T = targets, V = reason
|
|
})
|
|
else
|
|
sam.player.send_message(nil, "{A} started a votemute against {T}.", {
|
|
A = ply, T = targets
|
|
})
|
|
end
|
|
end
|
|
end)
|
|
:End()
|
|
|
|
command.new("votemap")
|
|
:SetPermission("votemap", "admin")
|
|
|
|
:AddArg("map", {exclude_current = true})
|
|
:AddArg("map", {optional = true, exclude_current = true})
|
|
:AddArg("map", {optional = true, exclude_current = true})
|
|
|
|
:GetRestArgs()
|
|
|
|
:Help("Start a vote to change map.")
|
|
|
|
:OnExecute(function(ply, ...)
|
|
local callback = function(_, option, count, total_count)
|
|
sam.player.send_message(nil, "Map vote for {V} has been passed. ({V_2}/{V_3})", {
|
|
V = option, V_2 = count, V_3 = total_count
|
|
})
|
|
|
|
if sam.is_valid_map(option) then
|
|
RunConsoleCommand("sam", "map", option)
|
|
end
|
|
end
|
|
|
|
local args = {...}
|
|
for i = select("#", ...), 1, -1 do
|
|
if args[i] == "None" then
|
|
args[i] = nil
|
|
end
|
|
end
|
|
table.insert(args, "Extend Current Map")
|
|
|
|
if start_vote(ply, callback, "Vote for the next map!", unpack(args)) then
|
|
sam.player.send_message(nil, "{A} started a map change vote.", {
|
|
A = ply
|
|
})
|
|
end
|
|
end)
|
|
:End() |