Initial commit

This commit is contained in:
pavetr
2026-03-15 14:54:49 +03:00
commit 64f8029c06
4027 changed files with 254888 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
local function IncludeFolder(fol)
fol = string.lower(fol)
local _, folders = file.Find(fol .. "*", "LUA")
for _, folder in SortedPairs(folders, true) do
if folder ~= "." and folder ~= ".." then
for _, File in SortedPairs(file.Find(fol .. folder .. "/sh_*.lua", "LUA"), true) do
include(fol .. folder .. "/" .. File)
end
for _, File in SortedPairs(file.Find(fol .. folder .. "/cl_*.lua", "LUA"), true) do
include(fol .. folder .. "/" .. File)
end
end
end
end
IncludeFolder(GM.FolderName .. "/gamemode/modules/fadmin/fadmin/")
IncludeFolder(GM.FolderName .. "/gamemode/modules/fadmin/fadmin/playeractions/")
--[[---------------------------------------------------------------------------
FAdmin global settings
---------------------------------------------------------------------------]]
net.Receive("FAdmin_GlobalSetting", function(len)
local setting, value = net.ReadString(), net.ReadType(net.ReadUInt(8))
FAdmin.GlobalSetting = FAdmin.GlobalSetting or {}
FAdmin.GlobalSetting[setting] = value
end)
net.Receive("FAdmin_PlayerSetting", function(len)
local uid, setting, value = net.ReadUInt(16), net.ReadString(), net.ReadType(net.ReadUInt(8))
FAdmin.PlayerSettings = FAdmin.PlayerSettings or {}
FAdmin.PlayerSettings[uid] = FAdmin.PlayerSettings[uid] or {}
FAdmin.PlayerSettings[uid][setting] = value
end)
timer.Create("FAdmin_CleanPlayerSettings", 300, 0, function()
if not FAdmin.PlayerSettings then return end
-- find highest userID
local max = math.huge
for _, v in ipairs(player.GetAll()) do
if IsValid(v) and v:UserID() > max then max = v:UserID() end
end
-- Anything lower than the maximal UserID can be culled
-- This prevents data from joining players from being removed
-- New players always get a strictly higher UserID than any player before them
for uid in pairs(FAdmin.PlayerSettings) do
if IsValid(Player(uid)) or uid > max then continue end
FAdmin.PlayerSettings[uid] = nil
end
end)
local plyMeta = FindMetaTable("Player")
function plyMeta:FAdmin_GetGlobal(setting)
local uid = self:UserID()
return FAdmin.PlayerSettings and FAdmin.PlayerSettings[uid] and FAdmin.PlayerSettings[uid][setting] or nil
end
net.Receive("FAdmin_GlobalPlayerSettings", function(len)
local globalCount = net.ReadUInt(8)
FAdmin.GlobalSetting = FAdmin.GlobalSetting or {}
for i = 1, globalCount do
FAdmin.GlobalSetting[net.ReadString()] = net.ReadType(net.ReadUInt(8))
end
local plyCount = net.ReadUInt(8)
FAdmin.PlayerSettings = FAdmin.PlayerSettings or {}
for i = 1, plyCount do
local uid = net.ReadUInt(16)
local count = net.ReadUInt(8)
FAdmin.PlayerSettings[uid] = FAdmin.PlayerSettings[uid] or {}
for j = 1, count do
FAdmin.PlayerSettings[uid][net.ReadString()] = net.ReadType(net.ReadUInt(8))
end
end
end)

View File

@@ -0,0 +1,99 @@
if not FAdmin or not FAdmin.StartHooks then return end
FAdmin.StartHooks["DarkRP"] = function()
-- DarkRP information:
FAdmin.ScoreBoard.Player:AddInformation("Money", function(ply) if LocalPlayer():IsAdmin() then return DarkRP.formatMoney(ply:getDarkRPVar("money")) end end)
FAdmin.ScoreBoard.Player:AddInformation("Steam name", function(ply) return ply:SteamName() end)
FAdmin.ScoreBoard.Player:AddInformation("Wanted", function(ply) if ply:getDarkRPVar("wanted") then return tostring(ply:getDarkRPVar("wantedReason") or "N/A") end end)
FAdmin.ScoreBoard.Player:AddInformation("Community link", function(ply) return FAdmin.SteamToProfile(ply) end)
FAdmin.ScoreBoard.Player:AddInformation("Rank", function(ply)
if FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "SeeAdmins") then
return ply:GetUserGroup()
end
end)
FAdmin.ScoreBoard.Player:AddInformation("Wanted reason", function(ply)
if ply:isWanted() and LocalPlayer():isCP() then
return ply:getWantedReason()
end
end)
-- Warrant
FAdmin.ScoreBoard.Player:AddActionButton("Warrant", "fadmin/icons/message", Color(0, 0, 200, 255),
function(ply) return LocalPlayer():isCP() end,
function(ply, button)
Derma_StringRequest("Warrant reason", "Enter the reason for the warrant", "", function(Reason)
RunConsoleCommand("darkrp", "warrant", ply:SteamID(), Reason)
end)
end)
--wanted
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
return ((ply:getDarkRPVar("wanted") and "Unw") or "W") .. "anted"
end,
function(ply) return "fadmin/icons/jail", ply:getDarkRPVar("wanted") and "fadmin/icons/disable" end,
Color(0, 0, 200, 255),
function(ply) return LocalPlayer():isCP() end,
function(ply, button)
if not ply:getDarkRPVar("wanted") then
Derma_StringRequest("wanted reason", "Enter the reason to arrest this player", "", function(Reason)
RunConsoleCommand("darkrp", "wanted", ply:SteamID(), Reason)
end)
else
RunConsoleCommand("darkrp", "unwanted", ply:UserID())
end
end)
--Teamban
local function teamban(ply, button)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Jobs:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
local command = "teamban"
local uid = ply:UserID()
for k, v in SortedPairsByMemberValue(RPExtraTeams, "name") do
local submenu = menu:AddSubMenu(v.name)
submenu:AddOption("2 minutes", function() RunConsoleCommand("darkrp", command, uid, k, 120) end)
submenu:AddOption("Half an hour", function() RunConsoleCommand("darkrp", command, uid, k, 1800) end)
submenu:AddOption("An hour", function() RunConsoleCommand("darkrp", command, uid, k, 3600) end)
submenu:AddOption("Until restart", function() RunConsoleCommand("darkrp", command, uid, k, 0) end)
end
menu:Open()
end
FAdmin.ScoreBoard.Player:AddActionButton("Ban from job", "fadmin/icons/changeteam", Color(200, 0, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "DarkRP_AdminCommands", ply) end, teamban)
local function teamunban(ply, button)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Jobs:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
local command = "teamunban"
local uid = ply:UserID()
for k, v in SortedPairsByMemberValue(RPExtraTeams, "name") do
menu:AddOption(v.name, function() RunConsoleCommand("darkrp", command, uid, k) end)
end
menu:Open()
end
FAdmin.ScoreBoard.Player:AddActionButton("Unban from job", function() return "fadmin/icons/changeteam", "fadmin/icons/disable" end, Color(200, 0, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "DarkRP_AdminCommands", ply) end, teamunban)
end

View File

@@ -0,0 +1,262 @@
local ContinueNewGroup
local EditGroups
local function RetrievePRIVS(len)
FAdmin.Access.Groups = net.ReadTable()
for k, v in pairs(FAdmin.Access.Groups) do
if CAMI.GetUsergroup(k) then continue end
CAMI.RegisterUsergroup({
Name = k,
Inherits = FAdmin.Access.ADMIN[v.ADMIN]
}, "FAdmin")
end
-- Remove any groups that are removed from FAdmin from CAMI.
for k in pairs(CAMI.GetUsergroups()) do
if FAdmin.Access.Groups[k] then continue end
CAMI.UnregisterUsergroup(k, "FAdmin")
end
end
net.Receive("FADMIN_SendGroups", RetrievePRIVS)
local function addPriv(um)
local group = um:ReadString()
FAdmin.Access.Groups[group] = FAdmin.Access.Groups[group] or {}
FAdmin.Access.Groups[group].PRIVS[um:ReadString()] = true
end
usermessage.Hook("FAdmin_AddPriv", addPriv)
local function removePriv(um)
FAdmin.Access.Groups[um:ReadString()].PRIVS[um:ReadString()] = nil
end
usermessage.Hook("FAdmin_RemovePriv", removePriv)
local function addGroupUI(ply, func)
Derma_StringRequest("Set name",
"What will be the name of the new group?",
"",
function(text)
if text == "" then return end
Derma_Query("On what access will this team be based? (the new group will inherit all the privileges from the group)", "Admin access",
"user", function() ContinueNewGroup(ply, text, 0, func) end,
"admin", function() ContinueNewGroup(ply, text, 1, func) end,
"superadmin", function() ContinueNewGroup(ply, text, 2, func) end)
end)
end
FAdmin.StartHooks["1SetAccess"] = function() -- 1 in hook name so it will be executed first.
FAdmin.Commands.AddCommand("setaccess", nil, "<Player>", "<Group name>", "[new group based on (number)]", "[new group privileges]")
FAdmin.ScoreBoard.Player:AddActionButton("Set access", "fadmin/icons/access", Color(155, 0, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "SetAccess") or LocalPlayer():IsSuperAdmin() end, function(ply)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Set access:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for k in SortedPairsByMemberValue(FAdmin.Access.Groups, "ADMIN", true) do
menu:AddOption(k, function()
if not IsValid(ply) then return end
RunConsoleCommand("_FAdmin", "setaccess", ply:UserID(), k)
end)
end
menu:AddOption("New...", function() addGroupUI(ply) end)
menu:Open()
end)
FAdmin.ScoreBoard.Server:AddPlayerAction("Edit groups", "fadmin/icons/access", Color(0, 155, 0, 255), function() return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "ManageGroups") or FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "ManagePrivileges") end, EditGroups)
-- Admin immunity
FAdmin.ScoreBoard.Server:AddServerSetting(function()
return (FAdmin.GlobalSetting.Immunity and "Disable" or "Enable") .. " Admin immunity"
end,
function()
return "fadmin/icons/access", FAdmin.GlobalSetting.Immunity and "fadmin/icons/disable"
end, Color(0, 0, 155, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "ManageGroups") end, function(button)
button:SetImage2((not FAdmin.GlobalSetting.Immunity and "fadmin/icons/disable") or "null")
button:SetText((not FAdmin.GlobalSetting.Immunity and "Disable" or "Enable") .. " Admin immunity")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_Fadmin", "immunity", (FAdmin.GlobalSetting.Immunity and 0) or 1)
end
)
end
ContinueNewGroup = function(ply, name, admin_access, func)
if IsValid(ply) then
RunConsoleCommand("_FAdmin", "setaccess", ply:UserID(), name, admin_access)
else
RunConsoleCommand("_FAdmin", "AddGroup", name, admin_access)
end
if func then
func(name, admin_access)
end
end
EditGroups = function()
local frame, SelectedGroup, AddGroup, RemGroup, Privileges, SelectedPrivs, AddPriv, RemPriv, lblImmunity, nmbrImmunity
frame = vgui.Create("DFrame")
frame:SetTitle("Create, edit and remove groups")
frame:MakePopup()
frame:SetVisible(true)
frame:SetSize(640, 480)
frame:Center()
SelectedGroup = vgui.Create("DComboBox", frame)
SelectedGroup:SetPos(5, 30)
SelectedGroup:SetWidth(145)
for _, v in pairs(FAdmin.Access.Groups) do
v.immunity = v.immunity or 0
end
for k in SortedPairsByMemberValue(FAdmin.Access.Groups, "immunity", true) do
SelectedGroup:AddChoice(k)
end
AddGroup = vgui.Create("DButton", frame)
AddGroup:SetPos(155, 30)
AddGroup:SetSize(60, 22)
AddGroup:SetText("Add Group")
AddGroup.DoClick = function()
addGroupUI(nil, function(name, admin, privs)
SelectedGroup:AddChoice(name)
SelectedGroup:SetValue(name)
RemGroup:SetDisabled(false)
Privileges:Clear()
SelectedPrivs:Clear()
nmbrImmunity:SetText(FAdmin.Access.Groups[FAdmin.Access.ADMIN[admin + 1]].immunity)
nmbrImmunity:SetDisabled(false)
nmbrImmunity:SetEditable(true)
for priv, am in SortedPairs(FAdmin.Access.Privileges) do
if am <= admin + 1 then
SelectedPrivs:AddLine(priv)
else
Privileges:AddLine(priv)
end
end
end)
end
RemGroup = vgui.Create("DButton", frame)
RemGroup:SetPos(220, 30)
RemGroup:SetSize(85, 22)
RemGroup:SetText("Remove Group")
RemGroup.DoClick = function()
RunConsoleCommand("_FAdmin", "RemoveGroup", SelectedGroup:GetValue())
for k, v in pairs(SelectedGroup.Choices) do
if v ~= SelectedGroup:GetValue() then continue end
SelectedGroup.Choices[k] = nil
break
end
table.ClearKeys(SelectedGroup.Choices)
SelectedGroup:SetValue("user")
SelectedGroup:OnSelect(1, "user")
end
Privileges = vgui.Create("DListView", frame)
Privileges:SetPos(5, 55)
Privileges:SetSize(300, 420)
Privileges:AddColumn("Available privileges")
SelectedPrivs = vgui.Create("DListView", frame)
SelectedPrivs:SetPos(340, 55)
SelectedPrivs:SetSize(295, 420)
SelectedPrivs:AddColumn("Selected Privileges")
function SelectedGroup:OnSelect(index, value, data)
if not FAdmin.Access.Groups[value] then return end
RemGroup:SetDisabled(false)
if table.HasValue(FAdmin.Access.ADMIN, value) then
RemGroup:SetDisabled(true)
end
Privileges:Clear()
SelectedPrivs:Clear()
for priv, _ in SortedPairs(FAdmin.Access.Privileges) do
if FAdmin.Access.Groups[value].PRIVS[priv] then
SelectedPrivs:AddLine(priv)
else
Privileges:AddLine(priv)
end
end
if nmbrImmunity then
nmbrImmunity:SetText(FAdmin.Access.Groups[value].immunity or "")
if table.HasValue({"superadmin", "admin", "user", "noaccess"}, string.lower(value)) then
nmbrImmunity:SetDisabled(true)
nmbrImmunity:SetEditable(false)
else
nmbrImmunity:SetDisabled(false)
nmbrImmunity:SetEditable(true)
end
end
end
SelectedGroup:SetValue("user")
SelectedGroup:OnSelect(1, "user")
AddPriv = vgui.Create("DButton", frame)
AddPriv:SetPos(310, 55)
AddPriv:SetSize(25, 25)
AddPriv:SetText(">")
AddPriv.DoClick = function()
for _, v in ipairs(Privileges:GetSelected()) do
local priv = v.Columns[1]:GetValue()
RunConsoleCommand("FAdmin", "AddPrivilege", SelectedGroup:GetValue(), priv)
SelectedPrivs:AddLine(priv)
Privileges:RemoveLine(v.m_iID)
end
end
RemPriv = vgui.Create("DButton", frame)
RemPriv:SetPos(310, 85)
RemPriv:SetSize(25, 25)
RemPriv:SetText("<")
RemPriv.DoClick = function()
for _, v in ipairs(SelectedPrivs:GetSelected()) do
local priv = v.Columns[1]:GetValue()
if SelectedGroup:GetValue() == LocalPlayer():GetUserGroup() and priv == "ManagePrivileges" then
return Derma_Message("You shouldn't be removing ManagePrivileges. It will make you unable to edit the groups. This is preventing you from locking yourself out of the system.", "Clever move.")
end
RunConsoleCommand("FAdmin", "RemovePrivilege", SelectedGroup:GetValue(), priv)
Privileges:AddLine(priv)
SelectedPrivs:RemoveLine(v.m_iID)
end
end
lblImmunity = vgui.Create("DLabel", frame)
lblImmunity:SetPos(340, 30)
lblImmunity:SetText("Immunity number (higher is more immune)")
lblImmunity:SizeToContents()
nmbrImmunity = vgui.Create("DTextEntry", frame)
nmbrImmunity:SetPos(545, 28)
nmbrImmunity:SetWide(90)
nmbrImmunity:SetNumeric(true)
nmbrImmunity:SetText(FAdmin.Access.Groups.user.immunity)
nmbrImmunity:SetDisabled(true)
nmbrImmunity:SetEditable(false)
nmbrImmunity.OnEnter = function(self) RunConsoleCommand("FAdmin", "SetImmunity", SelectedGroup:GetValue(), self:GetValue()) end
end

View File

@@ -0,0 +1,273 @@
CreateConVar("_FAdmin_immunity", 1, {FCVAR_GAMEDLL, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE})
FAdmin.Access = FAdmin.Access or {}
FAdmin.Access.ADMIN = {"user", "admin", "superadmin"}
FAdmin.Access.ADMIN[0] = "user"
FAdmin.Access.Groups = FAdmin.Access.Groups or {}
FAdmin.Access.Privileges = FAdmin.Access.Privileges or {}
function FAdmin.Access.AddGroup(name, admin_access --[[0 = not admin, 1 = admin, 2 = superadmin]], privs, immunity, fromCAMI, CAMIsrc)
FAdmin.Access.Groups[name] = FAdmin.Access.Groups[name] or {ADMIN = admin_access, PRIVS = privs or {}, immunity = immunity}
--Make sure things that come from CAMI come with a CAMIsrc
assert((fromCAMI and CAMIsrc ~= nil) or ((not fromCAMI) and CAMIsrc == nil))
--If the CAMIsrc is a string, save it, otherwise save an empty string
if not isstring(CAMIsrc) then
CAMIsrc = ""
end
-- Register custom usergroups with CAMI
if name ~= "user" and name ~= "admin" and name ~= "superadmin" and not fromCAMI then
CAMI.RegisterUsergroup({
Name = name,
Inherits = FAdmin.Access.ADMIN[admin_access]
}, "FAdmin")
end
-- Add newly created privileges on server reload
for p, _ in pairs(privs or {}) do
FAdmin.Access.Groups[name].PRIVS[p] = true
end
if not SERVER then return end
MySQLite.queryValue("SELECT COUNT(*) FROM FADMIN_GROUPS WHERE NAME = " .. MySQLite.SQLStr(name) .. ";", function(val)
if tonumber(val or 0) > 0 then return end
MySQLite.query("REPLACE INTO FADMIN_GROUPS VALUES(" .. MySQLite.SQLStr(name) .. ", " .. tonumber(admin_access) .. ");", function()
for priv, _ in pairs(privs or {}) do
MySQLite.query("REPLACE INTO FADMIN_PRIVILEGES VALUES(" .. MySQLite.SQLStr(name) .. ", " .. MySQLite.SQLStr(priv) .. ");")
end
if fromCAMI then
MySQLite.query("REPLACE INTO FADMIN_GROUPS_SRC VALUES(" .. MySQLite.SQLStr(name) .. ", " .. MySQLite.SQLStr(CAMIsrc) .. ");")
end
end)
end)
if immunity then
MySQLite.query("REPLACE INTO FAdmin_Immunity VALUES(" .. MySQLite.SQLStr(name) .. ", " .. tonumber(immunity) .. ");")
end
if FAdmin.Access.SendGroups and privs then
for _, v in ipairs(player.GetAll()) do
FAdmin.Access.SendGroups(v)
end
end
end
function FAdmin.Access.OnUsergroupRegistered(usergroup, source)
-- Don't re-add usergroups coming from FAdmin itself
if source == "FAdmin" then return end
local inheritRoot = CAMI.InheritanceRoot(usergroup.Inherits)
local admin_access = table.KeyFromValue(FAdmin.Access.ADMIN, inheritRoot) or 1
-- Add groups registered to CAMI to FAdmin. Assume privileges from either the usergroup it inherits or its inheritance root.
-- Immunity is unknown and can be set by the user later. FAdmin immunity only applies to FAdmin anyway.
local parent = FAdmin.Access.Groups[usergroup.Inherits] or FAdmin.Access.Groups[inheritRoot] or {}
FAdmin.Access.AddGroup(usergroup.Name, admin_access - 1, table.Copy(parent.PRIVS) or {}, parent.immunity or 10, true, source)
end
function FAdmin.Access.OnUsergroupUnregistered(usergroup, source)
if table.HasValue({"superadmin", "admin", "user", "noaccess"}, usergroup.Name) then return end
FAdmin.Access.Groups[usergroup.Name] = nil
if not SERVER then return end
MySQLite.query("DELETE FROM FADMIN_GROUPS WHERE NAME = " .. MySQLite.SQLStr(usergroup.Name) .. ";")
for _, v in ipairs(player.GetAll()) do
FAdmin.Access.SendGroups(v)
end
end
function FAdmin.Access.RemoveGroup(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ManageGroups") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
if not FAdmin.Access.Groups[args[1]] or table.HasValue({"superadmin", "admin", "user"}, string.lower(args[1])) then return true, args[1] end
-- Setting a group with a higher rank than one's own
if (not plyGroup or FAdmin.Access.Groups[args[1]].immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to remove usergroups with a higher rank than your own")
return false
end
CAMI.UnregisterUsergroup(args[1], "FAdmin")
FAdmin.Messages.SendMessage(ply, 4, "Group succesfully removed")
end
local PLAYER = FindMetaTable("Player")
local oldplyIsAdmin = PLAYER.IsAdmin
function PLAYER:IsAdmin(...)
local usergroup = self:GetUserGroup()
if not FAdmin or not FAdmin.Access or not FAdmin.Access.Groups or not FAdmin.Access.Groups[usergroup] then return oldplyIsAdmin(self, ...) or game.SinglePlayer() end
if (FAdmin.Access.Groups[usergroup] and FAdmin.Access.Groups[usergroup].ADMIN >= 1 --[[1 = admin]]) or (self.IsListenServerHost and self:IsListenServerHost()) then
return true
end
if CLIENT and tonumber(self:FAdmin_GetGlobal("FAdmin_admin")) and self:FAdmin_GetGlobal("FAdmin_admin") >= 1 then return true end
return oldplyIsAdmin(self, ...) or game.SinglePlayer()
end
local oldplyIsSuperAdmin = PLAYER.IsSuperAdmin
function PLAYER:IsSuperAdmin(...)
local usergroup = self:GetUserGroup()
if not FAdmin or not FAdmin.Access or not FAdmin.Access.Groups or not FAdmin.Access.Groups[usergroup] then return oldplyIsSuperAdmin(self, ...) or game.SinglePlayer() end
if (FAdmin.Access.Groups[usergroup] and FAdmin.Access.Groups[usergroup].ADMIN >= 2 --[[2 = superadmin]]) or (self.IsListenServerHost and self:IsListenServerHost()) then
return true
end
if CLIENT and tonumber(self:FAdmin_GetGlobal("FAdmin_admin")) and self:FAdmin_GetGlobal("FAdmin_admin") >= 2 then return true end
return oldplyIsSuperAdmin(self, ...) or game.SinglePlayer()
end
--Privileges
function FAdmin.Access.AddPrivilege(Name, admin_access)
FAdmin.Access.Privileges[Name] = admin_access
end
hook.Add("CAMI.OnPrivilegeRegistered", "FAdmin", function(privilege)
FAdmin.Access.AddPrivilege(privilege.Name, table.KeyFromValue(FAdmin.Access.ADMIN, CAMI.InheritanceRoot(privilege.MinAccess)) or 3)
-- Register privilege and add to respective usergroups
if SERVER then FAdmin.Access.RegisterCAMIPrivilege(privilege) end
end)
for _, camipriv in pairs(CAMI.GetPrivileges()) do
FAdmin.Access.AddPrivilege(camipriv.Name, table.KeyFromValue(FAdmin.Access.ADMIN, CAMI.InheritanceRoot(camipriv.MinAccess)) or 3)
-- Register if the database has already loaded
if SERVER and FAdmin.Access.RegisterCAMIPrivilege then FAdmin.Access.RegisterCAMIPrivilege(camipriv) end
end
hook.Add("CAMI.OnPrivilegeUnregistered", "FAdmin", function(privilege)
FAdmin.Access.Privileges[privilege.Name] = nil
end)
function FAdmin.Access.PlayerIsHost(ply)
return ply:EntIndex() == 0 or game.SinglePlayer() or (ply.IsListenServerHost and ply:IsListenServerHost())
end
function FAdmin.Access.PlayerHasPrivilege(ply, priv, target, ignoreImmunity)
-- This is the server console
if FAdmin.Access.PlayerIsHost(ply) then return true end
-- Privilege does not exist
if not FAdmin.Access.Privileges[priv] then return ply:IsAdmin() end
local Usergroup = ply:GetUserGroup()
local canTarget = hook.Call("FAdmin_CanTarget", nil, ply, priv, target)
if canTarget ~= nil then
return canTarget
end
if FAdmin.GlobalSetting.Immunity and
not ignoreImmunity and
not isstring(target) and IsValid(target) and target ~= ply and
FAdmin.Access.Groups[Usergroup] and FAdmin.Access.Groups[target:GetUserGroup()] and
FAdmin.Access.Groups[Usergroup].immunity and FAdmin.Access.Groups[target:GetUserGroup()].immunity and
FAdmin.Access.Groups[target:GetUserGroup()].immunity >= FAdmin.Access.Groups[Usergroup].immunity then
return false
end
-- Defer answer when usergroup is unknown
if not FAdmin.Access.Groups[Usergroup] then return end
if FAdmin.Access.Groups[Usergroup].PRIVS[priv] then
return true
end
if CLIENT and ply.FADMIN_PRIVS and ply.FADMIN_PRIVS[priv] then return true end
return false
end
hook.Add("CAMI.PlayerHasAccess", "FAdmin", function(actor, privilegeName, callback, target, extraInfo)
-- FAdmin doesn't know. Defer answer.
if not FAdmin.Access.Privileges[privilegeName] then return end
local res = FAdmin.Access.PlayerHasPrivilege(actor, privilegeName, target, extraInfo and extraInfo.IgnoreImmunity)
-- Defer again
if res == nil then return end
-- Publish the answer
callback(res, "FAdmin")
-- FAdmin knows the answer. Prevent other hooks from running.
return true
end)
hook.Add("CAMI.SteamIDHasAccess", "FAdmin", function(actorSteam, privilegeName, callback, targetSteam, extraInfo)
-- The client just doesn't know
if CLIENT then return end
if not targetSteam or extraInfo and extraInfo.IgnoreImmunity then
MySQLite.query(string.format(
[[SELECT COUNT(*) AS c
FROM FAdmin_PlayerGroup l
JOIN FADMIN_PRIVILEGES r ON l.groupname = r.NAME
WHERE l.steamid = %s AND r.PRIVILEGE = %s]],
MySQLite.SQLStr(actorSteam),
MySQLite.SQLStr(privilegeName)
), function(res) callback(tonumber(res[1].c) > 0) end)
return true
end
MySQLite.query(string.format(
[[SELECT ll.i AND rr.c AS res
FROM (SELECT li.immunity >= ri.immunity AS i
FROM FAdmin_PlayerGroup lg
JOIN FAdmin_Immunity li ON lg.groupname = li.groupname
JOIN FAdmin_PlayerGroup rg
JOIN FAdmin_Immunity ri ON rg.groupname = ri.groupname
WHERE lg.steamid = %s AND rg.steamid = %s) AS ll
JOIN (SELECT COUNT(*) AS c
FROM FAdmin_PlayerGroup l
JOIN FADMIN_PRIVILEGES r ON l.groupname = r.NAME
WHERE l.steamid = %s AND r.PRIVILEGE = %s) AS rr]],
MySQLite.SQLStr(actorSteam),
MySQLite.SQLStr(targetSteam),
MySQLite.SQLStr(actorSteam),
MySQLite.SQLStr(privilegeName)
), function(res) callback(res and res[1] and tobool(res[1].res) or false) end)
return true
end)
FAdmin.StartHooks["AccessFunctions"] = function()
FAdmin.Messages.RegisterNotification{
name = "setaccess",
hasTarget = true,
message = {"instigator", " set the usergroup of ", "targets", " to ", "extraInfo.1"},
receivers = "everyone",
writeExtraInfo = function(i) net.WriteString(i[1]) end,
readExtraInfo = function() return {net.ReadString()} end,
extraInfoColors = {Color(255, 102, 0)}
}
FAdmin.Access.AddPrivilege("SetAccess", 3) -- AddPrivilege is shared, run on both client and server
FAdmin.Access.AddPrivilege("ManagePrivileges", 3)
FAdmin.Access.AddPrivilege("ManageGroups", 3)
FAdmin.Access.AddPrivilege("SeeAdmins", 1)
FAdmin.Commands.AddCommand("RemoveGroup", FAdmin.Access.RemoveGroup)
FAdmin.Commands.AddCommand("Admins", function(ply)
if not FAdmin.Access.PlayerHasPrivilege(ply, "SeeAdmins") then return false end
for _, v in ipairs(player.GetAll()) do
ply:PrintMessage(HUD_PRINTCONSOLE, v:Nick() .. "\t|\t" .. v:GetUserGroup())
end
return true
end
)
end

View File

@@ -0,0 +1,449 @@
--Immunity
cvars.AddChangeCallback("_FAdmin_immunity", function(Cvar, Previous, New)
FAdmin.SetGlobalSetting("Immunity", (tonumber(New) == 1 and true) or false)
FAdmin.SaveSetting("_FAdmin_immunity", tonumber(New))
end)
hook.Add("DatabaseInitialized", "InitializeFAdminGroups", function()
MySQLite.query("CREATE TABLE IF NOT EXISTS FADMIN_GROUPS(NAME VARCHAR(40) NOT NULL PRIMARY KEY, ADMIN_ACCESS INTEGER NOT NULL);")
MySQLite.query("CREATE TABLE IF NOT EXISTS FAdmin_PlayerGroup(steamid VARCHAR(40) NOT NULL, groupname VARCHAR(40) NOT NULL, PRIMARY KEY(steamid));")
MySQLite.query("CREATE TABLE IF NOT EXISTS FAdmin_Immunity(groupname VARCHAR(40) NOT NULL, immunity INTEGER NOT NULL, PRIMARY KEY(groupname));")
MySQLite.query("CREATE TABLE IF NOT EXISTS FAdmin_CAMIPrivileges(privname VARCHAR(255) NOT NULL PRIMARY KEY);")
MySQLite.query("CREATE TABLE IF NOT EXISTS FADMIN_GROUPS_SRC(NAME VARCHAR(40) NOT NULL PRIMARY KEY REFERENCES FADMIN_GROUPS(NAME) ON DELETE CASCADE, SRC VARCHAR(40));")
MySQLite.query([[CREATE TABLE IF NOT EXISTS FADMIN_PRIVILEGES(
NAME VARCHAR(40),
PRIVILEGE VARCHAR(100),
PRIMARY KEY(NAME, PRIVILEGE),
FOREIGN KEY(NAME) REFERENCES FADMIN_GROUPS(NAME)
ON UPDATE CASCADE
ON DELETE CASCADE
);]], function()
-- Remove SetAccess workaround
MySQLite.query([[DELETE FROM FADMIN_PRIVILEGES WHERE NAME = "user" AND PRIVILEGE = "SetAccess";]])
MySQLite.query("SELECT g.NAME, g.ADMIN_ACCESS, p.PRIVILEGE, i.immunity, s.src FROM FADMIN_GROUPS g LEFT OUTER JOIN FADMIN_PRIVILEGES p ON g.NAME = p.NAME LEFT OUTER JOIN FAdmin_Immunity i ON g.NAME = i.groupname LEFT OUTER JOIN FADMIN_GROUPS_SRC s ON g.NAME = s.NAME;", function(data)
if not data then return end
for _, v in pairs(data) do
FAdmin.Access.Groups[v.NAME] = FAdmin.Access.Groups[v.NAME] or
{ADMIN = tonumber(v.ADMIN_ACCESS), PRIVS = {}}
if v.PRIVILEGE and v.PRIVILEGE ~= "NULL" then
FAdmin.Access.Groups[v.NAME].PRIVS[v.PRIVILEGE] = true
end
if v.immunity and v.immunity ~= "NULL" then
FAdmin.Access.Groups[v.NAME].immunity = tonumber(v.immunity)
end
if CAMI.GetUsergroup(v.NAME) then continue end
CAMI.RegisterUsergroup({
Name = v.NAME,
Inherits = FAdmin.Access.ADMIN[v.ADMIN_ACCESS] or "user"
}, v.SRC)
end
-- Send groups to early joiners and listen server hosts
for _, v in ipairs(player.GetAll()) do
FAdmin.Access.SendGroups(v)
end
-- See if there are any CAMI usergroups that FAdmin doesn't know about yet.
-- FAdmin doesn't start listening immediately because the database might not have initialised.
-- Besides, other admin mods might add usergroups before FAdmin's Lua files are even run
for _, v in pairs(CAMI.GetUsergroups()) do
if FAdmin.Access.Groups[v.Name] then continue end
FAdmin.Access.OnUsergroupRegistered(v,"")
end
-- Start listening for CAMI usergroup registrations.
hook.Add("CAMI.OnUsergroupRegistered", "FAdmin", FAdmin.Access.OnUsergroupRegistered)
hook.Add("CAMI.OnUsergroupUnregistered", "FAdmin", FAdmin.Access.OnUsergroupUnregistered)
FAdmin.Access.RegisterCAMIPrivileges()
end)
local function createGroups(privs)
FAdmin.Access.AddGroup("superadmin", 2, privs.superadmin, 100)
FAdmin.Access.AddGroup("admin", 1, privs.admin, 50)
FAdmin.Access.AddGroup("user", 0, privs.user, 10)
FAdmin.Access.AddGroup("noaccess", 0, privs.noaccess, 0)
end
MySQLite.query("SELECT DISTINCT PRIVILEGE FROM FADMIN_PRIVILEGES;", function(privTbl)
local privs = {}
local hasPrivs = {"noaccess", "user", "admin", "superadmin"}
-- No privileges registered to anyone. Reset everything
if not privTbl or table.IsEmpty(privTbl) then
for priv, access in pairs(FAdmin.Access.Privileges) do
for i = access + 1, #hasPrivs, 1 do
privs[hasPrivs[i]] = privs[hasPrivs[i]] or {}
privs[hasPrivs[i]][priv] = true
end
end
createGroups(privs)
return
end
-- Check for newly created privileges and assign them to the default usergroups
-- No privilege can be revoke from every group
local privSet = {}
for _, priv in ipairs(privTbl) do
privSet[priv.PRIVILEGE] = true
end
for priv, access in pairs(FAdmin.Access.Privileges) do
if privSet[priv] then continue end
for i = access + 1, #hasPrivs do
MySQLite.query(("REPLACE INTO FADMIN_PRIVILEGES VALUES(%s, %s);"):format(MySQLite.SQLStr(hasPrivs[i]), MySQLite.SQLStr(priv)))
end
end
createGroups(privs)
end)
end)
end)
-- Assign a privilege to its respective usergroups when they are seen for the first time
function FAdmin.Access.RegisterCAMIPrivilege(priv)
-- Privileges haven't been loaded yet or has already been seen
if not FAdmin.CAMIPrivs or FAdmin.CAMIPrivs[priv.Name] then return end
FAdmin.CAMIPrivs[priv.Name] = true
for groupName, groupdata in pairs(FAdmin.Access.Groups) do
if FAdmin.Access.Privileges[priv.Name] - 1 > groupdata.ADMIN then continue end
groupdata.PRIVS[priv.Name] = true
MySQLite.query(string.format([[REPLACE INTO FADMIN_PRIVILEGES VALUES(%s, %s);]], MySQLite.SQLStr(groupName), MySQLite.SQLStr(priv.Name)))
end
MySQLite.query(string.format([[REPLACE INTO FAdmin_CAMIPrivileges VALUES(%s);]], MySQLite.SQLStr(priv.Name)))
end
-- Assign privileges to their respective usergroups when they are seen for the first time
function FAdmin.Access.RegisterCAMIPrivileges()
MySQLite.query([[SELECT privname FROM FAdmin_CAMIPrivileges]], function(data)
FAdmin.CAMIPrivs = {}
for _, row in ipairs(data or {}) do
FAdmin.CAMIPrivs[row.privname] = true
end
for privName, _ in pairs(CAMI.GetPrivileges()) do
if FAdmin.CAMIPrivs[privName] then continue end
FAdmin.CAMIPrivs[privName] = true
for groupName, groupdata in pairs(FAdmin.Access.Groups) do
if FAdmin.Access.Privileges[privName] - 1 > groupdata.ADMIN then continue end
groupdata.PRIVS[privName] = true
MySQLite.query(string.format([[REPLACE INTO FADMIN_PRIVILEGES VALUES(%s, %s);]], MySQLite.SQLStr(groupName), MySQLite.SQLStr(privName)))
end
MySQLite.query(string.format([[REPLACE INTO FAdmin_CAMIPrivileges VALUES(%s);]], MySQLite.SQLStr(privName)))
end
end)
end
function FAdmin.Access.PlayerSetGroup(ply, group)
if not FAdmin.Access.Groups[group] then return end
ply = isstring(ply) and FAdmin.FindPlayer(ply) and FAdmin.FindPlayer(ply)[1] or ply
if not isstring(ply) and IsValid(ply) then
ply:SetUserGroup(group)
end
end
hook.Remove("PlayerInitialSpawn", "PlayerAuthSpawn") -- Remove Garry's usergroup setter.
-- Update the database only when an end users indicates that a player's usergroup is to be changed.
hook.Add("CAMI.PlayerUsergroupChanged", "FAdmin", function(ply, old, new, source)
MySQLite.query("REPLACE INTO FAdmin_PlayerGroup VALUES(" .. MySQLite.SQLStr(ply:SteamID()) .. ", " .. MySQLite.SQLStr(new) .. ");")
end)
hook.Add("CAMI.SteamIDUsergroupChanged", "FAdmin", function(steamId, old, new, source)
MySQLite.query("REPLACE INTO FAdmin_PlayerGroup VALUES(" .. MySQLite.SQLStr(steamId) .. ", " .. MySQLite.SQLStr(new) .. ");")
end)
function FAdmin.Access.SetRoot(ply, cmd, args) -- FAdmin setroot player. Sets the player to superadmin
if not FAdmin.Access.PlayerHasPrivilege(ply, "SetAccess") then
FAdmin.Messages.SendMessage(ply, 5, "No access!")
FAdmin.Messages.SendMessage(ply, 5, "Please use RCon to set yourself to superadmin if you are the owner of the server")
return false
end
local group = FAdmin.Access.Groups["superadmin"]
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
-- Setting a group with a higher rank than one's own
if (not plyGroup or group.immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to assign anyone a usergroup with a higher rank than your own")
FAdmin.Messages.SendMessage(ply, 5, "Please use RCon to set yourself to superadmin if you are the owner of the server")
return false
end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not IsValid(target) then continue end
local target_previous_group = target:GetUserGroup()
FAdmin.Access.PlayerSetGroup(target, "superadmin")
-- An end user changed the usergroup. Register with CAMI
CAMI.SignalUserGroupChanged(target, target_previous_group, "superadmin", "FAdmin")
FAdmin.Messages.SendMessage(ply, 2, "User set to superadmin!")
end
FAdmin.Messages.FireNotification("setaccess", ply, targets, {"superadmin"})
return true, targets, "superadmin"
end
-- AddGroup <Groupname> <Adminstatus> <Privileges>
local function AddGroup(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ManageGroups") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local admin = tonumber(args[2])
if not args[1] or not admin then FAdmin.Messages.SendMessage(ply, 5, "Incorrect arguments!") return false end
local privs = {}
for priv, am in SortedPairs(FAdmin.Access.Privileges) do
-- The user cannot create groups with privileges they don't have
if not FAdmin.Access.PlayerHasPrivilege(ply, priv) then continue end
if am <= admin + 1 then privs[priv] = true end
end
local immunity = FAdmin.Access.Groups[FAdmin.Access.ADMIN[admin + 1]].immunity
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
if (not plyGroup or immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to create usergroups with a higher rank than your own")
return false
end
FAdmin.Access.AddGroup(args[1], admin, privs, immunity) -- Add new group
FAdmin.Messages.SendMessage(ply, 4, "Group created")
FAdmin.Access.SendGroups()
return true, args[1]
end
local function AddPrivilege(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ManagePrivileges") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local group, priv = args[1], args[2]
if not FAdmin.Access.Groups[group] or not FAdmin.Access.Privileges[priv] then
FAdmin.Messages.SendMessage(ply, 5, "Invalid arguments")
return false
end
-- The player cannot add privileges that they themselves do not have
if not FAdmin.Access.PlayerHasPrivilege(ply, priv) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to assign privileges that you don't have yourself")
return false
end
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
-- Setting a group with a higher rank than one's own
if (not plyGroup or FAdmin.Access.Groups[group].immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to manage the privileges of a usergroup with a higher rank than your own")
return false
end
FAdmin.Access.Groups[group].PRIVS[priv] = true
MySQLite.query("REPLACE INTO FADMIN_PRIVILEGES VALUES(" .. MySQLite.SQLStr(group) .. ", " .. MySQLite.SQLStr(priv) .. ");")
SendUserMessage("FAdmin_AddPriv", player.GetAll(), group, priv)
FAdmin.Messages.SendMessage(ply, 4, "Privilege Added!")
return true, group, priv
end
local function RemovePrivilege(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ManagePrivileges") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local group, priv = args[1], args[2]
if not FAdmin.Access.Groups[group] or not FAdmin.Access.Privileges[priv] then
FAdmin.Messages.SendMessage(ply, 5, "Invalid arguments")
return false
end
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
-- Setting a group with a higher rank than one's own
if (not plyGroup or FAdmin.Access.Groups[group].immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to manage the privileges of a usergroup with a higher rank than your own")
return false
end
FAdmin.Access.Groups[group].PRIVS[priv] = nil
MySQLite.query("DELETE FROM FADMIN_PRIVILEGES WHERE NAME = " .. MySQLite.SQLStr(group) .. " AND PRIVILEGE = " .. MySQLite.SQLStr(priv) .. ";")
SendUserMessage("FAdmin_RemovePriv", player.GetAll(), group, priv)
FAdmin.Messages.SendMessage(ply, 4, "Privilege Removed!")
return true, group, priv
end
function FAdmin.Access.SendGroups(ply)
if not FAdmin.Access.Groups then return end
net.Start("FADMIN_SendGroups")
net.WriteTable(FAdmin.Access.Groups)
net.Send(IsValid(ply) and ply or player.GetAll())
end
-- FAdmin SetAccess <player> <groupname> [new_groupadmin, new_groupprivs]
function FAdmin.Access.SetAccess(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "SetAccess") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local targets = FAdmin.FindPlayer(args[1])
local admin = tonumber(args[3])
local group = FAdmin.Access.Groups[args[2]]
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
if not args[2] or not group and not admin then
FAdmin.Messages.SendMessage(ply, 1, "Group not found")
return false
elseif args[2] and not group and admin then
local privs = {}
for priv, am in SortedPairs(FAdmin.Access.Privileges) do
if am <= admin + 1 then privs[priv] = true end
end
local immunity = FAdmin.Access.Groups[FAdmin.Access.ADMIN[admin + 1]].immunity
-- Creating and setting a group with a higher rank than one's own
if (not plyGroup or immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to assign anyone a usergroup with a higher rank than your own")
return false
end
FAdmin.Access.AddGroup(args[2], tonumber(args[3]), privs, immunity) -- Add new group
FAdmin.Messages.SendMessage(ply, 4, "Group created")
FAdmin.Access.SendGroups()
end
-- Setting a group with a higher rank than one's own
if group and (not plyGroup or group.immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to assign anyone a usergroup with a higher rank than your own")
return false
end
if not targets and (string.find(args[1], "^STEAM_[0-9]:[01]:[0-9]+$") or args[1] == "BOT" or (string.find(args[1], "STEAM_") and #args == 6)) then
local target, groupname = args[1], args[2]
-- The console splits arguments on colons. Very annoying.
if args[1] == "STEAM_0" then
target = table.concat(args, "", 1, 5)
groupname = args[6]
end
FAdmin.Access.PlayerSetGroup(target, groupname)
MySQLite.queryValue(string.format("SELECT groupname FROM FAdmin_PlayerGroup WHERE steamid = %s", MySQLite.SQLStr(target)), function(val)
CAMI.SignalSteamIDUserGroupChanged(target, val or "user", groupname, "FAdmin")
end)
FAdmin.Messages.SendMessage(ply, 4, "User access set!")
return true, target, groupname
elseif not targets then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not IsValid(target) then continue end
local target_previous_group = target:GetUserGroup()
FAdmin.Access.PlayerSetGroup(target, args[2])
-- An end user changed the usergroup. Register with CAMI
CAMI.SignalUserGroupChanged(target, target_previous_group, args[2], "FAdmin")
end
FAdmin.Messages.SendMessage(ply, 4, "User access set!")
FAdmin.Messages.FireNotification("setaccess", ply, targets, {args[2]})
return true, targets, args[2]
end
--hooks and stuff
hook.Add("PlayerInitialSpawn", "FAdmin_SetAccess", function(ply)
MySQLite.queryValue("SELECT groupname FROM FAdmin_PlayerGroup WHERE steamid = " .. MySQLite.SQLStr(ply:SteamID()) .. ";", function(Group)
if not Group then return end
ply:SetUserGroup(Group)
if FAdmin.Access.Groups[Group] then
ply:FAdmin_SetGlobal("FAdmin_admin", FAdmin.Access.Groups[Group].ADMIN_ACCESS)
end
end, function(err) ErrorNoHalt(err) MsgN() end)
FAdmin.Access.SendGroups(ply)
end)
local function toggleImmunity(ply, cmd, args)
-- ManageGroups privilege because they can handle immunity settings
if not FAdmin.Access.PlayerHasPrivilege(ply, "ManageGroups") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then FAdmin.Messages.SendMessage(ply, 5, "Invalid argument!") return false end
RunConsoleCommand("_FAdmin_immunity", args[1])
local OnOff = (tonumber(args[1]) == 1 and "on") or "off"
FAdmin.Messages.ActionMessage(ply, player.GetAll(), ply:Nick() .. " turned " .. OnOff .. " admin immunity!", "Admin immunity has been turned " .. OnOff, "Turned admin immunity " .. OnOff)
return true, OnOff
end
local function setImmunity(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ManageGroups") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local group, immunity = args[1], tonumber(args[2])
if not FAdmin.Access.Groups[group] or not immunity then return false end
local plyGroup = FAdmin.Access.Groups[ply:EntIndex() == 0 and "superadmin" or ply:GetUserGroup()]
-- Setting a group with a higher rank than one's own
if (not plyGroup or FAdmin.Access.Groups[group].immunity > plyGroup.immunity) and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to change the immunity of a group with a higher rank than your")
return false
end
if immunity > plyGroup.immunity and not FAdmin.Access.PlayerIsHost(ply) then
FAdmin.Messages.SendMessage(ply, 5, "You're not allowed to set the immunity to any value higher than your own group's immunity")
return false
end
FAdmin.Access.Groups[group].immunity = immunity
MySQLite.query("REPLACE INTO FAdmin_Immunity VALUES(" .. MySQLite.SQLStr(group) .. ", " .. tonumber(immunity) .. ");")
FAdmin.Access.SendGroups(ply)
return true, group, immunity
end
FAdmin.StartHooks["Access"] = function() --Run all functions that depend on other plugins
FAdmin.Commands.AddCommand("setroot", FAdmin.Access.SetRoot)
FAdmin.Commands.AddCommand("setaccess", FAdmin.Access.SetAccess)
FAdmin.Commands.AddCommand("AddGroup", AddGroup)
FAdmin.Commands.AddCommand("AddPrivilege", AddPrivilege)
FAdmin.Commands.AddCommand("RemovePrivilege", RemovePrivilege)
FAdmin.Commands.AddCommand("immunity", toggleImmunity)
FAdmin.Commands.AddCommand("SetImmunity", setImmunity)
FAdmin.SetGlobalSetting("Immunity", GetConVar("_FAdmin_immunity"):GetBool())
end

View File

@@ -0,0 +1,17 @@
net.Receive("FAdmin_ReceiveAdminMessage", function(len)
local FromPly = net.ReadEntity()
local Text = net.ReadString()
local Team = FromPly:IsPlayer() and FromPly:Team() or 1
local Nick = FromPly:IsPlayer() and FromPly:Nick() or "Console"
local prefix = (FAdmin.Access.PlayerHasPrivilege(FromPly, "AdminChat") or FromPly:IsAdmin()) and "[Admin Chat] " or "[To admins] "
chat.AddNonParsedText(Color(255, 0, 0, 255), prefix, team.GetColor(Team), Nick .. ": ", color_white, Text)
end)
FAdmin.StartHooks["Chatting"] = function()
FAdmin.Commands.AddCommand("adminhelp", nil, "<text>")
FAdmin.Commands.AddCommand("//", nil, "<text>")
FAdmin.Access.AddPrivilege("AdminChat", 2)
end

View File

@@ -0,0 +1,28 @@
util.AddNetworkString("FAdmin_ReceiveAdminMessage")
local function ToAdmins(ply, cmd, args)
if not args[1] then return false end
local text = table.concat(args, " ")
local send = {}
if IsValid(ply) then table.insert(send, ply) end
for _, v in ipairs(player.GetAll()) do
if FAdmin.Access.PlayerHasPrivilege(v, "AdminChat") or v:IsAdmin() then
table.insert(send, v)
end
end
net.Start("FAdmin_ReceiveAdminMessage")
net.WriteEntity(ply)
net.WriteString(text)
net.Send(send)
return true, text
end
FAdmin.StartHooks["Chatting"] = function()
FAdmin.Commands.AddCommand("adminhelp", ToAdmins)
FAdmin.Commands.AddCommand("//", ToAdmins)
FAdmin.Access.AddPrivilege("AdminChat", 2)
end

View File

@@ -0,0 +1,87 @@
local PANEL = {}
AccessorFunc(PANEL, "gamemodeList", "GamemodeList")
AccessorFunc(PANEL, "mapList", "MapList")
function PANEL:Init()
self:SetMouseInputEnabled(true)
self:SetKeyboardInputEnabled(false)
self:SetDeleteOnClose(false)
self:SetTitle("Change level")
self:SetSize(630, ScrH() * 0.8)
self.gamemodeList = {}
self.mapList = {}
self.catList = vgui.Create("DCategoryList", self)
self.catList:Dock(FILL)
self.topPanel = vgui.Create("DPanel", self)
self.topPanel:SetPaintBackground(false)
self.topPanel:DockMargin(0, 0, 0, 4)
self.topPanel:Dock(TOP)
self.gmLabel = vgui.Create("DLabel", self.topPanel)
self.gmLabel:SetText("Gamemode:")
self.gmLabel:Dock(LEFT)
self.gmComboBox = vgui.Create("DComboBox", self.topPanel)
self.gmComboBox:Dock(FILL)
self.gmComboBox:SetValue("(current)")
self.bottomPanel = vgui.Create("DPanel", self)
self.bottomPanel:SetPaintBackground(false)
self.bottomPanel:DockMargin(0, 4, 0, 0)
self.bottomPanel:Dock(BOTTOM)
self.changeButton = vgui.Create("DButton", self.bottomPanel)
self.changeButton:SetText("Change level")
self.changeButton:Dock(RIGHT)
self.changeButton:SetWidth(100)
self.changeButton:SetEnabled(false)
self.changeButton.DoClick = function()
if not IsValid(self.selectedIconPanel) then return end
local _,gmName = self.gmComboBox:GetSelected()
local mapName = self.selectedIconPanel:GetText()
RunConsoleCommand("_FAdmin", "Changelevel", gmName and gmName or mapName, gmName and mapName)
end
end
function PANEL:Refresh()
for _, gmInfo in ipairs(self:GetGamemodeList()) do
self.gmComboBox:AddChoice(gmInfo.title, gmInfo.name)
end
self.gmComboBox:SetValue("(current)")
for catName, maps in pairs(self:GetMapList()) do
local cat = self.catList:Add(catName)
local iconLayout = vgui.Create("DIconLayout")
iconLayout:SetSpaceX(5)
iconLayout:SetSpaceY(5)
for _, map in ipairs(maps) do
local icon = iconLayout:Add("FAdmin_MapIcon")
icon:SetText(map)
icon:SetDark(true)
local mat = Material("maps/thumb/" .. map .. ".png")
if mat:IsError() then mat = Material("maps/thumb/noicon.png") end
icon:SetMaterial(mat)
local onToggled = icon.OnToggled
icon.OnToggled = function(iconSelf, selected)
onToggled(iconSelf, selected)
if IsValid(self.selectedIconPanel) then
if selected and self.selectedIconPanel ~= iconSelf then
self.selectedIconPanel:Toggle()
elseif not selected and self.selectedIconPanel == iconSelf then
self.selectedIconPanel = nil
self.changeButton:SetEnabled(false)
return
end
end
self.selectedIconPanel = iconSelf
self.changeButton:SetEnabled(true)
end
end
cat:SetContents(iconLayout)
end
end
vgui.Register("FAdmin_Changelevel", PANEL, "DFrame")

View File

@@ -0,0 +1,46 @@
local mapList = {}
local gamemodeList = {}
net.Receive("FAdmin_ChangelevelInfo", function(len)
mapList = {}
local mapLen = net.ReadUInt(16)
for i = 1, mapLen, 1 do
local cat = net.ReadString()
mapList[cat] = {}
local catLen = net.ReadUInt(16)
for j = 1, catLen, 1 do
mapList[cat][j] = net.ReadString()
end
end
gamemodeList = {}
local gmLen = net.ReadUInt(16)
for i = 1, gmLen, 1 do
gamemodeList[i] = {
name = net.ReadString(),
title = net.ReadString()
}
end
end)
local Changelevel
FAdmin.StartHooks["ChangeLevel"] = function()
FAdmin.Access.AddPrivilege("changelevel", 2)
FAdmin.Commands.AddCommand("changelevel", "[gamemode]", "<map>")
FAdmin.ScoreBoard.Server:AddServerAction("Changelevel", "icon16/world.png", Color(155, 0, 0, 255), function() return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "changelevel") end,
function(ply, button)
local refresh = not Changelevel or table.Count(Changelevel:GetMapList()) ~= table.Count(mapList)
Changelevel = Changelevel or vgui.Create("FAdmin_Changelevel")
if refresh then
Changelevel:SetGamemodeList(gamemodeList)
Changelevel:SetMapList(mapList)
Changelevel:Refresh()
end
Changelevel:SetVisible(true)
Changelevel:Center()
Changelevel:MakePopup()
end)
end

View File

@@ -0,0 +1,43 @@
local PANEL = {}
function PANEL:Init()
self.BaseClass.Init(self)
self:SetPaintBackground(true)
self:SetIsToggle(true)
self:SetSize(96, 110)
end
function PANEL:Paint(w, h)
if self.m_bToggle then
surface.SetDrawColor(255, 155, 20, 255)
surface.DrawRect(0, 0, w, h)
end
return false
end
function PANEL:UpdateColours(skin)
return self:SetTextStyleColor(skin.Colours.Button.Normal)
end
function PANEL:OnToggled(selected)
self:InvalidateLayout(true)
end
function PANEL:OnMousePressed(code)
DButton.OnMousePressed(self, code)
end
function PANEL:OnMouseReleased(code)
DButton.OnMouseReleased(self, code)
end
function PANEL:PerformLayout()
self.m_Image:SetPos(0, 0)
local w,h = self:GetSize()
h = h - 14
self.m_Image:SetSize(w, h)
self:SetTextInset(5, w / 2)
DLabel.PerformLayout(self)
end
vgui.Register("FAdmin_MapIcon", PANEL, "DImageButton")

View File

@@ -0,0 +1,266 @@
util.AddNetworkString("FAdmin_ChangelevelInfo")
local function ChangeLevel(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "changelevel") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local map = args[2] or args[1] -- Changelevel gamemode map OR changelevel map
local gameMode = args[2] and args[1]
if gameMode then
RunConsoleCommand("gamemode", gameMode)
end
RunConsoleCommand("changelevel", map)
return true, map, gameMode
end
local mapNames = {}
local mapPatterns = {}
local ignorePatterns = {
"^asi-", "^background", "^c[%d]m", "^devtest", "^ep1_background", "^ep2_background", "^mp_coop_", "^sp_a", "^styleguide"
}
local ignoreMaps = {
-- Prefixes
["ddd_"] = true,
["sdk_"] = true,
["test_"] = true,
["vst_"] = true,
-- Maps
["c4a1y"] = true,
["cp_docks"] = true,
["cp_parkour"] = true,
["cp_sequence"] = true,
["cp_terrace"] = true,
["cp_test"] = true,
["credits"] = true,
["curling_stadium"] = true,
["d2_coast_02"] = true,
["d3_c17_02_camera"] = true,
["duel_"] = true,
["e1912"] = true,
["ep1_citadel_00_demo"] = true,
["ffa_community"] = true,
["free_"] = true,
["intro"] = true,
["lobby"] = true,
["practice_box"] = true,
["test"] = true,
["tut_training"] = true,
["tutorial_standards"] = true,
["tutorial_standards_vs"] = true
}
hook.Add("PlayerInitialSpawn", "FAdmin_ChangelevelInfo", function(ply)
local mapList = {}
local maps = file.Find("maps/*.bsp", "GAME")
for _, v in ipairs(maps) do
local name = string.lower(string.gsub(v, "%.bsp$", ""))
if ignoreMaps[name] then continue end
local prefix = string.match(name, "^(.-_)")
if ignoreMaps[prefix] then continue end
for _, ignore in ipairs(ignorePatterns) do
if string.find(name, ignore) then
goto mapContinue
end
end
-- Check if the map has a simple name or prefix
local mapCategory = mapNames[name] or mapNames[prefix]
-- Check if the map has an embedded prefix, or is TTT/Sandbox
if not mapCategory then
for pattern, category in pairs(mapPatterns) do
if string.find(name, pattern) then
mapCategory = category
end
end
end
-- Throw all uncategorized maps into Other
mapCategory = mapCategory or "Other"
-- Don't show CS:GO maps
if mapCategory == "Counter-Strike" and not file.Exists("maps/" .. name .. ".bsp", "cstrike") then
continue
end
if not mapList[mapCategory] then
mapList[mapCategory] = {}
end
table.insert(mapList[mapCategory], name)
::mapContinue::
end
local gamemodeList = engine.GetGamemodes()
net.Start("FAdmin_ChangelevelInfo")
net.WriteUInt(table.Count(mapList), 16) -- 65536 should be enough
for cat, mps in pairs(mapList) do
net.WriteString(cat)
net.WriteUInt(#mps, 16)
for _, map in pairs(mps) do
net.WriteString(map)
end
end
net.WriteUInt(#gamemodeList, 16)
for _, gmInfo in ipairs(gamemodeList) do
net.WriteString(gmInfo.name)
net.WriteString(gmInfo.title)
end
net.Send(ply)
end)
FAdmin.StartHooks["ChangeLevel"] = function()
FAdmin.Commands.AddCommand("changelevel", ChangeLevel)
FAdmin.Access.AddPrivilege("changelevel", 2)
mapNames = {}
mapPatterns = {}
mapNames["aoc_"] = "Age of Chivalry"
mapNames["ar_"] = "Counter-Strike"
mapNames["cs_"] = "Counter-Strike"
mapNames["de_"] = "Counter-Strike"
mapNames["es_"] = "Counter-Strike"
mapNames["fy_"] = "Counter-Strike"
mapNames["gd_"] = "Counter-Strike"
mapNames["training1"] = "Counter-Strike"
mapNames["dod_"] = "Day Of Defeat"
mapNames["de_dam"] = "DIPRIP"
mapNames["dm_city"] = "DIPRIP"
mapNames["dm_refinery"] = "DIPRIP"
mapNames["dm_supermarket"] = "DIPRIP"
mapNames["dm_village"] = "DIPRIP"
mapNames["ur_city"] = "DIPRIP"
mapNames["ur_refinery"] = "DIPRIP"
mapNames["ur_supermarket"] = "DIPRIP"
mapNames["ur_village"] = "DIPRIP"
mapNames["dys_"] = "Dystopia"
mapNames["pb_dojo"] = "Dystopia"
mapNames["pb_rooftop"] = "Dystopia"
mapNames["pb_round"] = "Dystopia"
mapNames["pb_urbandome"] = "Dystopia"
mapNames["sav_dojo6"] = "Dystopia"
mapNames["varena"] = "Dystopia"
mapNames["d1_"] = "Half-Life 2"
mapNames["d2_"] = "Half-Life 2"
mapNames["d3_"] = "Half-Life 2"
mapNames["dm_"] = "Half-Life 2: Deathmatch"
mapNames["halls3"] = "Half-Life 2: Deathmatch"
mapNames["ep1_"] = "Half-Life 2: Episode 1"
mapNames["ep2_"] = "Half-Life 2: Episode 2"
mapNames["ep3_"] = "Half-Life 2: Episode 3"
mapNames["d2_lostcoast"] = "Half-Life 2: Lost Coast"
mapPatterns["^c[%d]a"] = "Half-Life"
mapPatterns["^t0a"] = "Half-Life"
mapNames["boot_camp"] = "Half-Life Deathmatch"
mapNames["bounce"] = "Half-Life Deathmatch"
mapNames["crossfire"] = "Half-Life Deathmatch"
mapNames["datacore"] = "Half-Life Deathmatch"
mapNames["frenzy"] = "Half-Life Deathmatch"
mapNames["lambda_bunker"] = "Half-Life Deathmatch"
mapNames["rapidcore"] = "Half-Life Deathmatch"
mapNames["snarkpit"] = "Half-Life Deathmatch"
mapNames["stalkyard"] = "Half-Life Deathmatch"
mapNames["subtransit"] = "Half-Life Deathmatch"
mapNames["undertow"] = "Half-Life Deathmatch"
mapNames["ins_"] = "Insurgency"
mapNames["l4d_"] = "Left 4 Dead"
mapNames["clocktower"] = "Nuclear Dawn"
mapNames["coast"] = "Nuclear Dawn"
mapNames["downtown"] = "Nuclear Dawn"
mapNames["gate"] = "Nuclear Dawn"
mapNames["hydro"] = "Nuclear Dawn"
mapNames["metro"] = "Nuclear Dawn"
mapNames["metro_training"] = "Nuclear Dawn"
mapNames["oasis"] = "Nuclear Dawn"
mapNames["oilfield"] = "Nuclear Dawn"
mapNames["silo"] = "Nuclear Dawn"
mapNames["sk_metro"] = "Nuclear Dawn"
mapNames["training"] = "Nuclear Dawn"
mapNames["bt_"] = "Pirates, Vikings, & Knights II"
mapNames["lts_"] = "Pirates, Vikings, & Knights II"
mapNames["te_"] = "Pirates, Vikings, & Knights II"
mapNames["tw_"] = "Pirates, Vikings, & Knights II"
mapNames["escape_"] = "Portal"
mapNames["testchmb_"] = "Portal"
mapNames["achievement_"] = "Team Fortress 2"
mapNames["arena_"] = "Team Fortress 2"
mapNames["cp_"] = "Team Fortress 2"
mapNames["ctf_"] = "Team Fortress 2"
mapNames["itemtest"] = "Team Fortress 2"
mapNames["koth_"] = "Team Fortress 2"
mapNames["mvm_"] = "Team Fortress 2"
mapNames["pl_"] = "Team Fortress 2"
mapNames["plr_"] = "Team Fortress 2"
mapNames["rd_"] = "Team Fortress 2"
mapNames["pd_"] = "Team Fortress 2"
mapNames["sd_"] = "Team Fortress 2"
mapNames["tc_"] = "Team Fortress 2"
mapNames["tr_"] = "Team Fortress 2"
mapNames["trade_"] = "Team Fortress 2"
mapNames["pass_"] = "Team Fortress 2"
mapNames["zpa_"] = "Zombie Panic! Source"
mapNames["zpl_"] = "Zombie Panic! Source"
mapNames["zpo_"] = "Zombie Panic! Source"
mapNames["zps_"] = "Zombie Panic! Source"
mapNames["bhop_"] = "Bunny Hop"
mapNames["cinema_"] = "Cinema"
mapNames["theater_"] = "Cinema"
mapNames["xc_"] = "Climb"
mapNames["deathrun_"] = "Deathrun"
mapNames["dr_"] = "Deathrun"
mapNames["fm_"] = "Flood"
mapNames["gmt_"] = "GMod Tower"
mapNames["gg_"] = "Gun Game"
mapNames["scoutzknivez"] = "Gun Game"
mapNames["ba_"] = "Jailbreak"
mapNames["jail_"] = "Jailbreak"
mapNames["jb_"] = "Jailbreak"
mapNames["mg_"] = "Minigames"
mapNames["pw_"] = "Pirate Ship Wars"
mapNames["ph_"] = "Prop Hunt"
mapNames["rp_"] = "Roleplay"
mapNames["slb_"] = "Sled Build"
mapNames["sb_"] = "Spacebuild"
mapNames["slender_"] = "Stop it Slender"
mapNames["gms_"] = "Stranded"
mapNames["surf_"] = "Surf"
mapNames["ts_"] = "The Stalker"
mapNames["zm_"] = "Zombie Survival"
mapNames["zombiesurvival_"] = "Zombie Survival"
mapNames["zs_"] = "Zombie Survival"
for _, gm in ipairs(engine.GetGamemodes()) do
if gm.maps ~= "" then
for _, pattern in ipairs(string.Split(gm.maps, "|")) do
-- When in doubt, just try to match it with string.find later
mapPatterns[string.lower(pattern)] = gm.title or "Unnammed Gamemode"
end
end
end
end

View File

@@ -0,0 +1,41 @@
local function SortedPairsByFunction(Table, Sorted, SortDown)
local CopyTable = {}
for _, v in pairs(Table) do
table.insert(CopyTable, {NAME = tostring(v:Nick()), PLY = v})
end
table.SortByMember(CopyTable, "NAME", SortDown)
local SortedTable = {}
for _, v in ipairs(CopyTable) do
if not IsValid(v.PLY) or not v.PLY[Sorted] then continue end
local SortBy = (Sorted ~= "Team" and v.PLY[Sorted](v.PLY)) or (v.PLY:getDarkRPVar("job") or team.GetName(v.PLY[Sorted](v.PLY)))
SortedTable[SortBy] = SortedTable[SortBy] or {}
table.insert(SortedTable[SortBy], v.PLY)
end
local SecondSort = {}
for _, v in SortedPairs(SortedTable, SortDown) do
table.insert(SecondSort, v)
end
CopyTable = {}
for _, v in ipairs(SecondSort) do
for _, b in pairs(v) do
table.insert(CopyTable, b)
end
end
return ipairs(CopyTable)
end
function FAdmin.ScoreBoard.Main.PlayerListView(Sorted, SortDown)
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:Clear(true)
for _, ply in SortedPairsByFunction(player.GetAll(), Sorted, SortDown) do
local Row = vgui.Create("FadminPlayerRow")
Row:SetPlayer(ply)
Row:Dock(TOP)
Row:InvalidateLayout()
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:AddItem(Row)
end
end

View File

@@ -0,0 +1,308 @@
FAdmin.PlayerIcon = {}
FAdmin.PlayerIcon.RightClickOptions = {}
function FAdmin.PlayerIcon.AddRightClickOption(name, func)
FAdmin.PlayerIcon.RightClickOptions[name] = func
end
-- FAdminPanelList
local PANEL = {}
function PANEL:Init()
self.Padding = 5
end
function PANEL:SizeToContents()
local w, h = self:GetSize()
-- Fix size of w to have the same size as the scoreboard
w = math.Clamp(w, ScrW() * 0.9, ScrW() * 0.9)
h = math.Min(h, ScrH() * 0.95)
-- It fucks up when there's only one icon in
if #self:GetChildren() == 1 then
h = math.Max(0, 120)
end
self:SetSize(w, h)
self:PerformLayout()
end
function PANEL:Paint()
end
derma.DefineControl("FAdminPanelList", "DPanellist adapted for FAdmin", PANEL, "DPanelList")
-- FAdminPlayerCatagoryHeader
local PANEL2 = {}
function PANEL2:PerformLayout()
self:SetFont("Trebuchet24")
end
derma.DefineControl("FAdminPlayerCatagoryHeader", "DCatagoryCollapse header adapted for FAdmin", PANEL2, "DCategoryHeader")
-- FAdminPlayerCatagory
local PANEL3 = {}
function PANEL3:Init()
if self.Header then
self.Header:Remove() -- the old header is still there don't ask me why
end
self.Header = vgui.Create("FAdminPlayerCatagoryHeader", self)
self.Header:SetSize(20, 25)
self:SetPadding(5)
self.Header:Dock(TOP)
self:SetExpanded(true)
self:SetMouseInputEnabled(true)
self:SetAnimTime(0.2)
self.animSlide = Derma_Anim("Anim", self, self.AnimSlide)
self:SetPaintBackgroundEnabled(true)
end
function PANEL3:Paint()
if self.CatagoryColor then
draw.RoundedBox(4, 0, 0, self:GetWide(), self.Header:GetTall(), self.CatagoryColor)
end
end
derma.DefineControl("FAdminPlayerCatagory", "DCatagoryCollapse adapted for FAdmin", PANEL3, "DCollapsibleCategory")
-- FAdmin player row (from the sandbox player row)
PANEL = {}
local PlayerRowSize = CreateClientConVar("FAdmin_PlayerRowSize", 30, true, false)
function PANEL:Init()
self.Size = PlayerRowSize:GetInt()
self.lblName = vgui.Create("DLabel", self)
self.lblFrags = vgui.Create("DLabel", self)
self.lblTeam = vgui.Create("DLabel", self)
self.lblDeaths = vgui.Create("DLabel", self)
self.lblPing = vgui.Create("DLabel", self)
self.lblWanted = vgui.Create("DLabel", self)
-- If you don't do this it'll block your clicks
self.lblName:SetMouseInputEnabled(false)
self.lblTeam:SetMouseInputEnabled(false)
self.lblFrags:SetMouseInputEnabled(false)
self.lblDeaths:SetMouseInputEnabled(false)
self.lblPing:SetMouseInputEnabled(false)
self.lblWanted:SetMouseInputEnabled(false)
self.lblName:SetColor(Color(255,255,255,200))
self.lblTeam:SetColor(Color(255,255,255,200))
self.lblFrags:SetColor(Color(255,255,255,200))
self.lblDeaths:SetColor(Color(255,255,255,200))
self.lblPing:SetColor(Color(255,255,255,200))
self.lblWanted:SetColor(Color(255,255,255,200))
self.imgAvatar = vgui.Create("AvatarImage", self)
self:SetCursor("hand")
end
function PANEL:Paint()
if not IsValid(self.Player) then return end
self.Size = PlayerRowSize:GetInt()
self.imgAvatar:SetSize(self.Size - 4, self.Size - 4)
local color = Color(100, 150, 245, 255)
if GAMEMODE.Name == "Sandbox" then
color = Color(100, 150, 245, 255)
if self.Player:Team() == TEAM_CONNECTING then
color = Color(200, 120, 50, 255)
elseif self.Player:IsAdmin() then
color = Color(30, 200, 50, 255)
end
if self.Player:GetFriendStatus() == "friend" then
color = Color(236, 181, 113, 255)
end
else
color = team.GetColor(self.Player:Team())
end
local hooks = hook.GetTable().FAdmin_PlayerRowColour
if hooks then
for _, v in pairs(hooks) do
color = (v and v(self.Player, color)) or color
break
end
end
draw.RoundedBox(4, 0, 0, self:GetWide(), self.Size, color)
surface.SetTexture(0)
if self.Player == LocalPlayer() or self.Player:GetFriendStatus() == "friend" then
surface.SetDrawColor(255, 255, 255, 50 + math.sin(RealTime() * 2) * 50)
end
surface.DrawTexturedRect(0, 0, self:GetWide(), self.Size)
return true
end
function PANEL:SetPlayer(ply)
self.Player = ply
self.imgAvatar:SetPlayer(ply)
self:UpdatePlayerData()
end
function PANEL:UpdatePlayerData()
if not self.Player then return end
if not self.Player:IsValid() then return end
self.lblName:SetText(DarkRP.deLocalise(self.Player:Nick()))
self.lblTeam:SetText((self.Player.DarkRPVars and DarkRP.deLocalise(self.Player:getDarkRPVar("job") or "")) or team.GetName(self.Player:Team()))
self.lblTeam:SizeToContents()
self.lblFrags:SetText(self.Player:Frags())
self.lblDeaths:SetText(self.Player:Deaths())
self.lblPing:SetText(self.Player:Ping())
self.lblWanted:SetText(self.Player:isWanted() and DarkRP.getPhrase("Wanted_text") or "")
end
function PANEL:ApplySchemeSettings()
self.lblName:SetFont("ScoreboardPlayerNameBig")
self.lblTeam:SetFont("ScoreboardPlayerNameBig")
self.lblFrags:SetFont("ScoreboardPlayerName")
self.lblDeaths:SetFont("ScoreboardPlayerName")
self.lblPing:SetFont("ScoreboardPlayerName")
self.lblWanted:SetFont("ScoreboardPlayerNameBig")
self.lblName:SetFGColor(color_white)
self.lblTeam:SetFGColor(color_white)
self.lblFrags:SetFGColor(color_white)
self.lblDeaths:SetFGColor(color_white)
self.lblPing:SetFGColor(color_white)
self.lblWanted:SetFGColor(color_white)
end
function PANEL:DoClick(x, y)
if not IsValid(self.Player) then self:Remove() return end
FAdmin.ScoreBoard.ChangeView("Player", self.Player)
end
function PANEL:DoRightClick()
if table.IsEmpty(FAdmin.PlayerIcon.RightClickOptions) then return end
local menu = DermaMenu()
menu:SetPos(gui.MouseX(), gui.MouseY())
for Name, func in SortedPairs(FAdmin.PlayerIcon.RightClickOptions) do
menu:AddOption(Name, function() if IsValid(self.Player) then func(self.Player, self) end end)
end
menu:Open()
end
function PANEL:Think()
if not self.PlayerUpdate or self.PlayerUpdate < CurTime() then
self.PlayerUpdate = CurTime() + 0.5
self:UpdatePlayerData()
end
end
function PANEL:PerformLayout()
self.imgAvatar:SetPos(2, 2)
self.imgAvatar:SetSize(32, 32)
self:SetSize(self:GetWide(), self.Size)
self.lblName:SizeToContents()
self.lblName:SetPos(24, 2)
self.lblName:MoveRightOf(self.imgAvatar, 8)
local COLUMN_SIZE = 75
self.lblPing:SetPos(self:GetWide() - COLUMN_SIZE * 0.4, 0)
self.lblDeaths:SetPos(self:GetWide() - COLUMN_SIZE * 1.4, 0)
self.lblFrags:SetPos(self:GetWide() - COLUMN_SIZE * 2.4, 0)
self.lblTeam:SetPos(self:GetWide() / 2 - (0.5 * self.lblTeam:GetWide()))
self.lblWanted:SizeToContents()
self.lblWanted:SetPos(math.floor(self:GetWide() / 4), 2)
end
vgui.Register("FadminPlayerRow", PANEL, "Button")
-- FAdminActionButton
local PANEL6 = {}
function PANEL6:Init()
self:SetDrawBackground(false)
self:SetDrawBorder(false)
self:SetStretchToFit(false)
self:SetSize(120, 40)
self.TextLabel = vgui.Create("DLabel", self)
self.TextLabel:SetColor(Color(200,200,200,200))
self.TextLabel:SetFont("Roboto20")
self.m_Image2 = vgui.Create("DImage", self)
self.BorderColor = Color(190,40,0,255)
end
function PANEL6:SetText(text)
self.TextLabel:SetText(text)
self.TextLabel:SizeToContents()
self:SetWide(self.TextLabel:GetWide() + 44)
end
function PANEL6:PerformLayout()
self.m_Image:SetSize(32,32)
self.m_Image:SetPos(4,4)
self.m_Image2:SetSize(32, 32)
self.m_Image2:SetPos(4,4)
self.TextLabel:SetPos(38, 8)
end
function PANEL6:SetImage2(Mat, bckp)
self.m_Image2:SetImage(Mat, bckp)
end
function PANEL6:SetBorderColor(Col)
self.BorderColor = Col or Color(190,40,0,255)
end
function PANEL6:Paint()
local BorderColor = self.BorderColor
if self.Hovered then
BorderColor = Color(math.Min(BorderColor.r + 40, 255), math.Min(BorderColor.g + 40, 255), math.Min(BorderColor.b + 40, 255), BorderColor.a)
end
if self.Depressed then
BorderColor = color_transparent
end
draw.RoundedBox(4, 0, 0, self:GetWide(), self:GetTall(), BorderColor)
draw.RoundedBox(4, 2, 2, self:GetWide() - 4, self:GetTall() - 4, Color(40, 40, 40, 255))
end
function PANEL6:OnMousePressed(mouse)
if self:GetDisabled() then return end
self.m_Image:SetSize(24,24)
self.m_Image:SetPos(8,8)
self.Depressed = true
end
function PANEL6:OnMouseReleased(mouse)
if self:GetDisabled() then return end
self.m_Image:SetSize(32,32)
self.m_Image:SetPos(4,4)
self.Depressed = false
self:DoClick()
end
derma.DefineControl("FAdminActionButton", "Button for doing actions", PANEL6, "DImageButton")

View File

@@ -0,0 +1,146 @@
local OverrideScoreboard = CreateClientConVar("FAdmin_OverrideScoreboard", 0, true, false) -- Set if it's a scoreboard or not
function FAdmin.ScoreBoard.ChangeView(newView, ...)
if FAdmin.ScoreBoard.CurrentView == newView or not FAdmin.ScoreBoard.Visible then return end
for _, v in pairs(FAdmin.ScoreBoard[FAdmin.ScoreBoard.CurrentView].Controls) do
v:SetVisible(false)
end
FAdmin.ScoreBoard.CurrentView = newView
FAdmin.ScoreBoard[newView].Show(...)
FAdmin.ScoreBoard.ChangeGmodLogo(FAdmin.ScoreBoard[newView].Logo)
FAdmin.ScoreBoard.Controls.BackButton = FAdmin.ScoreBoard.Controls.BackButton or vgui.Create("DButton")
FAdmin.ScoreBoard.Controls.BackButton:SetVisible(true)
FAdmin.ScoreBoard.Controls.BackButton:SetPos(FAdmin.ScoreBoard.X, FAdmin.ScoreBoard.Y)
FAdmin.ScoreBoard.Controls.BackButton:SetText("")
FAdmin.ScoreBoard.Controls.BackButton:SetTooltip("Click me to go back!")
FAdmin.ScoreBoard.Controls.BackButton:SetCursor("hand")
FAdmin.ScoreBoard.Controls.BackButton:SetSize(100,90)
FAdmin.ScoreBoard.Controls.BackButton:SetZPos(999)
function FAdmin.ScoreBoard.Controls.BackButton:DoClick()
FAdmin.ScoreBoard.ChangeView("Main")
end
FAdmin.ScoreBoard.Controls.BackButton.Paint = function() end
end
--"fadmin/back", gui/gmod_tool
local GmodLogo, TempGmodLogo, GmodLogoColor = surface.GetTextureID("gui/gmod_logo"), surface.GetTextureID("gui/gmod_logo"), color_white
function FAdmin.ScoreBoard.ChangeGmodLogo(new)
if surface.GetTextureID(new) == TempGmodLogo then return end
TempGmodLogo = surface.GetTextureID(new)
for i = 0, 0.5, 0.01 do
timer.Simple(i, function() GmodLogoColor = Color(255,255,255,GmodLogoColor.a-5.1) end)
end
timer.Simple(0.5, function() GmodLogo = surface.GetTextureID(new) end)
for i = 0.5, 1, 0.01 do
timer.Simple(i, function()
GmodLogoColor = Color(255, 255, 255, GmodLogoColor.a + 5.1)
end)
end
end
function FAdmin.ScoreBoard.Background()
surface.SetDrawColor(0,0,0,200)
surface.DrawRect(FAdmin.ScoreBoard.X, FAdmin.ScoreBoard.Y, FAdmin.ScoreBoard.Width, FAdmin.ScoreBoard.Height)
surface.SetTexture(GmodLogo)
surface.SetDrawColor(255,255,255,GmodLogoColor.a)
surface.DrawTexturedRect(FAdmin.ScoreBoard.X - 20, FAdmin.ScoreBoard.Y, 128, 128)
end
function FAdmin.ScoreBoard.DrawScoreBoard()
if (input.IsMouseDown(MOUSE_4) or input.IsKeyDown(KEY_BACKSPACE)) and not FAdmin.ScoreBoard.DontGoBack then
FAdmin.ScoreBoard.ChangeView("Main")
elseif FAdmin.ScoreBoard.DontGoBack then
FAdmin.ScoreBoard.DontGoBack = input.IsMouseDown(MOUSE_4) or input.IsKeyDown(KEY_BACKSPACE)
end
FAdmin.ScoreBoard.Background()
end
function FAdmin.ScoreBoard.ShowScoreBoard()
FAdmin.ScoreBoard.Visible = true
FAdmin.ScoreBoard.DontGoBack = input.IsMouseDown(MOUSE_4) or input.IsKeyDown(KEY_BACKSPACE)
FAdmin.ScoreBoard.Controls.Hostname = FAdmin.ScoreBoard.Controls.Hostname or vgui.Create("DLabel")
FAdmin.ScoreBoard.Controls.Hostname:SetText(DarkRP.deLocalise(GetHostName()))
FAdmin.ScoreBoard.Controls.Hostname:SetFont("ScoreboardHeader")
FAdmin.ScoreBoard.Controls.Hostname:SetColor(Color(200,200,200,200))
FAdmin.ScoreBoard.Controls.Hostname:SetPos(FAdmin.ScoreBoard.X + 90, FAdmin.ScoreBoard.Y + 20)
FAdmin.ScoreBoard.Controls.Hostname:SizeToContents()
FAdmin.ScoreBoard.Controls.Hostname:SetVisible(true)
FAdmin.ScoreBoard.Controls.Description = FAdmin.ScoreBoard.Controls.Description or vgui.Create("DLabel")
FAdmin.ScoreBoard.Controls.Description:SetText(string.format("%s\n%s", GAMEMODE.Name, GAMEMODE.Author))
FAdmin.ScoreBoard.Controls.Description:SetFont("ScoreboardSubtitle")
FAdmin.ScoreBoard.Controls.Description:SetColor(Color(200,200,200,200))
FAdmin.ScoreBoard.Controls.Description:SetPos(FAdmin.ScoreBoard.X + 90, FAdmin.ScoreBoard.Y + 50)
FAdmin.ScoreBoard.Controls.Description:SizeToContents()
if FAdmin.ScoreBoard.X + FAdmin.ScoreBoard.Width / 9.5 + FAdmin.ScoreBoard.Controls.Description:GetWide() > FAdmin.ScoreBoard.Width - 150 then
FAdmin.ScoreBoard.Controls.Description:SetFont("Trebuchet18")
FAdmin.ScoreBoard.Controls.Description:SetPos(FAdmin.ScoreBoard.X + 90, FAdmin.ScoreBoard.Y + 50)
end
FAdmin.ScoreBoard.Controls.Description:SetVisible(true)
FAdmin.ScoreBoard.Controls.ServerSettingsLabel = FAdmin.ScoreBoard.Controls.ServerSettingsLabel or vgui.Create("DLabel")
FAdmin.ScoreBoard.Controls.ServerSettingsLabel:SetFont("ScoreboardSubtitle")
FAdmin.ScoreBoard.Controls.ServerSettingsLabel:SetText("Server settings")
FAdmin.ScoreBoard.Controls.ServerSettingsLabel:SetColor(Color(200,200,200,200))
FAdmin.ScoreBoard.Controls.ServerSettingsLabel:SizeToContents()
FAdmin.ScoreBoard.Controls.ServerSettingsLabel:SetPos(FAdmin.ScoreBoard.Width-150, FAdmin.ScoreBoard.Y + 68)
FAdmin.ScoreBoard.Controls.ServerSettingsLabel:SetVisible(true)
FAdmin.ScoreBoard.Controls.ServerSettings = FAdmin.ScoreBoard.Controls.ServerSettings or vgui.Create("DImageButton")
FAdmin.ScoreBoard.Controls.ServerSettings:SetMaterial("vgui/gmod_tool")
FAdmin.ScoreBoard.Controls.ServerSettings:SetPos(FAdmin.ScoreBoard.Width-200, FAdmin.ScoreBoard.Y - 20)
FAdmin.ScoreBoard.Controls.ServerSettings:SizeToContents()
FAdmin.ScoreBoard.Controls.ServerSettings:SetVisible(true)
function FAdmin.ScoreBoard.Controls.ServerSettings:DoClick()
FAdmin.ScoreBoard.ChangeView("Server")
end
if FAdmin.ScoreBoard.Controls.BackButton then FAdmin.ScoreBoard.Controls.BackButton:SetVisible(true) end
FAdmin.ScoreBoard[FAdmin.ScoreBoard.CurrentView].Show()
gui.EnableScreenClicker(true)
hook.Add("HUDPaint", "FAdmin_ScoreBoard", FAdmin.ScoreBoard.DrawScoreBoard)
hook.Call("FAdmin_ShowFAdminMenu")
return true
end
concommand.Add("+FAdmin_menu", FAdmin.ScoreBoard.ShowScoreBoard)
hook.Add("ScoreboardShow", "FAdmin_scoreboard", function()
if FAdmin.GlobalSetting.FAdmin or OverrideScoreboard:GetBool() then -- Don't show scoreboard when FAdmin is not installed on server
return FAdmin.ScoreBoard.ShowScoreBoard()
end
end)
function FAdmin.ScoreBoard.HideScoreBoard()
if not FAdmin.GlobalSetting.FAdmin then return end
FAdmin.ScoreBoard.Visible = false
CloseDermaMenus()
gui.EnableScreenClicker(false)
hook.Remove("HUDPaint", "FAdmin_ScoreBoard")
for _, v in pairs(FAdmin.ScoreBoard[FAdmin.ScoreBoard.CurrentView].Controls) do
v:SetVisible(false)
end
for _, v in pairs(FAdmin.ScoreBoard.Controls) do
v:SetVisible(false)
end
return true
end
concommand.Add("-FAdmin_menu", FAdmin.ScoreBoard.HideScoreBoard)
hook.Add("ScoreboardHide", "FAdmin_scoreboard", function()
if FAdmin.GlobalSetting.FAdmin or OverrideScoreboard:GetBool() then -- Don't show scoreboard when FAdmin is not installed on server
return FAdmin.ScoreBoard.HideScoreBoard()
end
end)

View File

@@ -0,0 +1,110 @@
local Sorted, SortDown = CreateClientConVar("FAdmin_SortPlayerList", "Team", true), CreateClientConVar("FAdmin_SortPlayerListDown", 1, true)
local allowedSorts = {
["Name"] = true,
["Team"] = true,
["Frags"] = true,
["Deaths"] = true,
["Ping"] = true
}
function FAdmin.ScoreBoard.Main.Show()
local Sort = {}
local ScreenWidth, ScreenHeight = ScrW(), ScrH()
FAdmin.ScoreBoard.X = ScreenWidth * 0.05
FAdmin.ScoreBoard.Y = ScreenHeight * 0.025
FAdmin.ScoreBoard.Width = ScreenWidth * 0.9
FAdmin.ScoreBoard.Height = ScreenHeight * 0.95
FAdmin.ScoreBoard.ChangeView("Main")
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList = FAdmin.ScoreBoard.Main.Controls.FAdminPanelList or vgui.Create("DPanelList")
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:SetVisible(true)
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:Clear(true)
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList.Padding = 3
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:EnableVerticalScrollbar(true)
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:Clear(true)
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:SetPos(FAdmin.ScoreBoard.X + 20, FAdmin.ScoreBoard.Y + 90 + 30 + 20)
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:SetSize(FAdmin.ScoreBoard.Width - 40, FAdmin.ScoreBoard.Height - 90 - 30 - 20 - 20)
Sort.Name = Sort.Name or vgui.Create("DLabel")
Sort.Name:SetText("Sort by: Name")
Sort.Name:SetPos(FAdmin.ScoreBoard.X + 20, FAdmin.ScoreBoard.Y + 90 + 30)
Sort.Name.Type = "Name"
Sort.Name:SetVisible(true)
Sort.Team = Sort.Team or vgui.Create("DLabel")
Sort.Team:SetText("Team")
Sort.Team:SetPos(ScreenWidth * 0.5 - 30, FAdmin.ScoreBoard.Y + 90 + 30)
Sort.Team.Type = "Team"
Sort.Team:SetVisible(true)
Sort.Frags = Sort.Frags or vgui.Create("DLabel")
Sort.Frags:SetText("Kills")
Sort.Frags:SetPos(FAdmin.ScoreBoard.X + FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:GetWide() - 200, FAdmin.ScoreBoard.Y + 90 + 30)
Sort.Frags.Type = "Frags"
Sort.Frags:SetVisible(true)
Sort.Deaths = Sort.Deaths or vgui.Create("DLabel")
Sort.Deaths:SetText("Deaths")
Sort.Deaths:SetPos(FAdmin.ScoreBoard.X + FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:GetWide() - 140, FAdmin.ScoreBoard.Y + 90 + 30)
Sort.Deaths.Type = "Deaths"
Sort.Deaths:SetVisible(true)
Sort.Ping = Sort.Ping or vgui.Create("DLabel")
Sort.Ping:SetText("Ping")
Sort.Ping:SetPos(FAdmin.ScoreBoard.X + FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:GetWide() - 50, FAdmin.ScoreBoard.Y + 90 + 30)
Sort.Ping.Type = "Ping"
Sort.Ping:SetVisible(true)
local sortBy = Sorted:GetString()
sortBy = allowedSorts[sortBy] and sortBy or "Team"
FAdmin.ScoreBoard.Main.PlayerListView(sortBy, SortDown:GetBool())
for _, v in pairs(Sort) do
v:SetFont("Trebuchet20")
v:SizeToContents()
local X, Y = v:GetPos()
v.BtnSort = vgui.Create("DButton")
v.BtnSort:SetText("")
v.BtnSort.Type = "Down"
v.BtnSort.Paint = function(panel, w, h) derma.SkinHook("Paint", "ButtonDown", panel, w, h) end
v.BtnSort:SetSkin(GAMEMODE.Config.DarkRPSkin)
if Sorted:GetString() == v.Type then
v.BtnSort.Depressed = true
v.BtnSort.Type = (SortDown:GetBool() and "Down") or "Up"
end
v.BtnSort:SetSize(16, 16)
v.BtnSort:SetPos(X + v:GetWide() + 5, Y + 4)
function v.BtnSort.DoClick()
for _, b in pairs(Sort) do
b.BtnSort.Depressed = b.BtnSort == v.BtnSort
end
v.BtnSort.Type = (v.BtnSort.Type == "Down" and "Up") or "Down"
v.BtnSort.Paint = function(panel, w, h)
derma.SkinHook("Paint", "Button" .. v.BtnSort.Type, panel, w, h)
end
RunConsoleCommand("FAdmin_SortPlayerList", v.Type)
RunConsoleCommand("FAdmin_SortPlayerListDown", (v.BtnSort.Type == "Down" and "1") or "0")
FAdmin.ScoreBoard.Main.Controls.FAdminPanelList:Clear(true)
FAdmin.ScoreBoard.Main.PlayerListView(v.Type, v.BtnSort.Type == "Down")
end
table.insert(FAdmin.ScoreBoard.Main.Controls, v) -- Add them to the table so they get removed when you close the scoreboard
table.insert(FAdmin.ScoreBoard.Main.Controls, v.BtnSort)
end
end
function FAdmin.ScoreBoard.Main.AddPlayerRightClick(Name, func)
FAdmin.PlayerIcon.RightClickOptions[Name] = func
end
FAdmin.StartHooks["CopySteamID"] = function()
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Copy SteamID", function(ply) SetClipboardText(ply:SteamID()) end)
end

View File

@@ -0,0 +1,181 @@
FAdmin.ScoreBoard.Player.Information = {}
FAdmin.ScoreBoard.Player.ActionButtons = {}
function FAdmin.ScoreBoard.Player.Show(ply)
ply = ply or FAdmin.ScoreBoard.Player.Player
FAdmin.ScoreBoard.Player.Player = ply
if not IsValid(ply) or not IsValid(FAdmin.ScoreBoard.Player.Player) then FAdmin.ScoreBoard.ChangeView("Main") return end
local ScreenHeight = ScrH()
FAdmin.ScoreBoard.Player.Controls.AvatarBackground = vgui.Create("AvatarImage")
FAdmin.ScoreBoard.Player.Controls.AvatarBackground:SetPos(FAdmin.ScoreBoard.X + 20, FAdmin.ScoreBoard.Y + 100)
FAdmin.ScoreBoard.Player.Controls.AvatarBackground:SetSize(184, 184)
FAdmin.ScoreBoard.Player.Controls.AvatarBackground:SetPlayer(ply, 184)
FAdmin.ScoreBoard.Player.Controls.AvatarBackground:SetVisible(true)
FAdmin.ScoreBoard.Player.InfoPanels = FAdmin.ScoreBoard.Player.InfoPanels or {}
for k, v in pairs(FAdmin.ScoreBoard.Player.InfoPanels) do
if IsValid(v) then
v:Remove()
FAdmin.ScoreBoard.Player.InfoPanels[k] = nil
end
end
if IsValid(FAdmin.ScoreBoard.Player.Controls.InfoPanel1) then
FAdmin.ScoreBoard.Player.Controls.InfoPanel1:Remove()
end
FAdmin.ScoreBoard.Player.Controls.InfoPanel1 = vgui.Create("DListLayout")
FAdmin.ScoreBoard.Player.Controls.InfoPanel1:SetPos(FAdmin.ScoreBoard.X + 20, FAdmin.ScoreBoard.Y + 100 + 184 + 5 --[[ + Avatar size]])
FAdmin.ScoreBoard.Player.Controls.InfoPanel1:SetSize(184, ScreenHeight * 0.1 + 2)
FAdmin.ScoreBoard.Player.Controls.InfoPanel1:SetVisible(true)
FAdmin.ScoreBoard.Player.Controls.InfoPanel1:Clear(true)
FAdmin.ScoreBoard.Player.Controls.InfoPanel2 = FAdmin.ScoreBoard.Player.Controls.InfoPanel2 or vgui.Create("FAdminPanelList")
FAdmin.ScoreBoard.Player.Controls.InfoPanel2:SetPos(FAdmin.ScoreBoard.X + 25 + 184 --[[+ Avatar]], FAdmin.ScoreBoard.Y + 100)
FAdmin.ScoreBoard.Player.Controls.InfoPanel2:SetSize(FAdmin.ScoreBoard.Width - 184 - 30 - 10, 184 + 5 + ScreenHeight * 0.1 + 2)
FAdmin.ScoreBoard.Player.Controls.InfoPanel2:SetVisible(true)
FAdmin.ScoreBoard.Player.Controls.InfoPanel2:Clear(true)
local function AddInfoPanel()
local pan = FAdmin.ScoreBoard.Player.Controls.InfoPanel2:Add("DListLayout")
pan:SetSize(1, FAdmin.ScoreBoard.Player.Controls.InfoPanel2:GetTall())
table.insert(FAdmin.ScoreBoard.Player.InfoPanels, pan)
return pan
end
local SelectedPanel = AddInfoPanel() -- Make first panel to put the first things in
for k, v in pairs(FAdmin.ScoreBoard.Player.Information) do
SelectedPanel:Dock(LEFT)
local Value = v.func(FAdmin.ScoreBoard.Player.Player)
--if not Value or Value == "" then return --[[ Value = "N/A" ]] end
if Value and Value ~= "" then
local Text = vgui.Create("DLabel")
Text:Dock(LEFT)
Text:SetFont("TabLarge")
Text:SetText(v.name .. ": " .. Value)
Text:SizeToContents()
Text:SetColor(Color(200,200,200,200))
Text:SetTooltip("Click to copy " .. v.name .. " to clipboard")
Text:SetMouseInputEnabled(true)
function Text:OnMousePressed(mcode)
self:SetTooltip(v.name .. " copied to clipboard!")
ChangeTooltip(self)
SetClipboardText(Value)
self:SetTooltip("Click to copy " .. v.name .. " to clipboard")
end
timer.Create("FAdmin_Scoreboard_text_update_" .. v.name, 1, 0, function()
if not IsValid(ply) or not IsValid(FAdmin.ScoreBoard.Player.Player) or not IsValid(Text) then
timer.Remove("FAdmin_Scoreboard_text_update_" .. v.name)
if FAdmin.ScoreBoard.Visible and (not IsValid(ply) or not IsValid(FAdmin.ScoreBoard.Player.Player)) then FAdmin.ScoreBoard.ChangeView("Main") end
return
end
Value = v.func(FAdmin.ScoreBoard.Player.Player)
if not Value or Value == "" then Value = "N/A" end
Text:SetText(v.name .. ": " .. Value)
end)
if (#FAdmin.ScoreBoard.Player.Controls.InfoPanel1:GetChildren() * 17 + 17) <= FAdmin.ScoreBoard.Player.Controls.InfoPanel1:GetTall() and not v.NewPanel then
FAdmin.ScoreBoard.Player.Controls.InfoPanel1:Add(Text)
else
if #SelectedPanel:GetChildren() * 17 + 17 >= SelectedPanel:GetTall() or v.NewPanel then
SelectedPanel = AddInfoPanel() -- Add new panel if the last one is full
end
SelectedPanel:Add(Text)
if Text:GetWide() > SelectedPanel:GetWide() then
SelectedPanel:SetWide(Text:GetWide() + 40)
end
end
end
end
local CatColor = team.GetColor(ply:Team())
if GAMEMODE.Name == "Sandbox" then
CatColor = Color(100, 150, 245, 255)
if ply:Team() == TEAM_CONNECTING then
CatColor = Color(200, 120, 50, 255)
elseif ply:IsAdmin() then
CatColor = Color(30, 200, 50, 255)
end
if ply:GetFriendStatus() == "friend" then
CatColor = Color(236, 181, 113, 255)
end
end
CatColor = hook.Run("FAdmin_PlayerRowColour", ply, CatColor) or CatColor
FAdmin.ScoreBoard.Player.Controls.ButtonCat = FAdmin.ScoreBoard.Player.Controls.ButtonCat or vgui.Create("FAdminPlayerCatagory")
FAdmin.ScoreBoard.Player.Controls.ButtonCat:SetLabel(" Player options!")
FAdmin.ScoreBoard.Player.Controls.ButtonCat.CatagoryColor = CatColor
FAdmin.ScoreBoard.Player.Controls.ButtonCat:SetSize(FAdmin.ScoreBoard.Width - 40, 100)
FAdmin.ScoreBoard.Player.Controls.ButtonCat:SetPos(FAdmin.ScoreBoard.X + 20, FAdmin.ScoreBoard.Y + 100 + FAdmin.ScoreBoard.Player.Controls.InfoPanel2:GetTall() + 5)
FAdmin.ScoreBoard.Player.Controls.ButtonCat:SetVisible(true)
function FAdmin.ScoreBoard.Player.Controls.ButtonCat:Toggle()
end
FAdmin.ScoreBoard.Player.Controls.ButtonPanel = FAdmin.ScoreBoard.Player.Controls.ButtonPanel or vgui.Create("FAdminPanelList", FAdmin.ScoreBoard.Player.Controls.ButtonCat)
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:SetSpacing(5)
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:EnableHorizontal(true)
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:EnableVerticalScrollbar(true)
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:SizeToContents()
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:SetVisible(true)
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:SetSize(0, (ScreenHeight - FAdmin.ScoreBoard.Y - 40) - (FAdmin.ScoreBoard.Y + 100 + FAdmin.ScoreBoard.Player.Controls.InfoPanel2:GetTall() + 5))
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:Clear()
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:DockMargin(5, 5, 5, 5)
for _, v in ipairs(FAdmin.ScoreBoard.Player.ActionButtons) do
if v.Visible == true or (isfunction(v.Visible) and v.Visible(FAdmin.ScoreBoard.Player.Player) == true) then
local ActionButton = vgui.Create("FAdminActionButton")
local imageType = TypeID(v.Image)
if imageType == TYPE_STRING then
ActionButton:SetImage(v.Image or "icon16/exclamation")
elseif imageType == TYPE_TABLE then
ActionButton:SetImage(v.Image[1])
if v.Image[2] then ActionButton:SetImage2(v.Image[2]) end
elseif imageType == TYPE_FUNCTION then
local img1, img2 = v.Image(ply)
ActionButton:SetImage(img1)
if img2 then ActionButton:SetImage2(img2) end
else
ActionButton:SetImage("icon16/exclamation")
end
local name = v.Name
if isfunction(name) then name = name(FAdmin.ScoreBoard.Player.Player) end
ActionButton:SetText(DarkRP.deLocalise(name))
ActionButton:SetBorderColor(v.color)
function ActionButton:DoClick()
if not IsValid(FAdmin.ScoreBoard.Player.Player) then return end
return v.Action(FAdmin.ScoreBoard.Player.Player, self)
end
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:AddItem(ActionButton)
if v.OnButtonCreated then
v.OnButtonCreated(FAdmin.ScoreBoard.Player.Player, ActionButton)
end
end
end
FAdmin.ScoreBoard.Player.Controls.ButtonPanel:Dock(TOP)
end
function FAdmin.ScoreBoard.Player:AddInformation(name, func, ForceNewPanel) -- ForeNewPanel is to start a new column
table.insert(FAdmin.ScoreBoard.Player.Information, {name = name, func = func, NewPanel = ForceNewPanel})
end
function FAdmin.ScoreBoard.Player:AddActionButton(Name, Image, color, Visible, Action, OnButtonCreated)
table.insert(FAdmin.ScoreBoard.Player.ActionButtons, {Name = Name, Image = Image, color = color, Visible = Visible, Action = Action, OnButtonCreated = OnButtonCreated})
end
FAdmin.ScoreBoard.Player:AddInformation("Name", function(ply) return ply:Nick() end)
FAdmin.ScoreBoard.Player:AddInformation("Kills", function(ply) return ply:Frags() end)
FAdmin.ScoreBoard.Player:AddInformation("Deaths", function(ply) return ply:Deaths() end)
FAdmin.ScoreBoard.Player:AddInformation("Health", function(ply) return ply:Health() end)
FAdmin.ScoreBoard.Player:AddInformation("Ping", function(ply) return ply:Ping() end)
FAdmin.ScoreBoard.Player:AddInformation("SteamID", function(ply) return ply:SteamID() end, true)

View File

@@ -0,0 +1,227 @@
FAdmin.ScoreBoard.Server.Information = {} -- Compatibility for autoreload
FAdmin.ScoreBoard.Server.ActionButtons = {} -- Refresh server buttons when reloading gamemode
local function MakeServerOptions()
local _, YPos, Width = 20, FAdmin.ScoreBoard.Y + 120 + FAdmin.ScoreBoard.Height / 5 + 20, (FAdmin.ScoreBoard.Width - 40) / 3
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat = FAdmin.ScoreBoard.Server.Controls.ServerActionsCat or vgui.Create("FAdminPlayerCatagory")
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat:SetLabel(" Server Actions")
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat.CatagoryColor = Color(155, 0, 0, 255)
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat:SetSize(Width-5, FAdmin.ScoreBoard.Height - 20 - YPos)
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat:SetPos(FAdmin.ScoreBoard.X + 20, YPos)
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat:SetVisible(true)
function FAdmin.ScoreBoard.Server.Controls.ServerActionsCat:Toggle()
end
FAdmin.ScoreBoard.Server.Controls.ServerActions = FAdmin.ScoreBoard.Server.Controls.ServerActions or vgui.Create("FAdminPanelList")
FAdmin.ScoreBoard.Server.Controls.ServerActionsCat:SetContents(FAdmin.ScoreBoard.Server.Controls.ServerActions)
FAdmin.ScoreBoard.Server.Controls.ServerActions:SetTall(FAdmin.ScoreBoard.Height - 20 - YPos)
for k, v in ipairs(FAdmin.ScoreBoard.Server.Controls.ServerActions:GetChildren()) do
if k == 1 then continue end
v:Remove()
end
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat = FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat or vgui.Create("FAdminPlayerCatagory")
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat:SetLabel(" Player Actions")
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat.CatagoryColor = Color(0, 155, 0, 255)
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat:SetSize(Width-5, FAdmin.ScoreBoard.Height - 20 - YPos)
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat:SetPos(FAdmin.ScoreBoard.X + 20 + Width, YPos)
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat:SetVisible(true)
function FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat:Toggle()
end
FAdmin.ScoreBoard.Server.Controls.PlayerActions = FAdmin.ScoreBoard.Server.Controls.PlayerActions or vgui.Create("FAdminPanelList")
FAdmin.ScoreBoard.Server.Controls.PlayerActionsCat:SetContents(FAdmin.ScoreBoard.Server.Controls.PlayerActions)
FAdmin.ScoreBoard.Server.Controls.PlayerActions:SetTall(FAdmin.ScoreBoard.Height - 20 - YPos)
for k, v in ipairs(FAdmin.ScoreBoard.Server.Controls.PlayerActions:GetChildren()) do
if k == 1 then continue end
v:Remove()
end
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat = FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat or vgui.Create("FAdminPlayerCatagory")
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat:SetLabel(" Server Settings")
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat.CatagoryColor = Color(0, 0, 155, 255)
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat:SetSize(Width-5, FAdmin.ScoreBoard.Height - 20 - YPos)
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat:SetPos(FAdmin.ScoreBoard.X + 20 + Width * 2, YPos)
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat:SetVisible(true)
function FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat:Toggle()
end
FAdmin.ScoreBoard.Server.Controls.ServerSettings = FAdmin.ScoreBoard.Server.Controls.ServerSettings or vgui.Create("FAdminPanelList")
FAdmin.ScoreBoard.Server.Controls.ServerSettingsCat:SetContents(FAdmin.ScoreBoard.Server.Controls.ServerSettings)
FAdmin.ScoreBoard.Server.Controls.ServerSettings:SetTall(FAdmin.ScoreBoard.Height - 20 - YPos)
for k, v in ipairs(FAdmin.ScoreBoard.Server.Controls.ServerSettings:GetChildren()) do
if k == 1 then continue end
v:Remove()
end
for k, v in ipairs(FAdmin.ScoreBoard.Server.ActionButtons) do
local visible = v.Visible == true or (isfunction(v.Visible) and v.Visible(LocalPlayer()) == true)
local ActionButton = vgui.Create("FAdminActionButton")
local imageType = TypeID(v.Image)
if imageType == TYPE_STRING then
ActionButton:SetImage(v.Image or "icon16/exclamation")
elseif imageType == TYPE_TABLE then
ActionButton:SetImage(v.Image[1])
if v.Image[2] then ActionButton:SetImage2(v.Image[2]) end
elseif imageType == TYPE_FUNCTION then
local img1, img2 = v.Image()
ActionButton:SetImage(img1)
if img2 then ActionButton:SetImage2(img2) end
else
ActionButton:SetImage("icon16/exclamation")
end
local name = v.Name
if isfunction(name) then name = name() end
ActionButton:SetText(DarkRP.deLocalise(name))
ActionButton:SetBorderColor(visible and v.color or Color(120, 120, 120))
ActionButton:SetDisabled(not visible)
ActionButton:Dock(TOP)
function ActionButton:DoClick()
return v.Action(self)
end
FAdmin.ScoreBoard.Server.Controls[v.TYPE]:Add(ActionButton)
if v.OnButtonCreated then
v.OnButtonCreated(ActionButton)
end
end
end
function FAdmin.ScoreBoard.Server:AddServerAction(Name, Image, color, Visible, Action, OnButtonCreated)
table.insert(FAdmin.ScoreBoard.Server.ActionButtons, {TYPE = "ServerActions", Name = Name, Image = Image, color = color, Visible = Visible, Action = Action, OnButtonCreated = OnButtonCreated})
end
function FAdmin.ScoreBoard.Server:AddPlayerAction(Name, Image, color, Visible, Action, OnButtonCreated)
table.insert(FAdmin.ScoreBoard.Server.ActionButtons, {TYPE = "PlayerActions", Name = Name, Image = Image, color = color, Visible = Visible, Action = Action, OnButtonCreated = OnButtonCreated})
end
function FAdmin.ScoreBoard.Server:AddServerSetting(Name, Image, color, Visible, Action, OnButtonCreated)
table.insert(FAdmin.ScoreBoard.Server.ActionButtons, {TYPE = "ServerSettings", Name = Name, Image = Image, color = color, Visible = Visible, Action = Action, OnButtonCreated = OnButtonCreated})
end
function FAdmin.ScoreBoard.Server.Show(ply)
FAdmin.ScoreBoard.Server.InfoPanels = FAdmin.ScoreBoard.Server.InfoPanels or {}
for k, v in pairs(FAdmin.ScoreBoard.Server.InfoPanels) do
if IsValid(v) then
v:Remove()
FAdmin.ScoreBoard.Server.InfoPanels[k] = nil
end
end
if IsValid(FAdmin.ScoreBoard.Server.Controls.InfoPanel) then
FAdmin.ScoreBoard.Server.Controls.InfoPanel:Remove()
end
FAdmin.ScoreBoard.Server.Controls.InfoPanel = vgui.Create("FAdminPanelList")
FAdmin.ScoreBoard.Server.Controls.InfoPanel:SetPos(FAdmin.ScoreBoard.X + 20, FAdmin.ScoreBoard.Y + 120)
FAdmin.ScoreBoard.Server.Controls.InfoPanel:SetSize(FAdmin.ScoreBoard.Width - 40, FAdmin.ScoreBoard.Height / 5)
FAdmin.ScoreBoard.Server.Controls.InfoPanel:SetVisible(true)
FAdmin.ScoreBoard.Server.Controls.InfoPanel:Clear(true)
local function AddInfoPanel()
local pan = vgui.Create("FAdminPanelList")
pan:SetSize(1, FAdmin.ScoreBoard.Server.Controls.InfoPanel:GetTall())
pan:Dock(LEFT)
FAdmin.ScoreBoard.Server.Controls.InfoPanel:Add(pan)
table.insert(FAdmin.ScoreBoard.Server.InfoPanels, pan)
return pan
end
local SelectedPanel = AddInfoPanel() -- Make first panel to put the first things in
for _, v in pairs(FAdmin.ScoreBoard.Server.Information) do
local Text = vgui.Create("DLabel")
Text:SetFont("TabLarge")
Text:SetColor(Color(255,255,255,200))
Text:Dock(TOP)
Text.Func = v.Func
local EndText
local function RefreshText()
local Value = v.func()
if not Value or Value == "" then
Value = "N/A"
end
EndText = v.name .. ": " .. Value
local strLen = string.len(EndText)
if strLen > 40 then
local NewValue = string.sub(EndText, 1, 40)
for i = 40, strLen, 34 do
NewValue = NewValue .. "\n " .. string.sub(EndText, i + 1, i + 34)
end
EndText = NewValue
else
local MaxWidth = 240
surface.SetFont("TabLarge")
local TextWidth = surface.GetTextSize(v.name .. ": " .. Value)
if TextWidth <= MaxWidth then
local SpacesAmount = (MaxWidth - TextWidth) / 3
local Spaces = ""
for i = 1, SpacesAmount, 1 do
Spaces = Spaces .. " "
end
EndText = v.name .. ":" .. Spaces .. Value
end
end
Text:SetText(DarkRP.deLocalise(EndText))
Text:SizeToContents()
Text:SetTooltip("Click to copy " .. v.name .. " to clipboard")
Text:SetMouseInputEnabled(true)
end
RefreshText()
function Text:OnMousePressed(mcode)
self:SetTooltip(v.name .. " copied to clipboard!")
ChangeTooltip(self)
SetClipboardText(v.func() or "")
self:SetTooltip("Click to copy " .. v.name .. " to clipboard")
end
timer.Create("FAdmin_Scoreboard_text_update_" .. v.name, 1, 0, function()
if not IsValid(Text) then
timer.Remove("FAdmin_Scoreboard_text_update_" .. v.name)
FAdmin.ScoreBoard.ChangeView("Main")
return
end
RefreshText()
end)
if #SelectedPanel:GetChildren() * 17 + 17 >= SelectedPanel:GetTall() or v.NewPanel then
SelectedPanel = AddInfoPanel()
end
-- Add new panel if the last one is full
SelectedPanel:Add(Text)
if Text:GetWide() > SelectedPanel:GetWide() then
SelectedPanel:SetWide(Text:GetWide() + 40)
end
end
MakeServerOptions()
end
function FAdmin.ScoreBoard.Server:AddInformation(name, func, ForceNewPanel) -- ForeNewPanel is to start a new column
table.insert(FAdmin.ScoreBoard.Server.Information, {name = name, func = func, NewPanel = ForceNewPanel})
end
FAdmin.ScoreBoard.Server:AddInformation("Hostname", GetHostName)
FAdmin.ScoreBoard.Server:AddInformation("Gamemode", function() return GAMEMODE.Name end)
FAdmin.ScoreBoard.Server:AddInformation("Author", function() return GAMEMODE.Author end)
FAdmin.ScoreBoard.Server:AddInformation("Map", game.GetMap)
FAdmin.ScoreBoard.Server:AddInformation("Players", function() return player.GetCount() .. "/" .. game.MaxPlayers() end)
FAdmin.ScoreBoard.Server:AddInformation("Ping", function() return LocalPlayer():Ping() end)

View File

@@ -0,0 +1,24 @@
FAdmin.ScoreBoard = FAdmin.ScoreBoard or {}
local ScreenWidth, ScreenHeight = ScrW(), ScrH()
FAdmin.ScoreBoard.X = ScreenWidth * 0.05
FAdmin.ScoreBoard.Y = ScreenHeight * 0.025
FAdmin.ScoreBoard.Width = ScreenWidth * 0.9
FAdmin.ScoreBoard.Height = ScreenHeight * 0.95
FAdmin.ScoreBoard.Controls = FAdmin.ScoreBoard.Controls or {}
FAdmin.ScoreBoard.CurrentView = "Main"
FAdmin.ScoreBoard.Main = FAdmin.ScoreBoard.Main or {}
FAdmin.ScoreBoard.Main.Controls = FAdmin.ScoreBoard.Main.Controls or {}
FAdmin.ScoreBoard.Main.Logo = "gui/gmod_logo"
FAdmin.ScoreBoard.Player = FAdmin.ScoreBoard.Player or {}
FAdmin.ScoreBoard.Player.Controls = FAdmin.ScoreBoard.Player.Controls or {}
FAdmin.ScoreBoard.Player.Player = NULL
FAdmin.ScoreBoard.Player.Logo = "fadmin/back"
FAdmin.ScoreBoard.Server = FAdmin.ScoreBoard.Server or {}
FAdmin.ScoreBoard.Server.Controls = FAdmin.ScoreBoard.Server.Controls or {}
FAdmin.ScoreBoard.Server.Logo = "fadmin/back"

View File

@@ -0,0 +1,53 @@
--[[---------------------------------------------------------------------------
Common times for several punishment actions
---------------------------------------------------------------------------]]
FAdmin.PlayerActions.commonTimes = {}
FAdmin.PlayerActions.commonTimes[0] = "indefinitely"
FAdmin.PlayerActions.commonTimes[10] = "10 seconds"
FAdmin.PlayerActions.commonTimes[30] = "30 seconds"
FAdmin.PlayerActions.commonTimes[60] = "1 minute"
FAdmin.PlayerActions.commonTimes[300] = "5 minutes"
FAdmin.PlayerActions.commonTimes[600] = "10 minutes"
function FAdmin.PlayerActions.addTimeSubmenu(menu, submenuText, submenuClick, submenuItemClick)
local SubMenu = menu:AddSubMenu(submenuText, submenuClick)
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
SubMenu:AddPanel(Padding)
local SubMenuTitle = vgui.Create("DLabel")
SubMenuTitle:SetText(" Time:\n")
SubMenuTitle:SetFont("UiBold")
SubMenuTitle:SizeToContents()
SubMenuTitle:SetTextColor(color_black)
SubMenu:AddPanel(SubMenuTitle)
for secs, Time in SortedPairs(FAdmin.PlayerActions.commonTimes) do
SubMenu:AddOption(Time, function() submenuItemClick(secs) end)
end
end
function FAdmin.PlayerActions.addTimeMenu(ItemClick)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Time:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for secs, Time in SortedPairs(FAdmin.PlayerActions.commonTimes) do
menu:AddOption(Time, function() ItemClick(secs) end)
end
menu:Open()
end

View File

@@ -0,0 +1,22 @@
FAdmin.StartHooks["CleanUp"] = function()
FAdmin.Access.AddPrivilege("CleanUp", 2)
FAdmin.Commands.AddCommand("ClearDecals", nil)
FAdmin.Commands.AddCommand("StopSounds", nil)
FAdmin.Commands.AddCommand("CleanUp", nil)
FAdmin.ScoreBoard.Server:AddServerAction("Clear decals", "fadmin/icons/cleanup", Color(155, 0, 0, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "CleanUp") end, function(ply, button)
RunConsoleCommand("_FAdmin", "ClearDecals")
end)
FAdmin.ScoreBoard.Server:AddServerAction("Stop all sounds", "fadmin/icons/cleanup", Color(155, 0, 0, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "CleanUp") end, function(ply, button)
RunConsoleCommand("_FAdmin", "StopSounds")
end)
usermessage.Hook("FAdmin_StopSounds", function()
RunConsoleCommand("stopsound") -- bypass for ConCommand blocking it
end)
FAdmin.ScoreBoard.Server:AddServerAction("Clean up server", "fadmin/icons/cleanup", Color(155, 0, 0, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "CleanUp") end, function(ply, button)
RunConsoleCommand("_FAdmin", "CleanUp")
end)
end

View File

@@ -0,0 +1,44 @@
local function ClearDecals(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "CleanUp") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
for _, v in ipairs(player.GetAll()) do
v:ConCommand("r_cleardecals")
end
FAdmin.Messages.ActionMessage(ply, player.GetAll(), "You have removed all decals. NOTE: this does NOT make the server ANY less laggy!", "All decals have been removed. NOTE: this does NOT make the server ANY less laggy!", "Removed all decals.")
return true
end
local function StopSounds(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "CleanUp") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
umsg.Start("FAdmin_StopSounds")
umsg.End()
FAdmin.Messages.ActionMessage(ply, player.GetAll(), "You have stopped all sounds", "All sounds have been stopped", "Stopped all sounds")
return true
end
local function CleanUp(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "CleanUp") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
game.CleanUpMap()
FAdmin.Messages.ActionMessage(ply, player.GetAll(), "You have cleaned up the map", "The map has been cleaned up", "Cleaned up the map")
return true
end
FAdmin.StartHooks["CleanUp"] = function()
FAdmin.Commands.AddCommand("ClearDecals", ClearDecals)
FAdmin.Commands.AddCommand("StopSounds", StopSounds)
FAdmin.Commands.AddCommand("CleanUp", CleanUp)
local oldCleanup = concommand.GetTable()["gmod_admin_cleanup"]
concommand.Add("gmod_admin_cleanup", function(ply, cmd, args)
if args[1] then return oldCleanup(ply, cmd, args) end
return CleanUp(ply, cmd, args)
end)
FAdmin.Access.AddPrivilege("CleanUp", 2)
end

View File

@@ -0,0 +1,109 @@
local Options = {}
local targets
local colorBackground = Color(0, 0, 0, 200)
local colorHighlight = Color(255, 125, 0, 200)
hook.Add("ChatTextChanged", "FAdmin_Chat_autocomplete", function(text)
if not FAdmin.GlobalSetting.FAdmin then return end
Options = {}
local prefix = GetGlobalString("FAdmin_commandprefix")
prefix = prefix ~= '' and prefix or '/'
if string.sub(text, 1, 1) ~= prefix then targets = nil return end
local TExplode = string.Explode(" ", string.sub(text, 2))
if not TExplode[1] then return end
local Command = string.lower(TExplode[1])
local Args = table.Copy(TExplode)
Args[1] = nil
Args = table.ClearKeys(Args)
local optionsCount = 0
for k, v in pairs(FAdmin.Commands.List) do
if string.find(string.lower(k), Command, 1, true) ~= 1 then continue end
Options[prefix .. k] = table.Copy(v.ExtraArgs)
optionsCount = optionsCount + 1
end
local ChatBoxPosX, ChatBoxPosY = chat.GetChatBoxPos()
local ChatBoxWidth = chat.GetChatBoxSize() -- Don't need height
local DidMakeShorter = false
table.sort(Options)
local i = 1
for k in pairs(Options) do
local Pos = ChatBoxPosY + i * 24
if Pos + 24 > ScrH() then
Options[k] = nil
DidMakeShorter = true
optionsCount = optionsCount - 1
end
i = i + 1
end
-- Player arguments
local firstVal = table.GetFirstValue(Options)
if optionsCount == 1 and firstVal[#Args] and string.match(firstVal[#Args], ".Player.") then
local players = {}
for _, v in ipairs(FAdmin.FindPlayer(Args[#Args]) or {}) do
if not IsValid(v) then continue end
table.insert(players, v:Nick())
end
targets = table.concat(players, ", ")
end
local xPos = ChatBoxPosX + ChatBoxWidth + 2
hook.Add("HUDPaint", "FAdmin_Chat_autocomplete", function()
local j = 0
for option, args in pairs(Options) do
draw.WordBox(4, xPos, ChatBoxPosY + j * 24, option, "UiBold", colorBackground, color_white)
for k, arg in pairs(args) do
draw.WordBox(4, xPos + k * 130, ChatBoxPosY + j * 24, arg, "UiBold", colorBackground, color_white)
end
j = j + 1
end
if targets then
draw.WordBox(4, xPos, ChatBoxPosY + j * 24, "Targets: " .. targets, "UiBold", colorHighlight, color_white)
end
if DidMakeShorter then
draw.WordBox(4, xPos, ChatBoxPosY + j * 24, "...", "UiBold", colorBackground, color_white)
end
end)
end)
hook.Add("FinishChat", "FAdmin_Chat_autocomplete", function() hook.Remove("HUDPaint", "FAdmin_Chat_autocomplete") end)
local plyIndex = 1
hook.Add("OnChatTab", "FAdmin_Chat_autocomplete", function(text)
if not FAdmin.GlobalSetting.FAdmin then return end
for command in pairs(Options) do
if string.find(text, " ") == nil then
return string.sub(command, 1, string.find(command, " "))
elseif string.find(text, " ") then
plyIndex = plyIndex + 1
if plyIndex > player.GetCount() then
plyIndex = 1
end
return string.sub(command, 1, string.find(command, " ")) .. " " .. string.sub(player.GetAll()[plyIndex]:Nick(), 1, string.find(player.GetAll()[plyIndex]:Nick(), " "))
end
end
end)
FAdmin.StartHooks["Chatcommands"] = function()
FAdmin.ScoreBoard.Server:AddServerSetting("Set FAdmin's chat command prefix", "fadmin/icons/message", Color(0, 0, 155, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "ServerSetting") end, function()
local prefix = GetGlobalString("FAdmin_commandprefix")
prefix = prefix ~= '' and prefix or '/'
Derma_StringRequest("Set chat command prefix", "Make sure it's only one character!", prefix, fp{RunConsoleCommand, "_Fadmin", "CommandPrefix"})
end)
end

View File

@@ -0,0 +1,28 @@
local function AutoComplete(command, args)
local autocomplete = {}
args = string.Explode(" ", args)
table.remove(args, 1) --Remove the first space
if args[1] == "" then
for k in pairs(FAdmin.Commands.List) do
table.insert(autocomplete, command .. " " .. k)
end
elseif not args[2] or args[3] then
for k, v in pairs(FAdmin.Commands.List) do
if string.sub(k, 1, string.len(args[1])) == args[1] then
local ExtraArgs = table.concat(v.ExtraArgs, " ")
table.insert(autocomplete, command .. " " .. k .. " " .. ExtraArgs)
end
end
elseif not args[3] and FAdmin.Commands.List[string.lower(args[1])] and FAdmin.Commands.List[string.lower(args[1])].ExtraArgs[1] == "<Player>" then
for _, v in ipairs(player.GetAll()) do
if args[2] == "" or table.HasValue(FAdmin.FindPlayer(args[2]) or {}, v) then
table.insert(autocomplete, command .. " " .. args[1] .. " " .. v:Nick())
end
end
end
table.sort(autocomplete)
return autocomplete
end
concommand.Add("FAdmin", function(ply, cmd, args)
RunConsoleCommand("_" .. cmd, unpack(args))
end, AutoComplete)

View File

@@ -0,0 +1,6 @@
FAdmin.Commands = {}
FAdmin.Commands.List = {}
function FAdmin.Commands.AddCommand(name, callback, ...)
FAdmin.Commands.List[string.lower(name)] = {callback = callback, ExtraArgs = {...}}
end

View File

@@ -0,0 +1,52 @@
local convar = CreateConVar("FAdmin_commandprefix", "/", {FCVAR_SERVER_CAN_EXECUTE})
SetGlobalString("FAdmin_commandprefix", convar:GetString())
cvars.AddChangeCallback("FAdmin_commandprefix", function()
SetGlobalString("FAdmin_commandprefix", convar:GetString())
end)
hook.Add("PlayerSay", "FAdminChatCommands", function(ply, text, Team, dead)
local prefix = convar:GetString()
if string.sub(text, 1, 1) ~= prefix then return end
local TExplode = string.Explode(" ", string.sub(text, 2))
if not TExplode then return end
for k, v in ipairs(TExplode) do
if string.sub(v, -1) == "," and TExplode[k + 1] then
TExplode[k] = (TExplode[k] or "") .. (TExplode[k + 1] or "")
table.remove(TExplode, k + 1)
end
end
table.ClearKeys(TExplode, false)
local Command = string.lower(TExplode[1])
local Args = table.Copy(TExplode)
Args[1] = nil
Args = table.ClearKeys(Args)
if FAdmin.Commands.List[Command] then
local res = {FAdmin.Commands.List[Command].callback(ply, Command, Args)}
hook.Call("FAdmin_OnCommandExecuted", nil, ply, Command, Args, res)
return ""
end
end)
FAdmin.StartHooks["Chatcommands"] = function()
convar = convar or GetConVar("FAdmin_commandprefix")
FAdmin.Commands.AddCommand("CommandPrefix", function(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ServerSetting") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] or string.len(args[1]) ~= 1 then return end
FAdmin.Messages.ActionMessage(ply, player.GetAll(), ply:Nick() .. " set FAdmin's chat command prefix to " .. args[1], "FAdmin's chat command prefix has been set to " .. args[1], "Chat command prefix set to" .. args[1])
RunConsoleCommand("FAdmin_commandprefix", args[1])
FAdmin.SaveSetting("FAdmin_commandprefix", args[1])
return true
end)
end

View File

@@ -0,0 +1,71 @@
local function concommand_executed(ply, cmd, args)
if not args[1] then return end
local name = string.lower(args[1])
if not name or not FAdmin.Commands.List[name] then
FAdmin.Messages.SendMessage(ply, 1, "Command does not exist!")
return
end
local args2 = args
table.remove(args2, 1)
for k, v in pairs(args2) do
if string.sub(v, -1) == "," and args2[k + 1] then
args2[k] = args2[k] .. args2[k + 1]
table.remove(args2, k + 1)
end
end
table.ClearKeys(args2)
local res = {FAdmin.Commands.List[name].callback(ply, name, args2)}
hook.Call("FAdmin_OnCommandExecuted", nil, ply, name, args2, res)
end
local function AutoComplete(command, ...)
local autocomplete = {}
local args = string.Explode(" ", ...)
table.remove(args, 1) --Remove the first space
if args[1] == "" then
for k in pairs(FAdmin.Commands.List) do
table.insert(autocomplete, command .. " " .. k)
end
elseif not args[2] then
for k in pairs(FAdmin.Commands.List) do
if string.sub(k, 1, string.len(args[1])) == args[1] then
table.insert(autocomplete, command .. " " .. k)
end
end
end
table.sort(autocomplete)
return autocomplete
end
concommand.Add("_FAdmin", concommand_executed, AutoComplete)
concommand.Add("FAdmin", concommand_executed, AutoComplete)
-- DO NOT EDIT THIS, NO MATTER HOW MUCH YOU'VE EDITED FADMIN IT DOESN'T GIVE YOU ANY RIGHT TO CHANGE CREDITS AND/OR REMOVE THE AUTHOR
FAdmin.Commands.AddCommand("FAdminCredits", function(ply, cmd, args)
if ply:SteamID() == "STEAM_0:0:8944068" and args[1] then
local targets = FAdmin.FindPlayer(args[1])
if not targets or (#targets == 1 and not IsValid(targets[1])) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if IsValid(target) then
concommand_executed(target, "FAdmin", {"FAdminCredits"})
end
end
FAdmin.Messages.SendMessage(ply, 4, "Credits sent!")
return true
end
FAdmin.Messages.SendMessage(ply, 2, "FAdmin by (FPtje) Falco, STEAM_0:0:8944068")
for _, v in ipairs(player.GetAll()) do
if v:SteamID() == "STEAM_0:0:8944068" then
FAdmin.Messages.SendMessage(ply, 4, "(FPtje) Falco is in the server at this moment")
return true
end
end
FAdmin.Messages.SendMessage(ply, 5, "(FPtje) Falco is NOT in the server at this moment")
return true
end)

View File

@@ -0,0 +1,17 @@
local logging = CreateConVar("FAdmin_logging", 1, {FCVAR_REPLICATED, FCVAR_SERVER_CAN_EXECUTE})
if SERVER then return end
FAdmin.StartHooks["Logging"] = function()
FAdmin.Access.AddPrivilege("Logging", 3)
FAdmin.Commands.AddCommand("Logging", nil)
FAdmin.ScoreBoard.Server:AddServerSetting(function() return (logging:GetBool() and "Disable" or "Enable") .. " Logging" end,
function() return "fadmin/icons/message", logging:GetBool() and "fadmin/icons/disable" end,
Color(0, 0, 155, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "Logging") end, function(button)
button:SetImage2((not logging:GetBool() and "fadmin/icons/disable") or "null")
button:SetText((not logging:GetBool() and "Disable" or "Enable") .. " Logging")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_Fadmin", "Logging", logging:GetBool() and 0 or 1)
end)
end

View File

@@ -0,0 +1,161 @@
local logging
FAdmin.StartHooks["Logging"] = function()
FAdmin.Access.AddPrivilege("Logging", 3)
FAdmin.Commands.AddCommand("Logging", function(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Logging") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not tonumber(args[1]) then return end
local OnOff = (tobool(tonumber(args[1])) and "on") or "off"
FAdmin.Messages.ActionMessage(ply, player.GetAll(), ply:Nick() .. " turned logging " .. OnOff, "Logging has been turned " .. OnOff, "Turned logging " .. OnOff)
RunConsoleCommand("FAdmin_logging", args[1])
FAdmin.SaveSetting("FAdmin_logging", args[1])
return true, OnOff
end)
logging = GetConVar("FAdmin_logging")
end
function FAdmin.Log(text)
if not text or text == "" then return end
if not logging or not logging:GetBool() then return end
ServerLog("[FAdmin] " .. text .. "\n")
end
hook.Add("PlayerGiveSWEP", "FAdmin_Log", function(ply, class)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Gave themself a " .. (class or "Unknown"))
end)
hook.Add("PlayerSpawnedSENT", "FAdmin_Log", function(ply, ent)
if not IsValid(ply) or not ply:IsPlayer() or not IsValid(ent) then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (ent:GetClass() or "Unknown"))
end)
hook.Add("PlayerSpawnSWEP", "FAdmin_Log", function(ply, class)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (class or "Unknown"))
end)
hook.Add("PlayerSpawnedProp", "FAdmin_Log", function(ply, model, ent)
if not IsValid(ply) or not ply:IsPlayer() or not IsValid(ent) then return end
for _, v in ipairs(player.GetAll()) do
if v:IsAdmin() then
v:PrintMessage(HUD_PRINTCONSOLE, ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (model or "Unknown"))
end
end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (model or "Unknown"))
end)
hook.Add("PlayerSpawnedNPC", "FAdmin_Log", function(ply, ent)
if not IsValid(ply) or not ply:IsPlayer() or not IsValid(ent) then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (ent:GetClass() or "Unknown"))
end)
hook.Add("PlayerSpawnedVehicle", "FAdmin_Log", function(ply, ent)
if not IsValid(ply) or not ply:IsPlayer() or not IsValid(ent) then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (ent:GetClass() or "Unknown"))
end)
hook.Add("PlayerSpawnedEffect", "FAdmin_Log", function(ply, model, ent)
if not IsValid(ply) or not ply:IsPlayer() or not model then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (model or "Unknown"))
end)
hook.Add("PlayerSpawnedRagdoll", "FAdmin_Log", function(ply, model, ent)
if not IsValid(ply) or not ply:IsPlayer() or not IsValid(ent) then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned a " .. (model or "Unknown"))
end)
hook.Add("CanTool", "FAdmin_Log", function(ply, tr, toolclass)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Attempted to use tool " .. (toolclass or "Unknown"))
end)
hook.Add("PlayerLeaveVehicle", "FAdmin_Log", function(ply, vehicle)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") exited a " .. (IsValid(vehicle) and vehicle:GetClass() or "Unknown"))
end)
hook.Add("OnNPCKilled", "FAdmin_Log", function(NPC, Killer, Weapon)
if not IsValid(NPC) then return end
FAdmin.Log(NPC:GetClass() .. " was killed by " .. (IsValid(Killer) and (Killer:IsPlayer() and Killer:Nick() or Killer:GetClass()) or "Unknown") .. " with a " .. (IsValid(Weapon) and Weapon:GetClass() or "Unknown"))
end)
hook.Add("OnPlayerChangedTeam", "FAdmin_Log", function(ply, oldteam, newteam)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") changed from " .. team.GetName(oldteam) .. " to " .. team.GetName(newteam))
end)
hook.Add("WeaponEquip", "FAdmin_Log", function(weapon)
timer.Simple(0, function()
if not IsValid(weapon) then return end
local ply = weapon:GetOwner()
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Attempted to pick up a " .. weapon:GetClass())
end)
end)
hook.Add("PlayerDeath", "FAdmin_Log", function(ply, inflictor, Killer)
local Nick = IsValid(ply) and ply:Nick() or "N/A"
local SteamID = IsValid(ply) and ply:SteamID() or "N/A"
local KillerName = IsValid(Killer) and (Killer:IsPlayer() and Killer:Nick() or Killer:GetClass()) or "N/A"
local InflictorName = IsValid(inflictor) and inflictor:GetClass() or "N/A"
FAdmin.Log(Nick .. " (" .. SteamID .. ") Got killed by " .. KillerName .. " with a " .. InflictorName)
end)
hook.Add("PlayerSilentDeath", "FAdmin_Log", function(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Got killed silently")
end)
hook.Add("PlayerDisconnected", "FAdmin_Log", function(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Disconnected")
end)
hook.Add("PlayerInitialSpawn", "FAdmin_Log", function(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned for the first time")
end)
hook.Add("PlayerSpawn", "FAdmin_Log", function(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Spawned")
end)
hook.Add("PlayerSpray", "FAdmin_Log", function(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Sprayed his spray")
end)
hook.Add("PlayerEnteredVehicle", "FAdmin_Log", function(ply, vehicle)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Entered " .. (IsValid(vehicle) and vehicle:GetClass() or "Unknown"))
end)
hook.Add("EntityRemoved", "FAdmin_Log", function(ent)
if IsValid(ent) and ent:GetClass() == "prop_physics" then
FAdmin.Log(ent:GetClass() .. "(" .. (ent:GetModel() or "<no model>") .. ") Got removed")
end
end)
hook.Add("PlayerAuthed", "FAdmin_Log", function(ply, SteamID, _)
if not IsValid(ply) then return end
FAdmin.Log(ply:Nick() .. " (" .. (SteamID or "Unknown Steam ID") .. ") is Authed")
end)
hook.Add("PlayerNoClip", "FAdmin_Log", function(ply)
if not IsValid(ply) or not ply:IsPlayer() then return end
FAdmin.Log(ply:Nick() .. " (" .. ply:SteamID() .. ") Attempted to switch noclip")
end)
hook.Add("ShutDown", "FAdmin_Log", function()
FAdmin.shuttingDown = true
FAdmin.Log("Server succesfully shut down.")
end)

View File

@@ -0,0 +1,189 @@
local showChat = CreateClientConVar("FAdmin_ShowChatNotifications", 1, true, false)
local HUDNote_c = 0
local HUDNote_i = 1
local HUDNotes = {}
--Notify ripped off the Sandbox notify, changed to my likings
function FAdmin.Messages.AddMessage(MsgType, Message)
local tab = {}
tab.text = Message
tab.recv = SysTime()
tab.velx = 0
tab.vely = -5
surface.SetFont("GModNotify")
local w, _ = surface.GetTextSize(Message)
tab.x = ScrW() / 2 + w * 0.5 + (ScrW() / 20)
tab.y = ScrH()
tab.a = 255
local MsgTypeNames = {"ERROR", "NOTIFY", "QUESTION", "GOOD", "BAD"}
if not MsgTypeNames[MsgType] then return end
tab.col = FAdmin.Messages.MsgTypes[MsgTypeNames[MsgType]].COLOR
table.insert(HUDNotes, tab)
HUDNote_c = HUDNote_c + 1
HUDNote_i = HUDNote_i + 1
LocalPlayer():EmitSound("npc/turret_floor/click1.wav", 30, 100)
end
usermessage.Hook("FAdmin_SendMessage", function(u) FAdmin.Messages.AddMessage(u:ReadShort(), u:ReadString()) end)
local function DrawNotice(k, v, i)
local H = ScrH() / 1024
local x = v.x - 75 * H
local y = v.y - 27
surface.SetFont("GModNotify")
local w, h = surface.GetTextSize(v.text)
h = h + 16
local col = v.col
draw.RoundedBox(4, x - w - h + 24, y - 8, w + h - 16, h, col)
-- Draw Icon
surface.SetDrawColor(255, 255, 255, v.a)
draw.DrawNonParsedSimpleText(v.text, "GModNotify", x + 1, y + 1, Color(0, 0, 0, v.a * 0.8), TEXT_ALIGN_RIGHT)
draw.DrawNonParsedSimpleText(v.text, "GModNotify", x - 1, y - 1, Color(0, 0, 0, v.a * 0.5), TEXT_ALIGN_RIGHT)
draw.DrawNonParsedSimpleText(v.text, "GModNotify", x + 1, y - 1, Color(0, 0, 0, v.a * 0.6), TEXT_ALIGN_RIGHT)
draw.DrawNonParsedSimpleText(v.text, "GModNotify", x - 1, y + 1, Color(0, 0, 0, v.a * 0.6), TEXT_ALIGN_RIGHT)
draw.DrawNonParsedSimpleText(v.text, "GModNotify", x, y, Color(255, 255, 255, v.a), TEXT_ALIGN_RIGHT)
local ideal_y = ScrH() - (HUDNote_c - i) * h
local ideal_x = ScrW() / 2 + w * 0.5 + (ScrW() / 20)
local timeleft = 6 - (SysTime() - v.recv)
-- Cartoon style about to go thing
if (timeleft < 0.8) then
ideal_x = ScrW() / 2 + w * 0.5 + 200
end
-- Gone!
if (timeleft < 0.5) then
ideal_y = ScrH() + 50
end
local spd = RealFrameTime() * 15
v.y = v.y + v.vely * spd
v.x = v.x + v.velx * spd
local dist = ideal_y - v.y
v.vely = v.vely + dist * spd * 1
if (math.abs(dist) < 2 and math.abs(v.vely) < 0.1) then
v.vely = 0
end
dist = ideal_x - v.x
v.velx = v.velx + dist * spd * 1
if math.abs(dist) < 2 and math.abs(v.velx) < 0.1 then
v.velx = 0
end
-- Friction.. kind of FPS independant.
v.velx = v.velx * (0.95 - RealFrameTime() * 8)
v.vely = v.vely * (0.95 - RealFrameTime() * 8)
end
local function HUDPaint()
if not HUDNotes then return end
local i = 0
for k, v in ipairs(HUDNotes) do
if v ~= 0 then
i = i + 1
DrawNotice(k, v, i)
end
end
for k, v in ipairs(HUDNotes) do
if v ~= 0 and v.recv + 6 < SysTime() then
HUDNotes[k] = 0
HUDNote_c = HUDNote_c - 1
if HUDNote_c == 0 then
HUDNotes = {}
end
end
end
end
hook.Add("HUDPaint", "FAdmin_MessagePaint", HUDPaint)
local function ConsoleMessage(um)
MsgC(Color(255, 0, 0, 255), "(FAdmin) ", Color(200, 0, 200, 255), um:ReadString() .. "\n")
end
usermessage.Hook("FAdmin_ConsoleMessage", ConsoleMessage)
local red = Color(255, 0, 0)
local white = Color(190, 190, 190)
local brown = Color(102, 51, 0)
local blue = Color(102, 0, 255)
-- Inserts the instigator into a notification message
local function insertInstigator(res, instigator, _)
table.insert(res, brown)
table.insert(res, FAdmin.PlayerName(instigator))
end
-- Inserts the targets into the notification message
local function insertTargets(res, _, targets)
table.insert(res, blue)
table.insert(res, FAdmin.TargetsToString(targets))
end
local modMessage = {
instigator = insertInstigator,
you = function(res) table.insert(res, brown) table.insert(res, "you") end,
targets = insertTargets,
}
local function showNotification(notification, instigator, targets, extraInfo)
local res = {red, "[", white, "FAdmin", red, "] "}
for _, text in pairs(notification.message) do
if modMessage[text] then modMessage[text](res, instigator, targets) continue end
if string.sub(text, 1, 10) == "extraInfo." then
local id = tonumber(string.sub(text, 11))
table.insert(res, notification.extraInfoColors and notification.extraInfoColors[id] or white)
table.insert(res, extraInfo[id])
continue
end
table.insert(res, white)
table.insert(res, text)
end
if showChat:GetBool() then
chat.AddText(unpack(res))
else
local msgTbl = {}
for i = 8, #res, 2 do table.insert(msgTbl, res[i]) end
FAdmin.Messages.AddMessage(FAdmin.Messages.MsgTypesByName[notification.msgType], table.concat(msgTbl, ""))
MsgC(unpack(res))
Msg("\n")
end
end
local function receiveNotification()
local id = net.ReadUInt(16)
local notification = FAdmin.Notifications[id]
local instigator = net.ReadEntity()
local targets = {}
if notification.hasTarget then
local targetCount = net.ReadUInt(8)
for i = 1, targetCount do
table.insert(targets, net.ReadEntity())
end
end
local extraInfo = notification.readExtraInfo and notification.readExtraInfo()
showNotification(notification, instigator, targets, extraInfo)
end
net.Receive("FAdmin_Notification", receiveNotification)

View File

@@ -0,0 +1,135 @@
FAdmin.Messages = {}
FAdmin.Messages.MsgTypes = {
ERROR = {TEXTURE = "icon16/exclamation.png", COLOR = Color(255,180,0,80)},
NOTIFY = {TEXTURE = "vgui/notices/error", COLOR = Color(255,255,0,80)},
QUESTION = {TEXTURE = "vgui/notices/hint", COLOR = Color(0,0,255,80)},
GOOD = {TEXTURE = "icon16/tick.png", COLOR = Color(0,255,0,80)},
BAD = {TEXTURE = "icon16/cross.png", COLOR = Color(255,0,0,80)}
}
FAdmin.Messages.MsgTypesByName = {
ERROR = 1,
NOTIFY = 2,
QUESTION = 3,
GOOD = 4,
BAD = 5,
}
function FAdmin.PlayerName(ply)
if CLIENT and ply == LocalPlayer() then return "you" end
if isstring(ply) then return ply end
return isentity(ply) and (ply:EntIndex() == 0 and "Console" or ply:Nick()) or "unknown"
end
function FAdmin.TargetsToString(targets)
if not istable(targets) then
return FAdmin.PlayerName(targets)
end
local targetCount = #targets
if targetCount == 0 then
return "no one"
end
if targetCount == player.GetCount() and targetCount ~= 1 then
return "everyone"
end
targets = table.Copy(targets)
local names = fn.Map(FAdmin.PlayerName, targets)
if #names == 1 then
return names[1]
end
return table.concat(names, ", ", 1, #names - 1) .. " and " .. names[#names]
end
FAdmin.Notifications = {}
local validNotification = tc.checkTable{
-- A name to identify the notification by
name =
tc.addHint(
isstring,
"The name must be a string!"
),
-- Whether the notification applies to some kind of target
hasTarget =
tc.addHint(
tc.optional(isbool),
"hasTarget must either be true, false or nil!"
),
-- Who receives the notification. Can be either one of the list or a function that returns a table of players
receivers =
tc.addHint(
fn.FOr{tc.client, isfunction, tc.oneOf{"everyone", "admins", "superadmins", "self", "targets", "involved", "involved+admins", "involved+superadmins"}},
"receivers must either be a function returning a table of players or one of 'admins', 'superadmins', 'everyone', 'self', 'targets', 'involved', 'involved+admins', 'involved+superadmins'"
),
-- A table containing the message in parts. There are special strings
message =
tc.addHint(
tc.tableOf(isstring),
"The message field must be a table of strings! with special strings 'targets', 'you', 'instigator', 'extraInfo.#', with # a number."
),
-- The message type when chat notifications are disabled. NOTIFY by default
msgType =
tc.default(
"NOTIFY",
tc.addHint(
tc.oneOf{"ERROR", "NOTIFY", "QUESTION", "GOOD", "BAD"}, "msgType must be one of 'ERROR', 'NOTIFY', 'QUESTION', 'GOOD', 'BAD'"
)
),
-- A function that writes extra data in the net message
writeExtraInfo =
tc.addHint(
tc.optional(isfunction),
"writeExtraInfo must be a function"
),
-- A function that reads the written data, formats it and puts it in a table
readExtraInfo =
tc.addHint(
tc.optional(isfunction),
"writeExtraInfo must be a function"
),
-- When using extra information, this table contains the colours of the extraInfo messages
extraInfoColors =
tc.addHint(
tc.optional(tc.tableOf(tc.iscolor)),
"extraInfoColors must be a table of colours!"
),
-- Whether the notification is to be logged to console
logging =
tc.default(true,
tc.addHint(
isbool,
"logging must be a boolean!"
)
),
}
FAdmin.NotificationNames = {}
function FAdmin.Messages.RegisterNotification(tbl)
local correct, err = validNotification(tbl)
if not correct then
error(string.format("Incorrect notification format for notification '%s'!\n\n%s", istable(tbl) and tbl.name or "unknown", err), 2)
end
local key = table.insert(FAdmin.Notifications, tbl)
FAdmin.NotificationNames[tbl.name] = key
return key
end

View File

@@ -0,0 +1,137 @@
util.AddNetworkString("FAdmin_Notification")
function FAdmin.Messages.SendMessage(ply, MsgType, text)
if ply:EntIndex() == 0 then
ServerLog("FAdmin: " .. text .. "\n")
print("FAdmin: " .. text)
return
end
umsg.Start("FAdmin_SendMessage", ply)
umsg.Short(MsgType)
umsg.String(text)
umsg.End()
ply:PrintMessage(HUD_PRINTCONSOLE, text)
end
function FAdmin.Messages.SendMessageAll(text, MsgType)
FAdmin.Log("FAdmin message to everyone: " .. text)
umsg.Start("FAdmin_SendMessage")
umsg.Short(MsgType)
umsg.String(text)
umsg.End()
for _, ply in ipairs(player.GetAll()) do
ply:PrintMessage(HUD_PRINTCONSOLE, text)
end
end
function FAdmin.Messages.ConsoleNotify(ply, message)
umsg.Start("FAdmin_ConsoleMessage", ply)
umsg.String(message)
umsg.End()
end
function FAdmin.Messages.ActionMessage(ply, target, messageToPly, MessageToTarget, LogMSG)
if not target then return end
local Targets = (target.IsPlayer and target:IsPlayer() and target:Nick()) or ""
local plyNick = IsValid(ply) and ply:IsPlayer() and ply:Nick() or "Console"
local plySteamID = IsValid(ply) and ply:IsPlayer() and ply:SteamID() or "Console"
local bad = false
if ply ~= target then
if istable(target) then
if table.IsEmpty(target) then Targets = "no one" bad = true end
for k, v in ipairs(target) do
local suffix = ((k == #target-1) and " and ") or (k ~= #target and ", ") or ""
local Name = (v == ply and "yourself") or v:Nick()
if v ~= ply then FAdmin.Messages.SendMessage(v, 2, string.format(MessageToTarget, plyNick)) end
Targets = Targets .. Name .. suffix
end
else
FAdmin.Messages.SendMessage(target, 2, string.format(MessageToTarget, plyNick))
end
FAdmin.Messages.SendMessage(ply, bad and 1 or 4, string.format(messageToPly, Targets))
else
FAdmin.Messages.SendMessage(ply, bad and 1 or 4, string.format(messageToPly, "yourself"))
end
local action = plyNick .. " (" .. plySteamID .. ") " .. string.format(LogMSG, Targets:gsub("yourself", "themselves"))
FAdmin.Log("FAdmin Action: " .. action)
local haspriv = fn.Partial(fn.Flip(FAdmin.Access.PlayerHasPrivilege), "SeeAdmins")
local plys = fn.Filter(haspriv, player.GetAll())
if table.IsEmpty(plys) then return end
FAdmin.Messages.ConsoleNotify(plys, action)
end
local function logNotification(notification, instigator, targets, extraInfo)
local msgs = table.Copy(notification.message)
local function replace(val)
if val == "instigator" then return FAdmin.PlayerName(instigator) end
if val == "targets" then return FAdmin.TargetsToString(targets) end
if string.sub(val, 1, 10) == "extraInfo." then return tostring(extraInfo[tonumber(string.sub(val, 11))]) end
return val
end
fn.Map(replace, msgs)
FAdmin.Log(table.concat(msgs))
end
local receiversToPlayers -- allows usage of variable inside
receiversToPlayers = {
everyone = player.GetAll,
admins = function() return table.ClearKeys(fn.Filter(tc.player.IsAdmin, player.GetAll())) end,
superadmins = function() return table.ClearKeys(fn.Filter(tc.player.IsSuperAdmin, player.GetAll())) end,
self = fn.Id,
targets = function(_, t) return t end,
involved = function(i, t) local res = table.Copy(istable(t) and t or {t}) table.insert(res, i) return res end,
["involved+admins"] = function(i, t) return table.Add(receiversToPlayers.admins(i, t), receiversToPlayers.involved(i, t)) end,
["involved+superadmins"] = function(i, t) return table.Add(receiversToPlayers.superadmins(i, t), receiversToPlayers.involved(i, t)) end,
}
function FAdmin.Messages.FireNotification(name, instigator, targets, extraInfo)
local notId = FAdmin.NotificationNames[name]
if not notId then
error(string.format("Notification '%s' does not exist!", name), 2)
end
local notification = FAdmin.Notifications[notId]
local receivers = receiversToPlayers[notification.receivers]
receivers = receivers and receivers(instigator, targets) or notification.receivers(instigator, targets)
local targetCount = istable(targets) and #targets or not IsValid(targets) and 0 or 1
net.Start("FAdmin_Notification")
net.WriteUInt(notId, 16)
net.WriteEntity(instigator)
if notification.hasTarget then
net.WriteUInt(targetCount, 8)
if istable(targets) then
for _, t in ipairs(targets) do
net.WriteEntity(t)
end
else
net.WriteEntity(targets)
end
end
if notification.writeExtraInfo then notification.writeExtraInfo(extraInfo) end
net.Send(receivers)
if notification.logging then
logNotification(notification, instigator, targets, extraInfo)
end
end

View File

@@ -0,0 +1,85 @@
local MOTDPage = CreateConVar("_FAdmin_MOTDPage", "default", {FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE})
if CLIENT then -- I can't be bothered to make a cl_init when there's a shared file with just one line in it.
FAdmin.StartHooks["MOTD"] = function()
FAdmin.ScoreBoard.Server:AddServerAction("Place MOTD", "fadmin/icons/motd", Color(155, 0, 0, 255), function(ply) return ply:IsSuperAdmin() end, function()
RunConsoleCommand("_FAdmin", "CreateMOTD")
end)
FAdmin.ScoreBoard.Server:AddServerSetting("Set MOTD page", "fadmin/icons/motd", Color(0, 0, 155, 255), function(ply) return ply:IsSuperAdmin() end, function()
local Window = vgui.Create("DFrame")
Window:SetTitle("Set MOTD page")
Window:SetDraggable(false)
Window:ShowCloseButton(false)
Window:SetBackgroundBlur(true)
Window:SetDrawOnTop(true)
local InnerPanel = vgui.Create("DPanel", Window)
InnerPanel:SetPaintBackground(false) -- clear background
local Text = vgui.Create("DLabel", InnerPanel)
Text:SetText("Set the MOTD page. Click default to reset the MOTD to default.")
Text:SizeToContents()
Text:SetContentAlignment(5)
Text:SetTextColor(color_white)
local TextEntry = vgui.Create("DTextEntry", InnerPanel)
TextEntry:SetText(MOTDPage:GetString())
TextEntry.OnEnter = function() Window:Close() RunConsoleCommand("_FAdmin", "motdpage", TextEntry:GetValue()) end
function TextEntry:OnFocusChanged(changed)
self:RequestFocus()
self:SelectAllText(true)
end
local ButtonPanel = vgui.Create("DPanel", Window)
ButtonPanel:SetPaintBackground(false) -- clear background
ButtonPanel:SetTall(30)
local Button = vgui.Create("DButton", ButtonPanel)
Button:SetText("OK")
Button:SizeToContents()
Button:SetTall(20)
Button:SetWide(Button:GetWide() + 20)
Button:SetPos(5, 5)
Button.DoClick = function()
Window:Close()
RunConsoleCommand("_FAdmin", "motdpage", TextEntry:GetValue())
end
local ButtonDefault = vgui.Create("DButton", ButtonPanel)
ButtonDefault:SetText("Default")
ButtonDefault:SizeToContents()
ButtonDefault:SetTall(20)
ButtonDefault:SetWide(Button:GetWide() + 20)
ButtonDefault:SetPos(5, 5)
ButtonDefault.DoClick = function() Window:Close() RunConsoleCommand("_FAdmin", "motdpage", "default") end
ButtonDefault:MoveRightOf(Button, 5)
local ButtonCancel = vgui.Create("DButton", ButtonPanel)
ButtonCancel:SetText("Cancel")
ButtonCancel:SizeToContents()
ButtonCancel:SetTall(20)
ButtonCancel:SetWide(Button:GetWide() + 20)
ButtonCancel:SetPos(5, 5)
ButtonCancel.DoClick = function() Window:Close() end
ButtonCancel:MoveRightOf(ButtonDefault, 5)
ButtonPanel:SetWide(Button:GetWide() + 5 + ButtonCancel:GetWide() + 10 + ButtonDefault:GetWide() + 5)
local w, h = Text:GetSize()
w = math.max(w, 400)
Window:SetSize(w + 50, h + 25 + 75 + 10)
Window:Center()
InnerPanel:StretchToParent(5, 25, 5, 45)
Text:StretchToParent(5, 5, 5, 35)
TextEntry:StretchToParent(5, nil, 5, nil)
TextEntry:AlignBottom(5)
TextEntry:RequestFocus()
ButtonPanel:CenterHorizontal()
ButtonPanel:AlignBottom(8)
Window:MakePopup()
Window:DoModal()
end)
end
end

View File

@@ -0,0 +1,91 @@
FAdmin.MOTD = {}
local MOTDPage
sql.Query([[CREATE TABLE IF NOT EXISTS FADMIN_MOTD(
'map' TEXT NOT NULL PRIMARY KEY,
x INTEGER NOT NULL,
y INTEGER NOT NULL,
z INTEGER NOT NULL,
pitch INTEGER NOT NULL,
yaw INTEGER NOT NULL,
roll INTEGER NOT NULL
);]])
local MOTD = sql.Query("SELECT * FROM FADMIN_MOTD WHERE LOWER(map) = " .. MySQLite.SQLStr(string.lower(game.GetMap())) .. ";")
hook.Add("InitPostEntity", "PlaceMOTD", function()
if not MOTD or (not MOTD[1] and not MOTD["1"]) then return end
MOTD = MOTD[1] or MOTD["1"]
local ent = ents.Create("fadmin_motd")
ent:SetPos(Vector(MOTD.x, MOTD.y, MOTD.z))
ent:SetAngles(Angle(MOTD.pitch % 360, MOTD.yaw % 360, MOTD.roll % 360))
ent:Spawn()
ent:Activate()
if file.Exists("FAdmin/CurMOTDPage.txt", "DATA") and file.Read("FAdmin/CurMOTDPage.txt", "DATA") ~= "" then
game.ConsoleCommand("_FAdmin_MOTDPage \"" .. file.Read("FAdmin/CurMOTDPage.txt", "DATA") .. "\"\n")
end
end)
function FAdmin.MOTD.SaveMOTD(ent, ply)
local pos = ent:GetPos()
local ang = ent:GetAngles()
local map, x, y, z, pitch, yaw, roll =
string.lower(game.GetMap()),
pos.x, pos.y, pos.z,
ang.p, ang.y, ang.r
if MOTD then
sql.Query([[UPDATE FADMIN_MOTD SET ]]
.. "x = " .. MySQLite.SQLStr(x) .. ", "
.. "y = " .. MySQLite.SQLStr(y) .. ", "
.. "z = " .. MySQLite.SQLStr(z) .. ", "
.. "pitch = " .. MySQLite.SQLStr(pitch) .. ", "
.. "yaw = " .. MySQLite.SQLStr(yaw) .. ", "
.. "roll = " .. MySQLite.SQLStr(roll)
.. " WHERE map = " .. MySQLite.SQLStr(map) .. ";")
else
sql.Query([[INSERT INTO FADMIN_MOTD VALUES(]]
.. MySQLite.SQLStr(map) .. ", "
.. MySQLite.SQLStr(x) .. ", "
.. MySQLite.SQLStr(y) .. ", "
.. MySQLite.SQLStr(z) .. ", "
.. MySQLite.SQLStr(pitch) .. ", "
.. MySQLite.SQLStr(yaw) .. ", "
.. MySQLite.SQLStr(roll)
.. ");")
end
FAdmin.Messages.SendMessage(ply, 4, "MOTD position saved!")
end
function FAdmin.MOTD.RemoveMOTD(ent, ply)
sql.Query("DELETE FROM FADMIN_MOTD WHERE map = " .. MySQLite.SQLStr(string.lower(game.GetMap())) .. ";")
FAdmin.Messages.SendMessage(ply, 4, "MOTD removed!")
end
function FAdmin.MOTD.SetMOTDPage(ply, cmd, args)
if not args[1] then
FAdmin.Messages.SendMessage(ply, 4, "MOTD is set to: " .. MOTDPage:GetString())
return false
end
if ply:EntIndex() ~= 0 and (not ply.IsSuperAdmin or not ply:IsSuperAdmin()) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
RunConsoleCommand("_FAdmin_MOTDPage", args[1])
file.Write("FAdmin/CurMOTDPage.txt", args[1])
return true, args[1]
end
local function CreateMOTD(ply)
if IsValid(ply) and not ply:IsSuperAdmin() then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local MOTDEnt = ents.Create("fadmin_motd")
MOTDEnt:SpawnFunction(ply, ply:GetEyeTrace())
return true, MOTDEnt
end
FAdmin.StartHooks["MOTD"] = function()
MOTDPage = GetConVar("_FAdmin_MOTDPage")
FAdmin.Commands.AddCommand("MOTDPage", FAdmin.MOTD.SetMOTDPage)
FAdmin.Commands.AddCommand("CreateMOTD", CreateMOTD)
end

View File

@@ -0,0 +1,21 @@
local AdminsCanPickUpPlayers = CreateConVar("AdminsCanPickUpPlayers", 1, {FCVAR_REPLICATED, FCVAR_SERVER_CAN_EXECUTE})
local PlayersCanPickUpPlayers = CreateConVar("PlayersCanPickUpPlayers", 0, {FCVAR_REPLICATED, FCVAR_SERVER_CAN_EXECUTE})
FAdmin.StartHooks["PickUpPlayers"] = function()
FAdmin.Access.AddPrivilege("PickUpPlayers", 2)
FAdmin.ScoreBoard.Server:AddPlayerAction(function() return (AdminsCanPickUpPlayers:GetBool() and "Disable" or "Enable") .. " Admin>Player pickup" end,
function() return "fadmin/icons/pickup", AdminsCanPickUpPlayers:GetBool() and "fadmin/icons/disable" end, Color(0, 155, 0, 255), function(ply) return ply:IsSuperAdmin() end, function(button)
button:SetImage2((not AdminsCanPickUpPlayers:GetBool() and "fadmin/icons/disable") or "null")
button:SetText((not AdminsCanPickUpPlayers:GetBool() and "Disable" or "Enable") .. " Admin>Player pickup")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_FAdmin", "AdminsCanPickUpPlayers", AdminsCanPickUpPlayers:GetBool() and "0" or "1")
end)
FAdmin.ScoreBoard.Server:AddPlayerAction(function() return (PlayersCanPickUpPlayers:GetBool() and "Disable" or "Enable") .. " Player>Player pickup" end,
function() return "fadmin/icons/pickup", PlayersCanPickUpPlayers:GetBool() and "fadmin/icons/disable" end, Color(0, 155, 0, 255), function(ply) return ply:IsSuperAdmin() end, function(button)
button:SetImage2((not PlayersCanPickUpPlayers:GetBool() and "fadmin/icons/disable") or "null")
button:SetText((not PlayersCanPickUpPlayers:GetBool() and "Disable" or "Enable") .. " Player>Player pickup")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_FAdmin", "PlayersCanPickUpPlayers", PlayersCanPickUpPlayers:GetBool() and "0" or "1")
end)
end

View File

@@ -0,0 +1,58 @@
local AdminsCanPickUpPlayers = CreateConVar("AdminsCanPickUpPlayers", 1, {FCVAR_REPLICATED, FCVAR_SERVER_CAN_EXECUTE})
local PlayersCanPickUpPlayers = CreateConVar("PlayersCanPickUpPlayers", 0, {FCVAR_REPLICATED, FCVAR_SERVER_CAN_EXECUTE})
hook.Add("PhysgunPickup", "FAdmin_PickUpPlayers", function(ply, ent)
if not IsValid(ent) or not ent:IsPlayer() then return end
if PlayersCanPickUpPlayers:GetBool() or AdminsCanPickUpPlayers:GetBool() and
FAdmin.Access.PlayerHasPrivilege(ply, "PickUpPlayers", ent) and tobool(ply:GetInfo("cl_pickupplayers")) then
ent:SetMoveType(MOVETYPE_NONE)
ent:Freeze(true)
return true
end
end)
hook.Add("PhysgunDrop", "FAdmin_PickUpPlayers", function(ply, ent)
if IsValid(ent) and ent:IsPlayer() then
ent:SetMoveType(MOVETYPE_WALK)
ent:Freeze(false)
end
end)
local function ChangeAdmin(ply, cmd, args)
if not ply:IsSuperAdmin() then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local Value = tonumber(args[1])
if Value ~= 1 and Value ~= 0 then return false end
RunConsoleCommand("AdminsCanPickUpPlayers", Value)
FAdmin.SaveSetting("AdminsCanPickUpPlayers", Value)
local OnOff = (tobool(Value) and "on") or "off"
FAdmin.Messages.ActionMessage(ply, player.GetAll(), ply:Nick() .. " turned Admin>Player pickup " .. OnOff, "Admin>Player pickup has been turned " .. OnOff, "Turned Admin>Player pickup " .. OnOff)
return true, OnOff
end
local function ChangeUser(ply, cmd, args)
if not ply:IsSuperAdmin() then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local Value = tonumber(args[1])
if Value ~= 1 and Value ~= 0 then return false end
RunConsoleCommand("PlayersCanPickUpPlayers", Value)
FAdmin.SaveSetting("PlayersCanPickUpPlayers", Value)
local OnOff = (tobool(Value) and "on") or "off"
FAdmin.Messages.ActionMessage(ply, player.GetAll(), ply:Nick() .. " turned Player>Player pickup " .. OnOff, "Player>Player pickup has been turned " .. OnOff, "Turned Player>Player pickup " .. OnOff)
return true, OnOff
end
FAdmin.StartHooks["PickUpPlayers"] = function()
FAdmin.Access.AddPrivilege("PickUpPlayers", 2)
FAdmin.Commands.AddCommand("AdminsCanPickUpPlayers", ChangeAdmin)
FAdmin.Commands.AddCommand("PlayersCanPickUpPlayers", ChangeUser)
end

View File

@@ -0,0 +1,37 @@
FAdmin.StartHooks["zzSetTeam"] = function()
FAdmin.Messages.RegisterNotification{
name = "setteam",
hasTarget = true,
message = {"instigator", " set the team of ", "targets", " to ", "extraInfo.1"},
readExtraInfo = function()
return {team.GetName(net.ReadUInt(16))}
end,
extraInfoColors = {Color(255, 102, 0)}
}
FAdmin.Access.AddPrivilege("SetTeam", 2)
FAdmin.Commands.AddCommand("SetTeam", nil, "<Player>", "<Team>")
FAdmin.ScoreBoard.Player:AddActionButton("Set team", "fadmin/icons/changeteam", Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "SetTeam", ply) end, function(ply, button)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Teams:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for k, v in SortedPairsByMemberValue(team.GetAllTeams(), "Name") do
local uid = ply:UserID()
menu:AddOption(v.Name, function() RunConsoleCommand("_FAdmin", "setteam", uid, k) end)
end
menu:Open()
end)
end

View File

@@ -0,0 +1,67 @@
local function checkDarkRP(ply, target, t)
if not DarkRP then return true end
local TEAM = RPExtraTeams[t]
if not TEAM then return true end
if TEAM.customCheck then
local ret = TEAM.customCheck(target)
if ret ~= nil and not (ply:IsAdmin() and GAMEMODE.Config.adminBypassJobRestrictions) then return ret end
end
local hookValue = hook.Call("playerCanChangeTeam", nil, target, t, true)
if hookValue == false then return false end
local a = TEAM.admin
if a > 0 and not target:IsAdmin()
or a > 1 and not target:IsSuperAdmin()
then return false end
return true
end
local function SetTeam(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local targetsSet = {}
for k, v in pairs(team.GetAllTeams()) do
if k == tonumber(args[2]) or string.lower(v.Name) == string.lower(args[2] or "") then
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "SetTeam", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local setTeam = target.changeTeam or target.SetTeam -- DarkRP compatibility
if IsValid(target) and checkDarkRP(ply, target, k) then
setTeam(target, k, true)
table.insert(targetsSet, target)
end
end
if not table.IsEmpty(targetsSet) then
FAdmin.Messages.FireNotification("setteam", ply, targetsSet, {k})
else
FAdmin.Messages.SendMessage(ply, 1, "Could not set team")
end
break
end
end
return true, targets
end
FAdmin.StartHooks["zzSetTeam"] = function()
FAdmin.Messages.RegisterNotification{
name = "setteam",
hasTarget = true,
receivers = "everyone",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
message = {"instigator", " set the team of ", "targets", " to ", "extraInfo.1"},
}
FAdmin.Commands.AddCommand("SetTeam", SetTeam)
FAdmin.Access.AddPrivilege("SetTeam", 2)
end

View File

@@ -0,0 +1,47 @@
FAdmin.StartHooks["Chatmute"] = function()
FAdmin.Messages.RegisterNotification{
name = "chatmute",
hasTarget = true,
message = {"instigator", " chat muted ", "targets", " ", "extraInfo.1"},
readExtraInfo = function()
local time = net.ReadUInt(16)
return {time == 0 and FAdmin.PlayerActions.commonTimes[time] or string.format("for %s", FAdmin.PlayerActions.commonTimes[time] or (time .. " seconds"))}
end
}
FAdmin.Messages.RegisterNotification{
name = "chatunmute",
hasTarget = true,
message = {"instigator", " chat unmuted ", "targets"},
}
FAdmin.Access.AddPrivilege("Chatmute", 2)
FAdmin.Commands.AddCommand("Chatmute", nil, "<Player>")
FAdmin.Commands.AddCommand("UnChatmute", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("FAdmin_chatmuted") then return "Unmute chat" end
return "Mute chat"
end, function(ply)
if ply:FAdmin_GetGlobal("FAdmin_chatmuted") then return "fadmin/icons/chatmute" end
return "fadmin/icons/chatmute", "fadmin/icons/disable"
end, Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Chatmute", ply) end, function(ply, button)
if not ply:FAdmin_GetGlobal("FAdmin_chatmuted") then
FAdmin.PlayerActions.addTimeMenu(function(secs)
RunConsoleCommand("_FAdmin", "chatmute", ply:UserID(), secs)
button:SetImage2("null")
button:SetText("Unmute chat")
button:GetParent():InvalidateLayout()
end)
else
RunConsoleCommand("_FAdmin", "UnChatmute", ply:UserID())
end
button:SetImage2("fadmin/icons/disable")
button:SetText("Mute chat")
button:GetParent():InvalidateLayout()
end)
end

View File

@@ -0,0 +1,75 @@
local function MuteChat(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1]) or {}
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local time = tonumber(args[2] or 0)
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Chatmute", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and not target:FAdmin_GetGlobal("FAdmin_chatmuted") then
target:FAdmin_SetGlobal("FAdmin_chatmuted", true)
if time == 0 then continue end
timer.Simple(time, function()
if not IsValid(target) or not target:FAdmin_GetGlobal("FAdmin_chatmuted") then return false end
target:FAdmin_SetGlobal("FAdmin_chatmuted", false)
end)
end
end
FAdmin.Messages.FireNotification("chatmute", ply, targets, {time})
return true, targets, time
end
local function UnMuteChat(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Chatmute", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and target:FAdmin_GetGlobal("FAdmin_chatmuted") then
target:FAdmin_SetGlobal("FAdmin_chatmuted", false)
end
end
FAdmin.Messages.FireNotification("chatunmute", ply, targets)
return true, targets
end
FAdmin.StartHooks["Chatmute"] = function()
FAdmin.Messages.RegisterNotification{
name = "chatmute",
hasTarget = true,
receivers = "involved+admins",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
message = {"instigator", " chat muted ", "targets", " ", "extraInfo.1"},
}
FAdmin.Messages.RegisterNotification{
name = "chatunmute",
hasTarget = true,
receivers = "involved+admins",
message = {"instigator", " chat unmuted ", "targets"},
}
FAdmin.Commands.AddCommand("Chatmute", MuteChat)
FAdmin.Commands.AddCommand("UnChatmute", UnMuteChat)
FAdmin.Access.AddPrivilege("Chatmute", 2)
end
hook.Add("PlayerSay", "FAdmin_Chatmute", function(ply, text, Team, dead)
if ply:FAdmin_GetGlobal("FAdmin_chatmuted") then return "" end
end)

View File

@@ -0,0 +1,26 @@
FAdmin.StartHooks["zz_Cloak"] = function()
FAdmin.Access.AddPrivilege("Cloak", 2)
FAdmin.Commands.AddCommand("Cloak", nil, "<Player>")
FAdmin.Commands.AddCommand("Uncloak", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("FAdmin_cloaked") then return "Uncloak" end
return "Cloak"
end, function(ply)
if ply:FAdmin_GetGlobal("FAdmin_cloaked") then return "fadmin/icons/cloak", "fadmin/icons/disable" end
return "fadmin/icons/cloak"
end, Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Cloak", ply) end, function(ply, button)
if not ply:FAdmin_GetGlobal("FAdmin_cloaked") then
RunConsoleCommand("_FAdmin", "Cloak", ply:UserID())
else
RunConsoleCommand("_FAdmin", "Uncloak", ply:UserID())
end
if not ply:FAdmin_GetGlobal("FAdmin_cloaked") then button:SetImage2("fadmin/icons/disable") button:SetText("Uncloak") button:GetParent():InvalidateLayout() return end
button:SetImage2("null")
button:SetText("Cloak")
button:GetParent():InvalidateLayout()
end)
end

View File

@@ -0,0 +1,89 @@
local CloakThink
local function Cloak(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1]) or {ply}
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Cloak", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and not target:FAdmin_GetGlobal("FAdmin_cloaked") then
target:FAdmin_SetGlobal("FAdmin_cloaked", true)
target:SetNoDraw(true)
for _, v in ipairs(target:GetWeapons()) do
v:SetNoDraw(true)
end
for _, v in ipairs(ents.FindByClass("physgun_beam")) do
if v:GetParent() == target then
v:SetNoDraw(true)
end
end
hook.Add("Think", "FAdmin_Cloak", CloakThink)
end
end
FAdmin.Messages.ActionMessage(ply, targets, "You have cloaked %s", "You were cloaked by %s", "Cloaked %s")
return true, targets
end
local function UnCloak(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1]) or {ply}
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Cloak", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and target:FAdmin_GetGlobal("FAdmin_cloaked") then
target:FAdmin_SetGlobal("FAdmin_cloaked", false)
target:SetNoDraw(false)
for _, v in ipairs(target:GetWeapons()) do
v:SetNoDraw(false)
end
for _, v in ipairs(ents.FindByClass("physgun_beam")) do
if v:GetParent() == target then
v:SetNoDraw(false)
end
end
target.FAdmin_CloakWeapon = nil
local RemoveThink = true
for _, v in ipairs(player.GetAll()) do
if v:FAdmin_GetGlobal("FAdmin_cloaked") then
RemoveThink = false
break
end
end
if RemoveThink then hook.Remove("Think", "FAdmin_Cloak") end
end
end
FAdmin.Messages.ActionMessage(ply, targets, "You have uncloaked %s", "You were uncloaked by %s", "Uncloaked %s")
return true, targets
end
FAdmin.StartHooks["Cloak"] = function()
FAdmin.Commands.AddCommand("Cloak", Cloak)
FAdmin.Commands.AddCommand("Uncloak", UnCloak)
FAdmin.Access.AddPrivilege("Cloak", 2)
end
function CloakThink()
for _, v in ipairs(player.GetAll()) do
local ActiveWeapon = v:GetActiveWeapon()
if v:FAdmin_GetGlobal("FAdmin_cloaked") and ActiveWeapon:IsValid() and ActiveWeapon ~= v.FAdmin_CloakWeapon then
v.FAdmin_CloakWeapon = ActiveWeapon
ActiveWeapon:SetNoDraw(true)
if ActiveWeapon:GetClass() == "weapon_physgun" then
for a,b in ipairs(ents.FindByClass("physgun_beam")) do
if b:GetParent() == v then
b:SetNoDraw(true)
end
end
end
end
end
end

View File

@@ -0,0 +1,48 @@
FAdmin.StartHooks["Freeze"] = function()
FAdmin.Messages.RegisterNotification{
name = "freeze",
hasTarget = true,
message = {"instigator", " froze ", "targets", " ", "extraInfo.1"},
readExtraInfo = function()
local time = net.ReadUInt(16)
return {time == 0 and FAdmin.PlayerActions.commonTimes[time] or string.format("for %s", FAdmin.PlayerActions.commonTimes[time] or (time .. " seconds"))}
end
}
FAdmin.Messages.RegisterNotification{
name = "unfreeze",
hasTarget = true,
message = {"instigator", " unfroze ", "targets"},
}
FAdmin.Access.AddPrivilege("Freeze", 2)
FAdmin.Commands.AddCommand("freeze", nil, "<Player>")
FAdmin.Commands.AddCommand("unfreeze", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("FAdmin_frozen") then return "Unfreeze" end
return "Freeze"
end, function(ply)
if ply:FAdmin_GetGlobal("FAdmin_frozen") then return "fadmin/icons/freeze", "fadmin/icons/disable" end
return "fadmin/icons/freeze"
end, Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Freeze", ply) end, function(ply, button)
if not ply:FAdmin_GetGlobal("FAdmin_frozen") then
FAdmin.PlayerActions.addTimeMenu(function(secs)
RunConsoleCommand("_FAdmin", "freeze", ply:UserID(), secs)
button:SetImage2("fadmin/icons/disable")
button:SetText("Unfreeze")
button:GetParent():InvalidateLayout()
end)
else
RunConsoleCommand("_FAdmin", "unfreeze", ply:UserID())
end
button:SetImage2("null")
button:SetText("Freeze")
button:GetParent():InvalidateLayout()
end)
end

View File

@@ -0,0 +1,79 @@
local function Freeze(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local time = tonumber(args[2]) or 0
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Freeze", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and not target:FAdmin_GetGlobal("FAdmin_frozen") then
target:FAdmin_SetGlobal("FAdmin_frozen", true)
target:Lock()
if time == 0 then continue end
timer.Simple(time, function()
if not IsValid(target) or not target:FAdmin_GetGlobal("FAdmin_frozen") then return end
target:FAdmin_SetGlobal("FAdmin_frozen", false)
target:UnLock()
end)
end
end
FAdmin.Messages.FireNotification("freeze", ply, targets, {time})
return true, targets, time
end
local function Unfreeze(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Freeze", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and target:FAdmin_GetGlobal("FAdmin_frozen") then
target:FAdmin_SetGlobal("FAdmin_frozen", false)
target:UnLock()
end
end
FAdmin.Messages.FireNotification("unfreeze", ply, targets)
return true, targets
end
FAdmin.StartHooks["Freeze"] = function()
FAdmin.Messages.RegisterNotification{
name = "freeze",
hasTarget = true,
receivers = "involved+admins",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
message = {"instigator", " froze ", "targets", " ", "extraInfo.1"},
}
FAdmin.Messages.RegisterNotification{
name = "unfreeze",
hasTarget = true,
receivers = "involved+admins",
message = {"instigator", " unfroze ", "targets"},
}
FAdmin.Commands.AddCommand("freeze", Freeze)
FAdmin.Commands.AddCommand("unfreeze", Unfreeze)
FAdmin.Access.AddPrivilege("Freeze", 2)
end
local disallow = function(ply) if ply:FAdmin_GetGlobal("FAdmin_frozen") then return false end end
hook.Add("PlayerSpawnObject", "FAdmin_jail", disallow)
hook.Add("CanPlayerSuicide", "FAdmin_jail", disallow)

View File

@@ -0,0 +1,164 @@
-- Controls for the give weapons menu. These are litterally copied and edited from the garry's mod code.
-- Remaking them in case the gamemode is not derived from sandbox
-- Copying from garry's mod code because I'm lazy and because it looks good.
-- Weapon icon:
local PANEL = {}
function PANEL:Init()
self:SetSize(83, 83)
self.Label = vgui.Create("DLabel", self)
self:SetKeepAspect(true)
self:SetDrawBorder(true)
self.m_Image:SetPaintedManually(true)
end
function PANEL:PerformLayout()
self.Label:SizeToContents()
self.Label:SetFont("TabLarge")
self.Label:SetTextColor(color_white)
self.Label:SetContentAlignment(5)
self.Label:SetWide(self:GetWide())
self.Label:AlignBottom(2)
DImageButton.PerformLayout(self)
if self.imgAdmin then
self.imgAdmin:SizeToContents()
self.imgAdmin:AlignTop(4)
self.imgAdmin:AlignRight(4)
end
end
function PANEL:CreateAdminIcon()
self.imgAdmin = vgui.Create("DImage", self)
self.imgAdmin:SetImage("icon16/shield.png") -- SilkIcons are now merged into GMOD as materials/icon16
self.imgAdmin:SetTooltip("#Admin Only")
end
function PANEL:Paint()
local w, h = self:GetSize()
self.m_Image:Paint()
surface.SetDrawColor(30, 30, 30, 200)
surface.DrawRect(0, h - 16, w, 16)
end
function PANEL:Setup(NiceName, SpawnName, IconMaterial, AdminOnly, Parent, IsAmmo)
self.Label:SetText(DarkRP.deLocalise(NiceName))
self.DoClick = function() Parent:DoGiveWeapon(SpawnName, IsAmmo) end
self.DoRightClick = function() end
if not IconMaterial then
IconMaterial = "VGUI/entities/" .. SpawnName
end
self:SetOnViewMaterial(IconMaterial, "vgui/swepicon")
if AdminOnly then self:CreateAdminIcon() end
self:InvalidateLayout()
end
local WeaponIcon = vgui.RegisterTable(PANEL, "DImageButton")
-- Full panel:
local PANEL2 = {}
function PANEL2:Init()
self.PanelList = vgui.Create("DPanelList", self)
self.PanelList:SetPadding(4)
self.PanelList:SetSpacing(2)
self.PanelList:EnableVerticalScrollbar(true)
end
function PANEL2:BuildList()
self.PanelList:Clear()
if not self.HideAmmo then
local AmmoCat = vgui.Create("DCollapsibleCategory", self)
self.PanelList:AddItem(AmmoCat)
AmmoCat:SetLabel("Give ammo")
local AmmoPan = vgui.Create("DPanelList")
AmmoCat:SetContents(AmmoPan)
AmmoPan:EnableHorizontal(true)
AmmoPan:SetPaintBackground(false)
AmmoPan:SetSpacing(2)
AmmoPan:SetPadding(2)
AmmoPan:SetAutoSize(true)
for k in SortedPairs(FAdmin.AmmoTypes) do
local Icon = vgui.CreateFromTable(WeaponIcon, self)
Icon:Setup(k, k, "spawnicons/models/items/boxmrounds60x60.png", false, self, true) -- Gets created clientside by GMOD when someone is after that model, or trying to buy ammo.
AmmoPan:AddItem(Icon)
end
end
local Weapons = weapons.GetList()
local Categorised = {}
Categorised["Half-life 2"] = {}
for k, weapon in pairs(FAdmin.HL2Guns) do
table.insert(Categorised["Half-life 2"], {PrintName = k, ClassName = weapon, Spawnable = true,
Author = "Half-life 2",
Contact = "gaben@valvesoftware.com",
Instructions = "Shoot!"})
end
for k, weapon in pairs(Weapons) do
weapon = weapons.Get(weapon.ClassName)
Weapons[k] = weapon
weapon.Category = weapon.Category or "Other"
if not weapon.Spawnable and not weapon.AdminSpawnable then
Weapons[k] = nil
else
Categorised[weapon.Category] = Categorised[weapon.Category] or {}
table.insert(Categorised[weapon.Category], weapon)
Weapons[k] = nil
end
end
Weapons = nil
for CategoryName, v in SortedPairs(Categorised) do
local Category = vgui.Create("DCollapsibleCategory", self)
self.PanelList:AddItem(Category)
Category:SetLabel(CategoryName)
Category:SetCookieName("WeaponSpawn." .. CategoryName)
local Content = vgui.Create("DPanelList")
Category:SetContents(Content)
Content:EnableHorizontal(true)
Content:SetPaintBackground(false)
Content:SetSpacing(2)
Content:SetPadding(2)
Content:SetAutoSize(true)
for _, WeaponTable in SortedPairsByMemberValue(v, "PrintName") do
local Icon = vgui.CreateFromTable(WeaponIcon, self)
Icon:Setup(WeaponTable.PrintName or WeaponTable.ClassName, WeaponTable.ClassName, WeaponTable.SpawnMenuIcon, WeaponTable.AdminSpawnable and not WeaponTable.Spawnable, self)
local Tooltip = Format("Name: %s", WeaponTable.PrintName)
if WeaponTable.Author ~= "" then Tooltip = Format("%s\nAuthor: %s", Tooltip, WeaponTable.Author) end
if WeaponTable.Contact ~= "" then Tooltip = Format("%s\nContact: %s", Tooltip, WeaponTable.Contact) end
if WeaponTable.Instructions ~= "" then Tooltip = Format("%s\n\n%s", Tooltip, WeaponTable.Instructions) end
Icon:SetTooltip(Tooltip)
Content:AddItem(Icon)
end
end
self.PanelList:InvalidateLayout()
end
function PANEL2:PerformLayout()
self.PanelList:StretchToParent(0, 0, 0, 0)
end
derma.DefineControl("FAdmin_weaponPanel", "Weapon panel for giving weapons in FAdmin", PANEL2, "Panel")

View File

@@ -0,0 +1,31 @@
local function GiveWeaponGui(ply)
local frame = vgui.Create("DFrame")
frame:SetTitle("Give weapon")
frame:SetSize(ScrW() / 2, ScrH() - 50)
frame:Center()
frame:SetVisible(true)
frame:MakePopup()
local WeaponMenu = vgui.Create("FAdmin_weaponPanel", frame)
WeaponMenu:StretchToParent(0,25,0,0)
function WeaponMenu:DoGiveWeapon(SpawnName, IsAmmo)
if not ply:IsValid() then return end
local giveWhat = (IsAmmo and "ammo") or "weapon"
RunConsoleCommand("FAdmin", "give" .. giveWhat, ply:UserID(), SpawnName)
end
WeaponMenu:BuildList()
end
FAdmin.StartHooks["GiveWeapons"] = function()
FAdmin.Access.AddPrivilege("giveweapon", 2)
FAdmin.Commands.AddCommand("giveweapon", nil, "<Player>", "<weapon>")
FAdmin.ScoreBoard.Player:AddActionButton("Give weapon(s)", "fadmin/icons/weapon", Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "giveweapon") end, function(ply, button)
GiveWeaponGui(ply)
end)
end

View File

@@ -0,0 +1,57 @@
FAdmin.HL2Guns = {
Crowbar = "weapon_crowbar",
Gravgun = "weapon_gravgun",
Physgun = "weapon_physgun",
Stunstick = "weapon_stunstick",
Pistol = "weapon_pistol",
["357"] = "weapon_357",
Smg1 = "weapon_smg1",
Ar2 = "weapon_ar2",
Shotgun = "weapon_shotgun",
Crossbow = "weapon_crossbow",
Grenade = "weapon_frag",
RPG = "weapon_rpg",
["S.L.A.M."] = "weapon_SLAM",
Camera = "gmod_camera",
Toolgun = "gmod_tool"
}
FAdmin.AmmoTypes = {
AR2 = 30,
AR2AltFire = 3,
pistol = 180,
smg1 = 45,
["357"] = 6,
XBowBolt = 3,
Buckshot = 6,
RPG_Round = 3,
SMG1_Grenade = 1,
Grenade = 3,
slam = 1
}
FAdmin.StartHooks["GivingWeapons"] = function()
FAdmin.Messages.RegisterNotification{
name = "giveweapon",
hasTarget = true,
message = {"instigator", " gave ", "extraInfo.1", " to ", "targets"},
receivers = "everyone",
writeExtraInfo = function(i) net.WriteString(i[1]) end,
readExtraInfo = function()
return {net.ReadString()}
end,
extraInfoColors = {Color(255, 102, 0)}
}
FAdmin.Messages.RegisterNotification{
name = "giveammo",
hasTarget = true,
message = {"instigator", " gave ", "extraInfo.1", " ", "extraInfo.2", " ammo to ", "targets"},
receivers = "everyone",
writeExtraInfo = function(info) net.WriteUInt(info[1], 32) net.WriteString(info[2]) end,
readExtraInfo = function()
return {tostring(net.ReadUInt(32)), net.ReadString()}
end,
extraInfoColors = {Color(255, 102, 0), Color(255, 102, 153)}
}
end

View File

@@ -0,0 +1,57 @@
local function GiveWeapon(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "giveweapon") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[2] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local weapon = weapons.GetStored(args[2])
if table.HasValue(FAdmin.HL2Guns, args[2]) then weapon = args[2]
elseif weapon and weapon.ClassName then weapon = weapon.ClassName end
if not weapon then return false end
for _, target in ipairs(targets) do
if IsValid(target) then
target:Give(weapon)
end
end
FAdmin.Messages.ActionMessage(ply, targets, "You gave %s a " .. weapon, "%s gave you a " .. weapon, "Gave %s a " .. weapon)
FAdmin.Messages.FireNotification("giveweapon", ply, targets, {weapon})
return true, targets, weapon
end
local function GiveAmmo(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "giveweapon") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[2] or not FAdmin.AmmoTypes[args[2]] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local ammo = args[2]
local amount = tonumber(args[3]) or FAdmin.AmmoTypes[args[2]]
for _, target in ipairs(targets) do
if IsValid(target) then
target:GiveAmmo(amount, ammo)
end
end
FAdmin.Messages.FireNotification("giveammo", ply, targets, {amount, ammo})
return true, targets, ammo, amount
end
FAdmin.StartHooks["GiveWeapons"] = function()
FAdmin.Commands.AddCommand("giveweapon", GiveWeapon)
FAdmin.Commands.AddCommand("giveammo", GiveAmmo)
FAdmin.Access.AddPrivilege("giveweapon", 3)
end

View File

@@ -0,0 +1,40 @@
FAdmin.StartHooks["God"] = function()
FAdmin.Messages.RegisterNotification{
name = "god",
hasTarget = true,
message = {"instigator", " enabled godmode for ", "targets"},
receivers = "everyone",
}
FAdmin.Messages.RegisterNotification{
name = "ungod",
hasTarget = true,
message = {"instigator", " disabled godmode for ", "targets"},
receivers = "everyone",
}
FAdmin.Access.AddPrivilege("God", 2)
FAdmin.Commands.AddCommand("god", nil, "<Player>")
FAdmin.Commands.AddCommand("ungod", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("FAdmin_godded") then return "Ungod" end
return "God"
end, function(ply)
if ply:FAdmin_GetGlobal("FAdmin_godded") then return "fadmin/icons/god", "fadmin/icons/disable" end
return "fadmin/icons/god"
end, Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "God") end, function(ply, button)
if not ply:FAdmin_GetGlobal("FAdmin_godded") then
RunConsoleCommand("_FAdmin", "god", ply:UserID())
else
RunConsoleCommand("_FAdmin", "ungod", ply:UserID())
end
if not ply:FAdmin_GetGlobal("FAdmin_godded") then button:SetImage2("fadmin/icons/disable") button:SetText("Ungod") button:GetParent():InvalidateLayout() return end
button:SetImage2("null")
button:SetText("God")
button:GetParent():InvalidateLayout()
end)
end

View File

@@ -0,0 +1,66 @@
local function God(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "God") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if IsValid(target) and not target:FAdmin_GetGlobal("FAdmin_godded") then
target:FAdmin_SetGlobal("FAdmin_godded", true)
target:GodEnable()
end
end
FAdmin.Messages.FireNotification("god", ply, targets)
return true, targets
end
local function Ungod(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "God") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if IsValid(target) and target:FAdmin_GetGlobal("FAdmin_godded") then
target:FAdmin_SetGlobal("FAdmin_godded", false)
target:GodDisable()
end
end
FAdmin.Messages.FireNotification("ungod", ply, targets)
return true, targets
end
FAdmin.StartHooks["God"] = function()
FAdmin.Messages.RegisterNotification{
name = "god",
hasTarget = true,
message = {"instigator", " enabled godmode for ", "targets"},
receivers = "everyone",
}
FAdmin.Messages.RegisterNotification{
name = "ungod",
hasTarget = true,
message = {"instigator", " disabled godmode for ", "targets"},
receivers = "everyone",
}
FAdmin.Commands.AddCommand("God", God)
FAdmin.Commands.AddCommand("Ungod", Ungod)
FAdmin.Access.AddPrivilege("God", 2)
end
hook.Add("PlayerSpawn", "FAdmin_God", function(ply)
if ply:FAdmin_GetGlobal("FAdmin_godded") then
ply:GodEnable()
end
end)

View File

@@ -0,0 +1,31 @@
FAdmin.StartHooks["Health"] = function()
FAdmin.Messages.RegisterNotification{
name = "sethealth",
hasTarget = true,
message = {"instigator", " set the health of ", "targets", " to ", "extraInfo.1"},
readExtraInfo = function() return {tostring(net.ReadUInt(16))} end
}
FAdmin.Access.AddPrivilege("SetHealth", 2)
FAdmin.Commands.AddCommand("hp", nil, "<Player>", "<health>")
FAdmin.Commands.AddCommand("SetHealth", nil, "[Player]", "<health>")
FAdmin.ScoreBoard.Player:AddActionButton("Set health", "icon16/heart.png", Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "SetHealth", ply) end,
function(ply, button)
--Do nothing when the button has been clicked
end,
function(ply, button) -- Create the Wang when the mouse is pressed
button.OnMousePressed = function()
local window = Derma_StringRequest("Select health", "What do you want the health of the person to be?", "",
function(text)
local health = DarkRP.toInt(text or 100) or 100
RunConsoleCommand("_fadmin", "SetHealth", ply:UserID(), health)
end
)
-- The user is usually holding tab when clicking health, so fix the focus
window:RequestFocus()
end
end)
end

View File

@@ -0,0 +1,39 @@
local function SetHealth(ply, cmd, args)
if not args[1] then return false end
local Health = tonumber(args[2] or 100)
if not Health then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
targets = {ply}
Health = math.floor(tonumber(args[1] or 100) or 100)
return false
end
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "SetHealth", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) then
target:SetHealth(Health)
end
end
FAdmin.Messages.FireNotification("sethealth", ply, targets, {Health})
return true, targets, Health
end
FAdmin.StartHooks["Health"] = function()
FAdmin.Messages.RegisterNotification{
name = "sethealth",
hasTarget = true,
receivers = "everyone",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
message = {"instigator", " set the health of ", "targets", " to ", "extraInfo.1"},
}
FAdmin.Commands.AddCommand("SetHealth", SetHealth)
FAdmin.Commands.AddCommand("hp", SetHealth)
FAdmin.Access.AddPrivilege("SetHealth", 2)
end

View File

@@ -0,0 +1,39 @@
FAdmin.StartHooks["Ignite"] = function()
FAdmin.Messages.RegisterNotification{
name = "ignite",
hasTarget = true,
message = {"instigator", " ignited ", "targets", " ", "extraInfo.1"},
readExtraInfo = function()
local time = net.ReadUInt(16)
return {time == 0 and FAdmin.PlayerActions.commonTimes[time] or string.format("for %s", FAdmin.PlayerActions.commonTimes[time] or (time .. " seconds"))}
end
}
FAdmin.Messages.RegisterNotification{
name = "unignite",
hasTarget = true,
message = {"instigator", " unignited ", "targets"},
}
FAdmin.Access.AddPrivilege("Ignite", 2)
FAdmin.Commands.AddCommand("Ignite", nil, "<Player>", "[time]")
FAdmin.Commands.AddCommand("unignite", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply) return (ply:FAdmin_GetGlobal("FAdmin_ignited") and "Extinguish") or "Ignite" end,
function(ply) local disabled = (ply:FAdmin_GetGlobal("FAdmin_ignited") and "fadmin/icons/disable") or nil return "fadmin/icons/ignite", disabled end,
Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Ignite", ply) end,
function(ply, button)
if not ply:FAdmin_GetGlobal("FAdmin_ignited") then
RunConsoleCommand("_FAdmin", "ignite", ply:UserID())
button:SetImage2("fadmin/icons/disable")
button:SetText("Extinguish")
button:GetParent():InvalidateLayout()
else
RunConsoleCommand("_FAdmin", "unignite", ply:UserID())
button:SetImage2("null")
button:SetText("Ignite")
button:GetParent():InvalidateLayout()
end
end)
end

View File

@@ -0,0 +1,67 @@
local function Ignite(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local time = tonumber(args[2]) or 10
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Ignite", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) then
target:Ignite(time, 0)
target:FAdmin_SetGlobal("FAdmin_ignited", true)
timer.Simple(time, function()
if IsValid(target) then target:FAdmin_SetGlobal("FAdmin_ignited", false) end
end)
end
end
FAdmin.Messages.FireNotification("ignite", ply, targets, {time})
return true, targets
end
local function UnIgnite(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Ignite") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) then
target:Extinguish()
target:FAdmin_SetGlobal("FAdmin_ignited", false)
end
end
FAdmin.Messages.FireNotification("unignite", ply, targets)
return true, targets
end
FAdmin.StartHooks["Ignite"] = function()
FAdmin.Messages.RegisterNotification{
name = "ignite",
hasTarget = true,
receivers = "involved+admins",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
message = {"instigator", " ignited ", "targets", " ", "extraInfo.1"},
}
FAdmin.Messages.RegisterNotification{
name = "unignite",
hasTarget = true,
message = {"instigator", " unignited ", "targets"},
receivers = "involved+admins",
}
FAdmin.Commands.AddCommand("Ignite", Ignite)
FAdmin.Commands.AddCommand("Unignite", UnIgnite)
FAdmin.Access.AddPrivilege("Ignite", 2)
end

View File

@@ -0,0 +1,61 @@
FAdmin.StartHooks["Jail"] = function()
FAdmin.Access.AddPrivilege("Jail", 2)
FAdmin.Commands.AddCommand("Jail", nil, "<Player>", "[Small/Normal/Big]", "[Time]")
FAdmin.Commands.AddCommand("UnJail", nil, "<Player>")
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Jail/Unjail", function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then
RunConsoleCommand("_FAdmin", "unjail", ply:UserID())
else
RunConsoleCommand("_FAdmin", "jail", ply:UserID())
end
end)
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then return "Unjail" end
return "Jail"
end,
function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then return "fadmin/icons/jail", "fadmin/icons/disable" end
return "fadmin/icons/jail"
end,
Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Jail", ply) end,
function(ply, button)
if ply:FAdmin_GetGlobal("fadmin_jailed") then RunConsoleCommand("_FAdmin", "unjail", ply:UserID()) button:SetImage2("null") button:SetText("Jail") button:GetParent():InvalidateLayout() return end
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Jail Type:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for k, v in ipairs(FAdmin.PlayerActions.JailTypes) do
if v == "Unjail" then continue end
FAdmin.PlayerActions.addTimeSubmenu(menu, v .. " jail",
function()
RunConsoleCommand("_FAdmin", "Jail", ply:UserID(), k)
button:SetText("Unjail") button:GetParent():InvalidateLayout()
button:SetImage2("fadmin/icons/disable")
end,
function(secs)
RunConsoleCommand("_FAdmin", "Jail", ply:UserID(), k, secs)
button:SetText("Unjail")
button:GetParent():InvalidateLayout()
button:SetImage2("fadmin/icons/disable")
end
)
end
menu:Open()
end)
end

View File

@@ -0,0 +1,38 @@
FAdmin.PlayerActions.JailTypes = {}
FAdmin.PlayerActions.JailTypes[1] = "Small"
FAdmin.PlayerActions.JailTypes[2] = "Normal"
FAdmin.PlayerActions.JailTypes[3] = "Big"
FAdmin.PlayerActions.JailTypes[4] = "Unjail"
hook.Add("CanTool", "FAdmin_jailed", function(ply) -- shared so it doesn't look like you can use tool
if ply:FAdmin_GetGlobal("fadmin_jailed") then
return false
end
end)
hook.Add("PlayerNoClip", "FAdmin_jail", function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then
return false
end
end)
FAdmin.StartHooks["Jailing"] = function()
FAdmin.Messages.RegisterNotification{
name = "jail",
hasTarget = true,
message = {"instigator", " jailed ", "targets", " ", "extraInfo.1"},
receivers = "involved+admins",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
readExtraInfo = function()
local time = net.ReadUInt(16)
return {time == 0 and FAdmin.PlayerActions.commonTimes[time] or string.format("for %s", FAdmin.PlayerActions.commonTimes[time] or (time .. " seconds"))}
end
}
FAdmin.Messages.RegisterNotification{
name = "unjail",
hasTarget = true,
message = {"instigator", " unjailed ", "targets"},
receivers = "involved+admins",
}
end

View File

@@ -0,0 +1,167 @@
local function createJailTimer(target, jailTime)
if jailTime == 0 then return end
timer.Create("FAdmin_jail" .. target:UserID(), jailTime, 1, function()
if not IsValid(target) then return end
if not target:FAdmin_GetGlobal("fadmin_jailed") then return end
timer.Remove("FAdmin_jail_watch" .. target:UserID())
target:FAdmin_SetGlobal("fadmin_jailed", false)
for k in pairs(target.FAdminJailProps) do
if not IsValid(k) then continue end
k:SetCanRemove(true)
k:Remove()
end
target.FAdminJailProps = nil
end)
end
local function Jail(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local JailType = FAdmin.PlayerActions.JailTypes[tonumber(args[2])] or args[2] or FAdmin.PlayerActions.JailTypes[2]
JailType = string.lower(JailType)
local JailTime = tonumber(args[3]) or 0
local time = ""
for _, target in ipairs(targets) do
if not IsValid(target) then continue end
if not FAdmin.Access.PlayerHasPrivilege(ply, "Jail", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local jailDistance
ply:ExitVehicle()
local JailProps = {}
if JailType == "unjail" or string.lower(cmd) == "unjail" then
if target.FAdminJailProps then
for k in pairs(target.FAdminJailProps) do
if not IsValid(k) then continue end
k:SetCanRemove(true)
k:Remove()
end
end
target.FAdminJailProps = nil
timer.Remove("FAdmin_jail" .. target:UserID())
timer.Remove("FAdmin_jail_watch" .. target:UserID())
target:FAdmin_SetGlobal("fadmin_jailed", false)
elseif JailType == "small" then
jailDistance = 50
table.insert(JailProps, {pos = Vector(0,0,58), ang = Angle(0,0,0), model = "models/props_wasteland/laundry_dryer001.mdl"})
elseif JailType == "normal" then
jailDistance = 70
table.insert(JailProps, {pos = Vector(0,0,-5), ang = Angle(90,0,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(0,0,97), ang = Angle(90,0,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(21,31,46), ang = Angle(0,90,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(21,-31,46), ang = Angle(0,90,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(-21,31,46), ang = Angle(0,90,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(-21,-31,46), ang = Angle(0,90,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(-52,0,46), ang = Angle(0,0,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
table.insert(JailProps, {pos = Vector(52,0,46), ang = Angle(0,0,0), model = "models/props_building_details/Storefront_Template001a_Bars.mdl"})
elseif JailType == "big" then -- Requires CSS but it's really funny
jailDistance = 80
table.insert(JailProps, {pos = Vector(0,0,-5), ang = Angle(0,0,0), model = "models/props/cs_havana/gazebo.mdl"})
table.insert(JailProps, {pos = Vector(70,0,50), ang = Angle(0,0,0), model = "models/props_borealis/borealis_door001a.mdl"})
table.insert(JailProps, {pos = Vector(-70,0,100), ang = Angle(0,0,90), model = "models/props_lab/lockerdoorleft.mdl"})
table.insert(JailProps, {pos = Vector(-35,-55,100), ang = Angle(0,60,90), model = "models/props_lab/lockerdoorleft.mdl"})
table.insert(JailProps, {pos = Vector(-35,55,100), ang = Angle(0,300,90), model = "models/props_lab/lockerdoorleft.mdl"})
table.insert(JailProps, {pos = Vector(35,-55,100), ang = Angle(0,300,90), model = "models/props_lab/lockerdoorleft.mdl"})
table.insert(JailProps, {pos = Vector(35,55,100), ang = Angle(0,240,90), model = "models/props_lab/lockerdoorleft.mdl"})
else
FAdmin.Messages.SendMessage(ply, 5, "Bad arguments")
return
end
if not target:FAdmin_GetGlobal("fadmin_jailed") and JailType ~= "unjail" and string.lower(cmd) ~= "unjail" then
target:SetMoveType(MOVETYPE_WALK)
target:FAdmin_SetGlobal("fadmin_jailed", true)
target.FAdminJailPos = target:GetPos()
target.FAdminJailProps = {}
for _, v in ipairs(JailProps) do
local JailProp = ents.Create("fadmin_jail")
JailProp:SetPos(target.FAdminJailPos + v.pos)
JailProp:SetAngles(v.ang)
JailProp:SetModel(v.model)
JailProp:Spawn()
JailProp:Activate()
JailProp.target = target
JailProp.targetPos = target.FAdminJailPos
target.FAdminJailProps[JailProp] = true
end
createJailTimer(target, JailTime)
jailDistance = jailDistance * jailDistance
local userid = target:UserID()
timer.Create("FAdmin_jail_watch" .. target:UserID(), 1, 0, function()
if not IsValid(target) then
timer.Remove("FAdmin_jail_watch" .. userid)
return
end
if target:GetPos():DistToSqr(target.FAdminJailPos) > jailDistance then
target:SetPos(target.FAdminJailPos)
end
end)
time = "for " .. JailTime .. " seconds"
if JailTime == 0 then time = "indefinitely" end
end
end
if JailType == "unjail" or string.lower(cmd) == "unjail" then
FAdmin.Messages.FireNotification("unjail", ply, targets)
else
FAdmin.Messages.FireNotification("jail", ply, targets, {JailTime})
end
return true, targets, JailType, time
end
FAdmin.StartHooks["Jail"] = function()
FAdmin.Commands.AddCommand("Jail", Jail)
FAdmin.Commands.AddCommand("UnJail", Jail)
FAdmin.Access.AddPrivilege("Jail", 2)
end
hook.Add("PlayerSpawn", "FAdmin_jail", function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then
timer.Simple(0.1, function() if IsValid(ply) then ply:SetPos(ply.FAdminJailPos) end end)
end
end)
hook.Add("PlayerSpawnObject", "FAdmin_jailed", function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then
return false
end
end)
hook.Add("CanPlayerEnterVehicle", "FAdmin_jailed", function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then
return false
end
end)
--Kill stupid addons that does not call CanPlayerEnterVehicle (like Sit Anywhere script)
hook.Add("PlayerEnteredVehicle", "FAdmin_jailed", function(ply)
if ply:FAdmin_GetGlobal("fadmin_jailed") then
ply:ExitVehicle()
end
end)

View File

@@ -0,0 +1,377 @@
--[[
WHEN GETTING KICKED
]]
local KickText = ""
usermessage.Hook("FAdmin_kick_start", function()
hook.Add("HUDPaint", "FAdmin_kick", function()
draw.RoundedBox(0,0,0, ScrW(), ScrH(), Color(0,0,0,255))
draw.DrawNonParsedText("You are getting kicked\nReason: " .. KickText .. "\nLeaving voluntarily is also an option.", "HUDNumber5", ScrW() / 2, ScrH() / 2, Color(255, 0, 0, 255), TEXT_ALIGN_CENTER)
end)
end)
usermessage.Hook("FAdmin_kick_cancel", function()
hook.Remove("HUDPaint", "FAdmin_kick")
FAdmin.Messages.AddMessage(4, "Kick was canceled by admin")
end)
usermessage.Hook("FAdmin_kick_update", function(um)
KickText = um:ReadString()
end)
local BanText = "No reason"
local BanTimeText = "permanent"
usermessage.Hook("FAdmin_ban_start", function()
hook.Add("HUDPaint", "FAdmin_ban", function()
draw.RoundedBox(0,0,0, ScrW(), ScrH(), Color(0,0,0,255))
draw.DrawNonParsedText("You are getting banned\nReason: " .. BanText .. "\nTime: " .. " " .. BanTimeText .. "\nLeaving voluntarily or rejoining will not prevent banning.", "HUDNumber5", ScrW() / 2, ScrH() / 2, Color(0, 0, 255, 255), TEXT_ALIGN_CENTER)
end)
end)
usermessage.Hook("FAdmin_ban_cancel", function()
hook.Remove("HUDPaint", "FAdmin_ban")
FAdmin.Messages.AddMessage(4, "Ban was canceled by admin")
end)
usermessage.Hook("FAdmin_ban_update", function(um)
BanTimeText = FAdmin.PlayerActions.ConvertBanTime(um:ReadLong())
BanText = um:ReadString()
end)
--[[---------------------------------------------------------------------------
Show the window for banning
---------------------------------------------------------------------------]]
local function showBanWindow(SteamID, NICK, time, reason)
local BanTime = time or 60
NICK = NICK or ""
reason = reason or "No reason"
local M,H,D,W,Y = BanTime % 60,
math.floor(BanTime / 60) % 24,
math.floor(BanTime / 1440) % 7,
math.floor(BanTime / 10080) % 53,
math.floor(BanTime / 525948)
RunConsoleCommand("_FAdmin", "ban", SteamID, "start")
local Window = vgui.Create("DFrame")
Window:SetTitle("Ban Details")
Window:SetDraggable(false)
Window:ShowCloseButton(false)
Window:SetBackgroundBlur(true)
Window:SetDrawOnTop(true)
local InnerPanel = vgui.Create("DPanel", Window)
InnerPanel:SetPaintBackground(false)
local Text = vgui.Create("DLabel", InnerPanel)
Text:SetText("Ban " .. NICK .. "")
Text:SizeToContents()
Text:SetContentAlignment(5)
local TimePanel = vgui.Create("DPanel", Window)
TimePanel:SetPaintBackground(false)
local TextEntry = vgui.Create("DTextEntry", TimePanel)
function TextEntry:OnTextChanged()
RunConsoleCommand("_FAdmin", "ban", SteamID, "update", BanTime, self:GetValue())
end
TextEntry:SetText(DarkRP.deLocalise(reason))
TextEntry.OnEnter = function() Window:Close() RunConsoleCommand("_FAdmin", "ban", SteamID, "execute", BanTime, TextEntry:GetValue()) end
function TextEntry:OnFocusChanged(changed)
self:RequestFocus()
self:SelectAllText(true)
end
local Minutes = vgui.Create("DNumberWang", TimePanel)
Minutes:SetMinMax(0, 59)
Minutes:SetDecimals(0)
Minutes:SetValue(M)
local Hours = vgui.Create("DNumberWang", TimePanel)
Hours:SetMinMax(0, 23)
Hours:SetValue(H)
Hours:SetDecimals(0)
local Days = vgui.Create("DNumberWang", TimePanel)
Days:SetMinMax(0, 6)
Days:SetValue(D)
Days:SetDecimals(0)
local Weeks = vgui.Create("DNumberWang", TimePanel)
Weeks:SetMinMax(0, 53)
Weeks:SetValue(W)
Weeks:SetDecimals(0)
local Years = vgui.Create("DNumberWang", TimePanel)
Years:SetMinMax(0, 3)
Years:SetValue(Y)
Years:SetDecimals(0)
local MinLabel, HourLabel, DayLabel, WeekLabel, YearLabel = vgui.Create("DLabel", TimePanel), vgui.Create("DLabel", TimePanel),
vgui.Create("DLabel", TimePanel), vgui.Create("DLabel", TimePanel), vgui.Create("DLabel", TimePanel)
MinLabel:SetText("Minutes:")
HourLabel:SetText("Hours:")
DayLabel:SetText("Days:")
WeekLabel:SetText("Weeks:")
YearLabel:SetText("Years:")
MinLabel:SetPos(370, 0)
HourLabel:SetPos(280, 0)
DayLabel:SetPos(190, 0)
WeekLabel:SetPos(100, 0)
YearLabel:SetPos(10, 0)
local function update()
BanTime = M + H * 60 + D * 1440 + W * 10080 + Y * 525948
RunConsoleCommand("_FAdmin", "ban", SteamID, "update", BanTime, TextEntry:GetValue())
end
function Minutes:OnValueChanged(val) if val == M then return end M = val update() end
function Hours:OnValueChanged(val) if val == H then return end H = val update() end
function Days:OnValueChanged(val) if val == D then return end D = val update() end
function Weeks:OnValueChanged(val) if val == W then return end W = val update() end
function Years:OnValueChanged(val) if val == Y then return end Y = val update() end
local ButtonPanel = vgui.Create("DPanel", Window)
ButtonPanel:SetTall(25)
ButtonPanel:SetPaintBackground(false)
local Button = vgui.Create("DButton", ButtonPanel)
Button:SetText("OK")
Button:SizeToContents()
Button:SetTall(20)
Button:SetWide(Button:GetWide() + 20)
Button:SetPos(5, 3)
Button.DoClick = function()
Window:Close()
M, H, D, W, Y = Minutes:GetValue(), Hours:GetValue(), Days:GetValue(), Weeks:GetValue(), Years:GetValue()
update()
RunConsoleCommand("_FAdmin", "ban", SteamID, BanTime, (TextEntry and TextEntry:GetValue()) or "")
end
local ButtonCancel = vgui.Create("DButton", ButtonPanel)
ButtonCancel:SetText("Cancel")
ButtonCancel:SizeToContents()
ButtonCancel:SetTall(20)
ButtonCancel:SetWide(Button:GetWide() + 20)
ButtonCancel:SetPos(5, 3)
ButtonCancel.DoClick = function() Window:Close() RunConsoleCommand("_FAdmin", "ban", SteamID, "cancel") end
ButtonCancel:MoveRightOf(Button, 5)
ButtonPanel:SetWide(Button:GetWide() + 5 + ButtonCancel:GetWide() + 10)
Window:SetSize(450, 111 + 75 + 20)
Window:Center()
InnerPanel:StretchToParent(5, 25, 5, 125)
TimePanel:StretchToParent(5, 83, 5, 37)
Minutes:SetPos(370, 20)
Hours:SetPos(280, 20)
Days:SetPos(190, 20)
Weeks:SetPos(100, 20)
Years:SetPos(10, 20)
Text:StretchToParent(5, 5, 5, nil)
TextEntry:StretchToParent(5, nil, 5, nil)
TextEntry:AlignBottom(5)
TextEntry:RequestFocus()
ButtonPanel:CenterHorizontal()
ButtonPanel:AlignBottom(7)
Window:MakePopup()
Window:DoModal()
end
--[[
ADD BUTTONS ETC. TO MENU
]]
FAdmin.StartHooks["CL_KickBan"] = function()
FAdmin.Access.AddPrivilege("Kick", 2)
FAdmin.Access.AddPrivilege("Ban", 2)
FAdmin.Access.AddPrivilege("UnBan", 2)
FAdmin.Commands.AddCommand("kick", nil, "<Player>", "[Reason]")
FAdmin.Commands.AddCommand("ban", nil, "<Player>", "<Time (minutes)>", "[Reason]")
FAdmin.Commands.AddCommand("unban", "<SteamID>")
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Quick Kick", function(ply, Panel)
RunConsoleCommand("_FAdmin", "kick", ply:UserID(), "Quick kick")
if IsValid(Panel) then Panel:Remove() end
end)
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Ban", function(ply, Panel)
showBanWindow(ply:SteamID(), ply:Nick())
if IsValid(Panel) then Panel:Remove() end
end)
-- Kick button
FAdmin.ScoreBoard.Player:AddActionButton("Kick", "fadmin/icons/kick", nil, function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Kick", ply) end, function(ply)
if not IsValid(ply) then return end
local UserID = ply:UserID()
local NICK = ply:Nick()
RunConsoleCommand("FAdmin", "kick", UserID, "start")
local Window = vgui.Create("DFrame")
Window:SetTitle("Reason for kicking")
Window:SetDraggable(false)
Window:ShowCloseButton(false)
Window:SetBackgroundBlur(true)
Window:SetDrawOnTop(true)
local InnerPanel = vgui.Create("DPanel", Window)
InnerPanel:SetPaintBackground(false)
local Text = vgui.Create("DLabel", InnerPanel)
Text:SetText(NICK .. " knows they are getting kicked\nTake all your time entering the reason, they can't do anything anymore")
Text:SizeToContents()
Text:SetContentAlignment(5)
Text:SetTextColor(color_white)
local TextEntry = vgui.Create("DTextEntry", InnerPanel)
function TextEntry:OnTextChanged()
RunConsoleCommand("_FAdmin", "kick", UserID, "update", self:GetValue())
end
TextEntry:SetText("Enter reason here")
TextEntry.OnEnter = function() Window:Close() RunConsoleCommand("_FAdmin", "kick", UserID, "execute", TextEntry:GetValue()) end
function TextEntry:OnFocusChanged(changed)
self:RequestFocus()
self:SelectAllText(true)
end
local ButtonPanel = vgui.Create("DPanel", Window)
ButtonPanel:SetTall(30)
ButtonPanel:SetPaintBackground(false)
local Button = vgui.Create("DButton", ButtonPanel)
Button:SetText("OK")
Button:SizeToContents()
Button:SetTall(20)
Button:SetWide(Button:GetWide() + 20)
Button:SetPos(5, 5)
Button.DoClick = function() Window:Close() RunConsoleCommand("_FAdmin", "kick", UserID, "execute", TextEntry:GetValue()) end
local ButtonCancel = vgui.Create("DButton", ButtonPanel)
ButtonCancel:SetText("Cancel")
ButtonCancel:SizeToContents()
ButtonCancel:SetTall(20)
ButtonCancel:SetWide(Button:GetWide() + 20)
ButtonCancel:SetPos(5, 5)
ButtonCancel.DoClick = function()
Window:Close()
RunConsoleCommand("FAdmin", "kick", UserID, "cancel")
end
ButtonCancel:MoveRightOf(Button, 5)
ButtonPanel:SetWide(Button:GetWide() + 5 + ButtonCancel:GetWide() + 10)
local w, h = Text:GetSize()
w = math.max(w, 400)
Window:SetSize(w + 50, h + 25 + 75 + 10)
Window:Center()
InnerPanel:StretchToParent(5, 25, 5, 45)
Text:StretchToParent(5, 5, 5, 35)
TextEntry:StretchToParent(5, nil, 5, nil)
TextEntry:AlignBottom(5)
TextEntry:RequestFocus()
ButtonPanel:CenterHorizontal()
ButtonPanel:AlignBottom(8)
Window:MakePopup()
Window:DoModal()
end)
-- Ban button
FAdmin.ScoreBoard.Player:AddActionButton("Ban", "fadmin/icons/ban", nil, function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Ban", ply) end, function(ply)
local SteamID = ply:SteamID()
local NICK = ply:Nick()
if ply:IsBot() then SteamID = "BOT" end
showBanWindow(SteamID, NICK)
end)
FAdmin.ScoreBoard.Server:AddPlayerAction("Unban", function() return "fadmin/icons/ban", "fadmin/icons/disable" end, Color(0, 155, 0, 255), true, function(button)
local selectedLine
local Frame = vgui.Create("DFrame")
Frame:SetSize(740, 600)
Frame:SetTitle("Unban Details")
Frame:SetDraggable(true)
Frame:ShowCloseButton(true)
Frame:SetBackgroundBlur(true)
Frame:SetDrawOnTop(true)
local BanList = vgui.Create("DListView", Frame)
BanList:StretchToParent(5, 55, 5, 5)
BanList:AddColumn("SteamID")
BanList:AddColumn("Name")
BanList:AddColumn("Time")
BanList:AddColumn("Reason")
BanList:AddColumn("Banned by")
BanList:AddColumn("Banned by SteamID")
local unban = vgui.Create("DButton", Frame)
unban:SetText("Unban")
unban:SetPos(695, 25)
unban:SetSize(40, 25)
function unban:DoClick()
if IsValid(selectedLine) then
RunConsoleCommand("_FAdmin", "Unban", string.upper(selectedLine:GetValue(1)))
BanList:RemoveLine(selectedLine:GetID())
end
end
local edit = vgui.Create("DButton", Frame)
edit:SetText("Edit")
edit:SetPos(650, 25)
edit:SetSize(40, 25)
function edit:DoClick()
if not selectedLine then return end
showBanWindow(selectedLine:GetValue(1), selectedLine.name, selectedLine.time > os.time() and (selectedLine.time - os.time()) / 60 or 0, selectedLine.reason)
Frame:Close()
end
local function RetrieveBans(len)
local banCount = net.ReadUInt(32)
for i = 1, banCount do
local steamid = net.ReadString()
local time = net.ReadUInt(32)
local name = net.ReadString()
local reason = net.ReadString()
local adminname = net.ReadString()
local adminsteam = net.ReadString()
local Line = BanList:AddLine(
steamid,
name or "N/A",
(tonumber(time or "") and FAdmin.PlayerActions.ConvertBanTime((tonumber(time) - os.time()) / 60)) or "N/A",
reason or "",
adminname or "",
adminsteam or "")
Line.name = name
Line.time = time
Line.reason = reason
function Line:OnSelect()
selectedLine = self
end
end
end
net.Receive("FAdmin_retrievebans", RetrieveBans)
RunConsoleCommand("_FAdmin", "RequestBans")
Frame:Center()
Frame:MakePopup()
Frame:DoModal()
end)
end

View File

@@ -0,0 +1,96 @@
function FAdmin.PlayerActions.ConvertBanTime(time)
local Add = ""
time = math.Round(time)
if time <= 0 then
return "permanent"
elseif time < 60 then
-- minutes
return math.ceil(time) .. " minute(s)"
elseif time >= 60 and time < 1440 then
-- hours
if math.floor((time / 60 - math.floor(time / 60)) * 60) > 0 then
Add = ", " .. FAdmin.PlayerActions.ConvertBanTime((time / 60 - math.floor(time / 60)) * 60)
end
return math.floor(time / 60) .. " hour(s)" .. Add
elseif time >= 1440 and time < 10080 then
-- days
if math.floor((time / 1440 - math.floor(time / 1440)) * 1440) > 0 then
Add = ", " .. FAdmin.PlayerActions.ConvertBanTime((time / 1440 - math.floor(time / 1440)) * 1440)
end
return math.floor(time / 1440) .. " day(s)" .. Add
elseif time >= 10080 and time < 525948 then
-- weeks
if math.floor((time / 10080 - math.floor(time / 10080)) * 10080) > 0 then
Add = ", " .. FAdmin.PlayerActions.ConvertBanTime((time / 10080 - math.floor(time / 10080)) * 10080)
end
return math.floor(time / 10080) .. " week(s)" .. Add
elseif time >= 525948 then
-- years
if math.floor((time / 525948 - math.floor(time / 525948)) * 525948) > 0 then
Add = ", " .. FAdmin.PlayerActions.ConvertBanTime((time / 525948 - math.floor(time / 525948)) * 525948)
end
return math.floor(time / 525948) .. " year(s)" .. Add
end
return time
end
FAdmin.StartHooks["kickbanning"] = function()
FAdmin.Messages.RegisterNotification{
name = "kick",
hasTarget = false,
message = {"instigator", " kicked ", "extraInfo.1", " (", "extraInfo.2", ")"},
receivers = "everyone",
writeExtraInfo = function(info)
net.WriteString(info[1])
net.WriteString(info[2])
end,
readExtraInfo = function()
return {net.ReadString(), net.ReadString()}
end,
extraInfoColors = {Color(102, 0, 255), Color(255, 102, 0)}
}
FAdmin.Messages.RegisterNotification{
name = "ban",
hasTarget = false,
message = {"instigator", " banned ", "extraInfo.1", " for ", "extraInfo.2", " (", "extraInfo.3", ")"},
receivers = "everyone",
writeExtraInfo = function(info)
net.WriteString(info[1])
net.WriteUInt(info[2], 32)
net.WriteString(info[3])
end,
readExtraInfo = function()
return {net.ReadString(), FAdmin.PlayerActions.ConvertBanTime(net.ReadUInt(32)), net.ReadString()}
end,
extraInfoColors = {Color(102, 0, 255), Color(255, 102, 0), Color(255, 102, 0)}
}
FAdmin.Messages.RegisterNotification{
name = "unban",
hasTarget = false,
message = {"instigator", " unbanned ", "extraInfo.1", " (", "extraInfo.2", ")"},
receivers = "everyone",
writeExtraInfo = function(info)
net.WriteString(info[1])
net.WriteString(info[2])
end,
readExtraInfo = function()
return {net.ReadString(), net.ReadString()}
end,
extraInfoColors = {Color(102, 0, 255), Color(255, 102, 0)}
}
end

View File

@@ -0,0 +1,328 @@
-- Kicking
local function Kick(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local CanKick = hook.Call("FAdmin_CanKick", nil, ply, targets)
if CanKick == false then return false end
local stage = args[2] or ""
stage = string.lower(stage)
local stages = {"start", "cancel", "update", "execute"}
local Reason = (not table.HasValue(stages, stage) and table.concat(args, ' ', 2)) or table.concat(args, ' ', 3) or ply.FAdminKickReason
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Kick", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) then
if stage == "start" then
SendUserMessage("FAdmin_kick_start", target) -- Tell him he's getting kicked
target:Lock() -- Make sure he can't remove the hook clientside and keep minging.
target:KillSilent()
elseif stage == "cancel" then
SendUserMessage("FAdmin_kick_cancel", target) -- No I changed my mind, you can stay
target:UnLock()
target:Spawn()
ply.FAdminKickReason = nil
elseif stage == "update" then -- Update reason text
if not args[3] then return false end
ply.FAdminKickReason = args[3]
SendUserMessage("FAdmin_kick_update", target, args[3])
else
local name = IsValid(ply) and ply:IsPlayer() and ply:Nick() or "Console"
Reason = Reason and string.gsub(Reason, ";", " ") or "No reason provided"
hook.Call("FAdmin_Kick", nil, ply, target, Reason)
game.ConsoleCommand(string.format("kickid %s %s\n", target:UserID(), "Kicked by " .. name ..
" (" .. Reason .. ")"))
ply.FAdminKickReason = nil
end
end
end
if stage ~= "start" and stage ~= "cancel" and stage ~= "update" then
FAdmin.Messages.FireNotification("kick", ply, nil, {FAdmin.TargetsToString(targets), Reason})
end
return true, targets, stage, Reason
end
local StartBannedUsers = {} -- Prevent rejoining before actual ban occurs
hook.Add("PlayerAuthed", "FAdmin_LeavingBeforeBan", function(ply, SteamID, ...)
if not StartBannedUsers[SteamID] then return end
if not IsValid(StartBannedUsers[SteamID].author) then
StartBannedUsers[SteamID] = nil
return
end
game.ConsoleCommand(string.format("kickid %s %s\n", ply:UserID(), "Getting banned"))
end)
-- Banning
FAdmin.BANS = FAdmin.BANS or {}
local function RequestBans(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "UnBan") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
net.Start("FAdmin_retrievebans")
net.WriteUInt(table.Count(FAdmin.BANS), 32)
for k, v in pairs(FAdmin.BANS) do
net.WriteString(k or "") -- SteamID
net.WriteUInt(v.time or 0, 32)
net.WriteString(v.name or "")
net.WriteString(v.reason or "")
net.WriteString(v.adminname or "")
net.WriteString(v.adminsteam or "")
end
net.Send(ply)
return true, FAdmin.BANS
end
timer.Create("FAdminCheckBans", 60, 0, function()
for k, v in pairs(FAdmin.BANS) do
if v.time and not isstring(v.time) and tonumber(v.time) < os.time() and v.time ~= 0 then
FAdmin.BANS[k] = nil
end
end
end)
local function SaveBan(SteamID, Nick, Duration, Reason, AdminName, Admin_steam)
local StoreBans = hook.Call("FAdmin_StoreBan", nil, SteamID, Nick, Duration, Reason, AdminName, Admin_steam)
if StoreBans == true then return end
if tonumber(Duration) == 0 then
FAdmin.BANS[SteamID] = {}
FAdmin.BANS[SteamID].time = 0
FAdmin.BANS[SteamID].name = Nick
FAdmin.BANS[SteamID].reason = Reason
FAdmin.BANS[SteamID].adminname = AdminName
FAdmin.BANS[SteamID].adminsteam = Admin_steam
else
FAdmin.BANS[SteamID] = {}
FAdmin.BANS[SteamID].time = os.time() + Duration * 60 --in minutes, so *60
FAdmin.BANS[SteamID].name = Nick
FAdmin.BANS[SteamID].reason = Reason
FAdmin.BANS[SteamID].adminname = AdminName
FAdmin.BANS[SteamID].adminsteam = Admin_steam
end
end
local function Ban(ply, cmd, args)
if not args[2] then return false end
--start cancel update execute
local targets = FAdmin.FindPlayer(args[1])
if not targets and string.find(args[1], "STEAM_") ~= 1 and string.find(args[2], "STEAM_") ~= 1 then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
elseif not targets and (string.find(args[1], "STEAM_") == 1 or string.find(args[2], "STEAM_") == 1) then
targets = {(args[1] ~= "execute" and args[1]) or args[2]}
if args[1] == "STEAM_0" then
targets[1] = table.concat(args, "", 1, 5)
args[1] = targets[1]
args[2] = args[6]
args[3] = args[7]
targets = FAdmin.FindPlayer(targets[1]) or targets
for i = 2, #args do
if i >= 4 then args[i] = nil end
end
end
end
local CanBan = hook.Call("FAdmin_CanBan", nil, ply, targets)
if CanBan == false then return false end
local stage = string.lower(args[2])
local stages = {"start", "cancel", "update", "execute"}
local Reason = (not table.HasValue(stages, stage) and table.concat(args, ' ', 3)) or table.concat(args, ' ', 4) or ply.FAdminKickReason
local time
for _, target in ipairs(targets) do
if (isstring(target) and not FAdmin.Access.PlayerHasPrivilege(ply, "Ban")) or
not FAdmin.Access.PlayerHasPrivilege(ply, "Ban", target) then
FAdmin.Messages.SendMessage(ply, 5, "No access!")
return false
end
if stage == "start" and not isstring(target) and IsValid(target) then
SendUserMessage("FAdmin_ban_start", target) -- Tell him he's getting banned
target:Lock() -- Make sure he can't remove the hook clientside and keep minging.
target:KillSilent()
StartBannedUsers[target:SteamID()] = {author = ply}
elseif stage == "cancel" then
if not isstring(target) and IsValid(target) then
SendUserMessage("FAdmin_ban_cancel", target) -- No I changed my mind, you can stay
target:UnLock()
target:Spawn()
StartBannedUsers[target:SteamID()] = nil
else -- If he left and you want to cancel
StartBannedUsers[args[1]] = nil
end
elseif stage == "update" then -- Update reason text
if not args[4] or isstring(target) or not IsValid(target) then return false end
ply.FAdminKickReason = args[4]
umsg.Start("FAdmin_ban_update", target)
umsg.Long(tonumber(args[3]))
umsg.String(tostring(args[4]))
umsg.End()
else
time = tonumber(args[2]) or 0
Reason = (Reason ~= "" and Reason) or args[3] or ""
if stage == "execute" then
time = tonumber(args[3]) or 60 --Default to one hour, not permanent.
Reason = args[4] or ""
end
local TimeText = FAdmin.PlayerActions.ConvertBanTime(time)
if not isstring(target) and IsValid(target) then
StartBannedUsers[target:SteamID()] = nil
local nick = ply.Nick and ply:Nick() or "console"
SaveBan(target:SteamID(), target:Nick(), time, Reason, nick, ply.SteamID and ply:SteamID() or "Console")
Reason = string.gsub(Reason, ";", " ")
target:Kick("banned by " .. nick .. " for " .. TimeText .. " (" .. Reason .. ")")
else
StartBannedUsers[args[1]] = nil
SaveBan(target, nil, time, Reason ~= "" and Reason, ply.Nick and ply:Nick() or "console", ply.SteamID and ply:SteamID() or "Console") -- Again default to one hour
end
ply.FAdminKickReason = nil
end
end
if stage ~= "start" and stage ~= "cancel" and stage ~= "update" then
FAdmin.Messages.FireNotification("ban", ply, nil, {FAdmin.TargetsToString(targets), time, Reason})
end
return true, targets, stage, Reason
end
-- Input validation: verify that a steam id is valid
local function isValidSteamId(steamId)
if steamId == "STEAM_ID_PENDING" then return true end
if steamId == "UNKNOWN" then return true end
if string.match(steamId, "^STEAM_[0-9]:[0-9]:[0-9]+$") then return true end
if string.match(steamId, "^[0-9]+$") then return true end
return false
end
-- Unbanning
local function UnBan(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "UnBan") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local steamID = string.upper(args[1])
if not isValidSteamId(steamID) then
FAdmin.Messages.SendMessage(ply, 5, "Player not found")
return false
end
local nick = "Unknown"
hook.Call("FAdmin_UnBan", nil, ply, steamID)
for k, v in pairs(FAdmin.BANS) do
if string.upper(k) == steamID then
nick = FAdmin.BANS[k].name or nick
FAdmin.BANS[k] = nil
break
end
end
StartBannedUsers[steamID] = nil
game.ConsoleCommand("removeid " .. steamID .. "\n")
FAdmin.Messages.FireNotification("unban", ply, nil, {nick, steamID})
return true, steamID
end
-- Commands and privileges
FAdmin.StartHooks["KickBan"] = function()
FAdmin.Commands.AddCommand("kick", Kick)
FAdmin.Commands.AddCommand("ban", Ban)
FAdmin.Commands.AddCommand("unban", UnBan)
FAdmin.Commands.AddCommand("RequestBans", RequestBans)
FAdmin.Access.AddPrivilege("Kick", 2)
FAdmin.Access.AddPrivilege("Ban", 2)
FAdmin.Access.AddPrivilege("UnBan", 2)
end
hook.Add("DarkRPDBInitialized", "FAdmin_Retrievebans", function()
timer.Simple(2, function()
local RetrieveBans = hook.Call("FAdmin_RetrieveBans", nil)
if RetrieveBans then
for k, v in pairs(RetrieveBans) do
FAdmin.BANS[string.upper(k)] = v
end
return
end
end)
if file.Exists("FAdmin/Bans.txt", "DATA") then
local bans = util.KeyValuesToTable(file.Read("FAdmin/bans.txt", "DATA") or {})
for k, v in pairs(bans) do
FAdmin.BANS[string.upper(k)] = v
end
for k, v in pairs(FAdmin.BANS) do
v.time = tonumber(v.time)
if v.time and v.time < os.time() then
FAdmin.BANS[string.upper(k)] = nil
continue
elseif not v.time then
continue
end
hook.Call("FAdmin_StoreBan", nil, string.upper(k), v.name, (v.time - os.time()) / 60, v.reason, v.adminname, v.adminsteam)
end
file.Delete("FAdmin/Bans.txt", "DATA")
end
end)
local function canJoin(steamID)
local ban = FAdmin.BANS[string.upper(steamID)]
if not ban then return end
if ban.time ~= 0 and ban.time < os.time() then
FAdmin.BANS[string.upper(steamID)] = nil
return
end
local timeText = FAdmin.PlayerActions.ConvertBanTime((ban.time - os.time()) / 60)
return false, "banned by " .. (ban.adminname or "<Unknown>") .. " for " .. timeText .. " (" .. (ban.reason or "no reason") .. ")"
end
hook.Add("CheckPassword", "FAdmin_Bans", fc{canJoin, util.SteamIDFrom64})
-- When the bans haven't loaded yet, or when the player passes
-- CheckPassword when banned, they'll be caught on InitialSpawn
hook.Add("PlayerInitialSpawn", "FAdmin_Bans", function(ply)
local allowedIn, reason = canJoin(ply:SteamID())
if allowedIn == false then
ply:Kick(reason)
end
end)
hook.Add("PlayerDisconnected", "FAdmin bans", function(ply)
for k,v in pairs(StartBannedUsers) do
if v.author ~= ply then continue end
StartBannedUsers[k] = nil
local target = player.GetBySteamID(k)
if not IsValid(target) then continue end
SendUserMessage("FAdmin_ban_cancel", target)
target:UnLock()
target:Spawn()
end
end)

View File

@@ -0,0 +1,77 @@
local function MessageGui(ply)
if not FAdmin.Messages or not FAdmin.Messages.MsgTypes then return end
local frame = vgui.Create("DFrame")
frame:SetTitle("Send message")
frame:SetSize(350, 170)
frame:Center()
frame:SetVisible(true)
frame:MakePopup()
local MsgType = 2
local i = 0
local TypeButtons = {}
local MsgTypeNames = {ERROR = 1, NOTIFY = 2, QUESTION = 3, GOOD = 4, BAD = 5}
for k, v in pairs(FAdmin.Messages.MsgTypes) do
local MsgTypeButton = vgui.Create("DCheckBox", frame)
MsgTypeButton:SetPos(20 + i * 64, 46)
if k == "NOTIFY" then MsgTypeButton:SetValue(true) end
function MsgTypeButton:DoClick()
for _, B in pairs(TypeButtons) do B:SetValue(false) end
self:SetValue(true)
MsgType = MsgTypeNames[k]
end
local Icon = vgui.Create("DImageButton", frame)
Icon:SetImage(v.TEXTURE)
Icon:SetPos(20 + i * 64 + 16, 30)
Icon:SetSize(32, 32)
function Icon:DoClick()
for _, B in pairs(TypeButtons) do B:SetValue(false) end
MsgTypeButton:SetValue(true)
MsgType = MsgTypeNames[k]
end
table.insert(TypeButtons, MsgTypeButton)
i = i + 1
end
local OK = vgui.Create("DButton", frame)
local TextBox = vgui.Create("DTextEntry", frame)
TextBox:SetPos(20, 100)
TextBox:StretchToParent(20, nil, 20, nil)
TextBox:RequestFocus()
function TextBox:Think() -- Most people are holding tab when they open this window. Get focus back!
TextBox.InTab = TextBox.InTab or input.IsKeyDown(KEY_TAB)
if TextBox.InTab and not input.IsKeyDown(KEY_TAB) then self:RequestFocus() end
end
function TextBox:OnEnter()
OK:DoClick()
end
OK:SetSize(100, 20)
OK:SetText("OK")
OK:AlignRight(20)
OK:AlignBottom(20)
function OK:DoClick()
frame:Close()
if not IsValid(ply) then return end
RunConsoleCommand("_FAdmin", "Message", ply:SteamID(), MsgType, TextBox:GetValue())
end
end
FAdmin.StartHooks["zzSendMessage"] = function()
FAdmin.Access.AddPrivilege("Message", 1)
FAdmin.Commands.AddCommand("Message", nil, "<Player>", "[type]", "<text>")
FAdmin.ScoreBoard.Player:AddActionButton("Send message", "fadmin/icons/message", Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Message") and not ply:IsBot() end, function(ply, button)
MessageGui(ply)
end
)
end

View File

@@ -0,0 +1,37 @@
local function DoMessage(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Message") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[2] then return false end
ply.FAdmin_LastMessageTime = ply.FAdmin_LastMessageTime or CurTime() - 2
if ply.FAdmin_LastMessageTime > (CurTime() - 2) then
FAdmin.Messages.SendMessage(ply, 5, "Wait before sending a new message")
return false
end
ply.FAdmin_LastMessageTime = CurTime()
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) or not args[3] then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local MsgType = tonumber(args[2]) or 2
for _, target in ipairs(targets) do
if IsValid(target) then
FAdmin.Messages.SendMessage(target, MsgType, ply:Nick() .. ": " .. args[3])
end
end
if ply ~= targets[1] then
FAdmin.Messages.SendMessage(ply, MsgType, ply:Nick() .. ": " .. args[3])
end
return true, targets, MsgType, args[3]
end
FAdmin.StartHooks["DoMessage"] = function()
FAdmin.Commands.AddCommand("Message", DoMessage)
FAdmin.Access.AddPrivilege("Message", 1) -- Anyone can send messages. Why not?
end

View File

@@ -0,0 +1,51 @@
local sbox_noclip = GetConVar("sbox_noclip")
local function EnableDisableNoclip(ply)
return ply:FAdmin_GetGlobal("FADmin_CanNoclip") or
((FAdmin.Access.PlayerHasPrivilege(ply, "Noclip") or sbox_noclip:GetBool())
and not ply:FAdmin_GetGlobal("FADmin_DisableNoclip"))
end
FAdmin.StartHooks["zz_Noclip"] = function()
FAdmin.Messages.RegisterNotification{
name = "noclipenable",
hasTarget = true,
message = {"instigator", " enabled noclip for ", "targets"},
}
FAdmin.Messages.RegisterNotification{
name = "noclipdisable",
hasTarget = true,
message = {"instigator", " disabled noclip for ", "targets"},
}
FAdmin.Access.AddPrivilege("Noclip", 2)
FAdmin.Access.AddPrivilege("SetNoclip", 2)
FAdmin.Commands.AddCommand("SetNoclip", nil, "<Player>", "<Toggle 1/0>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if EnableDisableNoclip(ply) then
return "Disable noclip"
end
return "Enable noclip"
end, function(ply) return "fadmin/icons/noclip", EnableDisableNoclip(ply) and "fadmin/icons/disable" end, Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "SetNoclip") end, function(ply, button)
if EnableDisableNoclip(ply) then
RunConsoleCommand("_FAdmin", "SetNoclip", ply:UserID(), 0)
else
RunConsoleCommand("_FAdmin", "SetNoclip", ply:UserID(), 1)
end
if EnableDisableNoclip(ply) then
button:SetText("Enable noclip")
button:SetImage2("null")
button:GetParent():InvalidateLayout()
return
end
button:SetText("Disable noclip")
button:SetImage2("fadmin/icons/disable")
button:GetParent():InvalidateLayout()
end)
end

View File

@@ -0,0 +1,42 @@
local sbox_noclip = GetConVar("sbox_noclip")
local function sendNoclipMessage(ply)
if not SERVER or ply.FADmin_HasGotNoclipMessage then return end
FAdmin.Messages.SendMessage(ply, 4, "Noclip allowed")
ply.FADmin_HasGotNoclipMessage = true
end
hook.Add("PlayerNoClip", "FAdmin_noclip", function(ply)
if ply:FAdmin_GetGlobal("FADmin_DisableNoclip") then
if SERVER then
FAdmin.Messages.SendMessage(ply, 5, "Noclip disallowed!")
end
return false
end
-- No further judgement when sbox_noclip is on
if sbox_noclip:GetBool() then return end
if ply:FAdmin_GetGlobal("FADmin_CanNoclip") then
sendNoclipMessage(ply)
return true
end
if not ply:Alive() then return end
-- Has privilege
if not FAdmin.Access.PlayerHasPrivilege(ply, "Noclip") then return end
-- Disallow if other hooks say no
for k, v in pairs(hook.GetTable().PlayerNoClip) do
if k == "FAdmin_noclip" then continue end
if v(ply) == false then return false end
end
sendNoclipMessage(ply)
return true
end)

View File

@@ -0,0 +1,60 @@
local function SetNoclip(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "SetNoclip") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local Toggle = tobool(tonumber(args[2])) or false
for _, target in ipairs(targets) do
if IsValid(target) then
if Toggle then
target:FAdmin_SetGlobal("FADmin_CanNoclip", true)
target:FAdmin_SetGlobal("FADmin_DisableNoclip", false)
if not FAdmin.Access.PlayerHasPrivilege(target, "Noclip") then
FAdmin.Messages.SendMessage(ply, 3, "This is not permanent! Make it permanent with a custom group in SetAccess!")
end
else
target:FAdmin_SetGlobal("FADmin_CanNoclip", false)
target:FAdmin_SetGlobal("FADmin_DisableNoclip", true)
if target:GetMoveType() == MOVETYPE_NOCLIP then
target:SetMoveType(MOVETYPE_WALK)
end
end
end
end
if Toggle then
FAdmin.Messages.FireNotification("noclipenable", ply, targets)
else
FAdmin.Messages.FireNotification("noclipdisable", ply, targets)
end
return true, targets, Toggle
end
FAdmin.StartHooks["zz_Noclip"] = function()
FAdmin.Messages.RegisterNotification{
name = "noclipenable",
hasTarget = true,
receivers = "involved",
message = {"instigator", " enabled noclip for ", "targets"},
}
FAdmin.Messages.RegisterNotification{
name = "noclipdisable",
hasTarget = true,
receivers = "involved",
message = {"instigator", " disabled noclip for ", "targets"},
}
FAdmin.Access.AddPrivilege("Noclip", 2)
FAdmin.Access.AddPrivilege("SetNoclip", 2)
FAdmin.Commands.AddCommand("SetNoclip", SetNoclip)
end

View File

@@ -0,0 +1,59 @@
FAdmin.StartHooks["Ragdoll"] = function()
FAdmin.Access.AddPrivilege("Ragdoll", 2)
FAdmin.Commands.AddCommand("Ragdoll", nil, "<Player>", "[normal/hang/kick]")
FAdmin.Commands.AddCommand("UnRagdoll", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("fadmin_ragdolled") then return "Unragdoll" end
return "Ragdoll"
end,
function(ply)
if ply:FAdmin_GetGlobal("fadmin_ragdolled") then return "fadmin/icons/ragdoll", "fadmin/icons/disable" end
return "fadmin/icons/ragdoll"
end,
Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Ragdoll", ply) end,
function(ply, button)
if ply:FAdmin_GetGlobal("fadmin_ragdolled") then
RunConsoleCommand("_FAdmin", "unragdoll", ply:UserID())
button:SetImage2("null")
button:SetText("Ragdoll")
button:GetParent():InvalidateLayout()
return end
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Ragdoll Type:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for k, v in ipairs(FAdmin.PlayerActions.RagdollTypes) do
if v == "Unragdoll" then continue end
FAdmin.PlayerActions.addTimeSubmenu(menu, v,
function()
RunConsoleCommand("_FAdmin", "Ragdoll", ply:UserID(), k)
button:SetImage2("fadmin/icons/disable")
button:SetText("Unragdoll")
button:GetParent():InvalidateLayout()
end,
function(secs)
RunConsoleCommand("_FAdmin", "Ragdoll", ply:UserID(), k, secs)
button:SetImage2("fadmin/icons/disable")
button:SetText("Unragdoll")
button:GetParent():InvalidateLayout()
end
)
end
menu:Open()
end)
end

View File

@@ -0,0 +1,31 @@
-- lua_Run A = Player(5):GetEyeTrace().Entity
-- lua_run for i = 1, A:GetPhysicsObjectCount() do B = A:WorldToLocal(A:GetPhysicsObjectNum(i):GetPos()) print("Vector("..B.x..", "..B.y..", "..B.z.."),") end
-- lua_run for i = 1, A:GetPhysicsObjectCount() do B = A:GetPhysicsObjectNum(i):GetAngle() print("Angle("..B.p..", "..B.y..", "..B.r.."),") end
FAdmin.PlayerActions.RagdollTypes = {
[1] = "Normal",
[2] = "Kick them in the nuts",
[3] = "Hang",
[4] = "Unragdoll"
}
FAdmin.StartHooks["Ragdolling"] = function()
FAdmin.Messages.RegisterNotification{
name = "ragdoll",
hasTarget = true,
message = {"instigator", " ragdolled ", "targets", " ", "extraInfo.1"},
receivers = "involved+admins",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
readExtraInfo = function()
local time = net.ReadUInt(16)
return {time == 0 and FAdmin.PlayerActions.commonTimes[time] or string.format("for %s", FAdmin.PlayerActions.commonTimes[time] or (time .. " seconds"))}
end
}
FAdmin.Messages.RegisterNotification{
name = "unragdoll",
hasTarget = true,
message = {"instigator", " unragdolled ", "targets"},
receivers = "involved+admins",
}
end

View File

@@ -0,0 +1,333 @@
local HangProps = {
[1] = {model = "models/props_docks/dock02_pole02a_256.mdl", pos = Vector(100, 0, 39), ang = Angle(0,0,0)},
[2] = {model = "models/props_docks/dock01_pole01a_128.mdl", pos = Vector(43, 0, 135), ang = Angle(0, -90, 90)}
}
local VictimPos1 = {
Vector(0.08349609375, 4.9041748046875, 10.35856628418),
Vector(-7.62841796875, 2.5777587890625, 19.235778808594),
Vector(7.866943359375, 3.7470703125, 19.656280517578),
Vector(9.823974609375, 2.7562255859375, 8.1713256835938),
Vector(10.78173828125, -0.431640625, -2.8172454833984),
Vector(-9.223876953125, 2.2598876953125, 7.7528839111328),
Vector(-10.81884765625, -2.521240234375, -2.6094360351563),
Vector(-4.3515625, 0.2113037109375, -0.05419921875),
Vector(-7.78466796875, -0.5653076171875, -17.549179077148),
Vector(0.08544921875, 1.6834716796875, 25.412673950195),
Vector(4.400390625, -0.2120361328125, 0.064102172851563),
Vector(6.23095703125, -0.237548828125, -17.736618041992),
Vector(8.871337890625, 1.25146484375, -33.981475830078),
Vector(-9.429443359375, 2.0859375, -33.777191162109)
}
local VictimAng1 = {
Angle(-87.673042297363, -109.66005706787, 294.1647644043),
Angle(82.838233947754, -165.22711181641, 201.99559020996),
Angle(79.187240600586, -26.850950241089, 355.43997192383),
Angle(73.147010803223, -73.275413513184, 310.1682434082),
Angle(80.774833679199, -150.97926330566, 325.01263427734),
Angle(63.71996307373, -112.01448822021, 253.77954101563),
Angle(77.913925170898, -69.091110229492, 173.12385559082),
Angle(78.631988525391, -167.21780395508, 216.82838439941),
Angle(79.116714477539, 121.81723022461, 146.85758972168),
Angle(-89.117118835449, 92.446853637695, 267.04473876953),
Angle(83.278358459473, -2.6300358772278, 12.258254051208),
Angle(79.429931640625, 29.419277191162, 43.093002319336),
Angle(37.975448608398, -70.136756896973, 293.39251708984),
Angle(42.589946746826, -95.914726257324, 258.73498535156)
}
-- Kick leg = 9 and 14
local KickerPos = {
Vector(0.151123046875, -0.55889892578125, 12.428649902344),
Vector(-6.949951171875, -4.727294921875, 21.128128051758),
Vector(8.18798828125, -4.1649780273438, 20.041198730469),
Vector(12.109619140625, 6.8145751953125, 19.155548095703),
Vector(8.816162109375, 16.727844238281, 14.390106201172),
Vector(-10.9814453125, -12.980773925781, 13.879943847656),
Vector(-7.9189453125, -24.001403808594, 14.877258300781),
Vector(-4.06396484375, 0.56243896484375, -0.14239501953125),
Vector(-0.764404296875, 15.5107421875, -9.5738525390625),
Vector(1.176025390625, -7.4561767578125, 26.153648376465),
Vector(3.85009765625, -0.55645751953125, -0.035125732421875),
Vector(5.841796875, -1.1864624023438, -17.723190307617),
Vector(4.7431640625, 4.4840698242188, -33.206146240234),
Vector(0.028076171875, 27.153869628906, 2.1262817382813)
}
local KickerAng = {
Angle(-72.853500366211, -77.192611694336, 258.47763061523),
Angle(38.269737243652, -116.13293457031, 218.30332946777),
Angle(4.3439903259277, 70.343925476074, 147.32099914551),
Angle(24.522411346436, 108.37782287598, 157.29452514648),
Angle(15.059949874878, 50.6491355896, 180.38879394531),
Angle(-4.983060836792, -74.469413757324, 230.35047912598),
Angle(1.2094515562057, -73.130561828613, 136.18098449707),
Angle(32.704917907715, 77.20344543457, 82.96809387207),
Angle(-45.073616027832, 86.105369567871, 82.506660461426),
Angle(-79.46248626709, -65.311363220215, 68.129730224609),
Angle(82.879898071289, -27.148105621338, 318.85842895508),
Angle(69.541847229004, 100.96334838867, 80.36100769043),
Angle(31.048385620117, -61.657707214355, 279.41061401367),
Angle(-19.616451263428, 81.610832214355, 87.282814025879)
}
local function unragdoll(target)
timer.Remove(target:SteamID() .. "FAdminRagdoll")
target:FAdmin_SetGlobal("fadmin_ragdolled", false)
target:UnSpectate()
target:Spawn()
if not istable(target.FAdminRagdoll) and IsValid(target.FAdminRagdoll) then
if target.FAdminRagdoll.SetCanRemove then target.FAdminRagdoll:SetCanRemove(true) end
target.FAdminRagdoll:Remove()
elseif istable(target.FAdminRagdoll) then
for _, v in pairs(target.FAdminRagdoll) do
if not IsValid(v) then continue end
if v.SetCanRemove then v:SetCanRemove(true) end
v:Remove()
end
end
target.FAdminRagdoll = nil
end
local function ragdollKick(target)
if istable(target.FAdminRagdoll) or IsValid(target.FAdminRagdoll) then return false end
local doll = ents.Create("prop_ragdoll")
doll:SetModel(target:GetModel())
doll:SetPos(target:GetPos())
doll:Spawn()
doll:Activate()
-- The rotation angle (the direction the ragdoll is looking at)
local angle = Angle(0, target:EyeAngles().y + 90, 0)
for i = 1, doll:GetPhysicsObjectCount() do
local phys = doll:GetPhysicsObjectNum(i)
if phys and phys:IsValid() and VictimPos1[i] then
phys:EnableMotion(false)
-- Copy the vector
local pos = Vector(VictimPos1[i].x, VictimPos1[i].y, VictimPos1[i].z)
pos:Rotate(angle)
phys:SetPos(pos + doll:GetPos())
phys:SetAngles(VictimAng1[i] + angle)
end
end
-- The kicker's position is behind the target with distance 35, translated to stand a bit higher
local aimVec = Vector(target:GetAimVector().x, target:GetAimVector().y, 0)
local kickerPos = target:GetPos() - aimVec * 35 + Vector(0, 0, 5)
local Kicker = ents.Create("prop_ragdoll")
Kicker:SetModel("models/Police.mdl")
Kicker:SetPos(kickerPos)
Kicker:Spawn()
Kicker:Activate()
Kicker:EmitSound("npc/combine_soldier/vo/contactconfirmprosecuting.wav", 100, 100)
for i = 1, Kicker:GetPhysicsObjectCount() do
local phys = Kicker:GetPhysicsObjectNum(i)
if phys and phys:IsValid() then
phys:EnableMotion(false)
if i == 8 or i == 9 or i == 14 then
phys:EnableCollisions(false)
timer.Simple(2, function()
if phys:IsValid() then
phys:EnableMotion(true)
phys:Wake()
phys:SetVelocity(aimVec - Vector(0, 0, 1000))
end
end)
end
local pos = Vector(KickerPos[i].x, KickerPos[i].y, KickerPos[i].z)
pos:Rotate(angle)
phys:SetPos(pos + Kicker:GetPos())
phys:SetAngles(KickerAng[i] + angle)
end
end
target:StripWeapons()
target:Spectate(OBS_MODE_CHASE)
target:SpectateEntity(doll)
target.FAdminRagdoll = doll
timer.Simple(2.1, function() if IsValid(doll) then
doll:EmitSound("physics/body/body_medium_impact_hard6.wav", 100, 100)
for i = 1, doll:GetPhysicsObjectCount() do
local phys = doll:GetPhysicsObjectNum(i)
if phys and phys:IsValid() then
phys:EnableCollisions(false)
phys:EnableMotion(true)
phys:SetVelocity((aimVec:GetNormalized() + Vector(0, 0, 1)) * 1000)
end
end
end end)
timer.Simple(2.2, function() if IsValid(doll) then
for i = 1, doll:GetPhysicsObjectCount() do
local phys = doll:GetPhysicsObjectNum(i)
if phys and phys:IsValid() then
phys:EnableCollisions(true)
end
end
end end)
timer.Simple(5, function()
if IsValid(Kicker) then
Kicker:Remove()
end
end)
end
local function Ragdoll(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local RagdollType = string.lower(FAdmin.PlayerActions.RagdollTypes[tonumber(args[2])] or args[2] or cmd)
local time = tonumber(args[3]) or 0
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Ragdoll", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not IsValid(target) then continue end
if RagdollType == "unragdoll" or string.lower(cmd) == "unragdoll" and target:FAdmin_GetGlobal("fadmin_ragdolled") then
unragdoll(target)
elseif RagdollType == "normal" or RagdollType == "ragdoll" then
if istable(target.FAdminRagdoll) or IsValid(target.FAdminRagdoll) then return false end
local doll = ents.Create("prop_ragdoll")
doll:SetModel(target:GetModel())
doll:SetPos(target:GetPos())
doll:SetAngles(target:GetAngles())
doll:Spawn()
doll:Activate()
target:StripWeapons()
target:Spectate(OBS_MODE_CHASE)
target:SpectateEntity(doll)
target.FAdminRagdoll = doll
elseif RagdollType == "hang" then
if istable(target.FAdminRagdoll) or IsValid(target.FAdminRagdoll) then return false end
target.FAdminRagdoll = {}
local doll = ents.Create("prop_ragdoll")
doll:SetModel(target:GetModel())
doll:SetPos(target:GetPos())
doll:SetAngles(target:GetAngles())
doll:Spawn()
doll:Activate()
table.insert(target.FAdminRagdoll, doll)
target:StripWeapons()
target:Spectate(OBS_MODE_CHASE)
target:SpectateEntity(doll)
local HangOn
for k,v in ipairs(HangProps) do
local prop = ents.Create("fadmin_jail")
prop.target = prop
prop:SetModel(v.model)
prop:SetPos(v.pos + target:GetPos())
prop:SetAngles(v.ang)
prop:Spawn()
prop:Activate()
local phys = prop:GetPhysicsObject()
if IsValid(phys) then phys:EnableMotion(false) end
table.insert(target.FAdminRagdoll, prop)
HangOn = prop -- Hang on the last prop
end
if not HangOn then return false end
doll:SetPos(HangOn:GetPos() - Vector(-50,0,10))
timer.Simple(0.2, function() constraint.Rope(doll, HangOn, 10, 0, Vector(-2.4,0,-0.6), Vector(0,0,53), 10, 40, 0, 4, "cable/rope", false) end)
elseif string.find(RagdollType, "kick") == 1 then -- Best ragdoll mod EVER
ragdollKick(target)
end
if time ~= 0 then
timer.Create(target:SteamID() .. "FAdminRagdoll", time, 1, function()
if not IsValid(target) then return end
if IsValid(target.FAdminRagdoll) then
target:SetPos(target.FAdminRagdoll:GetPos())
target.FAdminRagdoll:Remove()
elseif istable(target.FAdminRagdoll) then
for k, v in pairs(target.FAdminRagdoll) do SafeRemoveEntity(v) end
end
target:UnSpectate()
target:Spawn()
target.FAdminRagdoll = nil
target:FAdmin_SetGlobal("fadmin_ragdolled", false)
end)
end
if RagdollType ~= "unragdoll" and string.lower(cmd) ~= "unragdoll" then
target:FAdmin_SetGlobal("fadmin_ragdolled", true)
end
end
if RagdollType == "unragdoll" or string.lower(cmd) == "unragdoll" then
FAdmin.Messages.FireNotification("unragdoll", ply, targets)
else
FAdmin.Messages.FireNotification("ragdoll", ply, targets, {time})
end
return true, targets, RagdollType, time
end
FAdmin.StartHooks["Ragdoll"] = function()
FAdmin.Commands.AddCommand("Ragdoll", Ragdoll)
FAdmin.Commands.AddCommand("UnRagdoll", Ragdoll)
FAdmin.Access.AddPrivilege("Ragdoll", 2)
end
hook.Add("PlayerSpawnObject", "FAdmin_ragdoll", function(ply)
if istable(ply.FAdminRagdoll) or IsValid(ply.FAdminRagdoll) then
return false
end
end)
hook.Add("CanPlayerSuicide", "FAdmin_ragdoll", function(ply)
if istable(ply.FAdminRagdoll) or IsValid(ply.FAdminRagdoll) then
return false
end
end)
hook.Add("PlayerDeath", "FAdmin_ragdoll", function(ply)
if (istable(ply.FAdminRagdoll) or IsValid(ply.FAdminRagdoll)) and IsValid(ply:GetRagdollEntity()) then
ply:GetRagdollEntity():Remove()
end
end)
hook.Add("PlayerDeathThink", "FAdmin_ragdoll", function(ply)
if istable(ply.FAdminRagdoll) or IsValid(ply.FAdminRagdoll) then
return false
end
end)
hook.Add("PlayerDisconnected", "FAdmin_ragdoll", function(ply)
if not ply.FAdminRagdoll then return end
if IsValid(ply.FAdminRagdoll) then
ply.FAdminRagdoll:Remove()
return
end
if not istable(ply.FAdminRagdoll) then return end
for _, v in pairs(ply.FAdminRagdoll or {}) do
if IsValid(v) then v:Remove() end
end
end)

View File

@@ -0,0 +1,53 @@
local Damages = {0, 1, 10, 50, 100, 500, 9999999--[[for the 12-year-olds]]}
local Repetitions = {[1] = "once", [5] = "5 times", [10] = "10 times", [50] = "50 times", [100] = "100 times"}
FAdmin.StartHooks["Slap"] = function()
FAdmin.Messages.RegisterNotification{
name = "slap",
hasTarget = true,
message = {"instigator", " slapped ", "targets"},
}
FAdmin.Access.AddPrivilege("Slap", 2)
FAdmin.Commands.AddCommand("Slap", nil, "<Player>", "[Amount]", "[Repetitions]")
-- Right click option
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Slap", function(ply)
RunConsoleCommand("_FAdmin", "Slap", ply:UserID())
end)
-- Slap option in player menu
FAdmin.ScoreBoard.Player:AddActionButton("Slap", "fadmin/icons/slap", Color(255, 130, 0, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Slap", ply) end, function(ply)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Damage:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for _, v in ipairs(Damages) do
local SubMenu = menu:AddSubMenu(v, function() RunConsoleCommand("_FAdmin", "slap", ply:UserID(), v) end)
local SubMenuTitle = vgui.Create("DLabel")
SubMenuTitle:SetText(" " .. v .. " damage\n")
SubMenuTitle:SetFont("UiBold")
SubMenuTitle:SizeToContents()
SubMenuTitle:SetTextColor(color_black)
SubMenu:AddPanel(SubMenuTitle)
for reps, Name in SortedPairs(Repetitions) do
local uid = ply:UserID()
SubMenu:AddOption(Name, function() RunConsoleCommand("_FAdmin", "slap", uid, v, reps) end)
end
end
menu:Open()
end)
end

View File

@@ -0,0 +1,63 @@
local function ExecuteSlap(target, Amount, ply)
if not IsValid(target) or not IsValid(ply) then return end
local Force = Vector(math.Rand(-500, 500), math.Rand(-500, 500), math.Rand(-100, 700))
local DmgInfo = DamageInfo()
DmgInfo:SetDamage(Amount)
DmgInfo:SetDamageType(DMG_DROWN)
DmgInfo:SetAttacker(ply)
DmgInfo:SetDamageForce(Force)
target:TakeDamageInfo(DmgInfo)
target:SetVelocity(Force)
end
local function Slap(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local Amount = DarkRP.toInt(args[2]) or 10
local Repetitions = DarkRP.toInt(args[3])
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Slap", target) then
FAdmin.Messages.SendMessage(ply, 5, "No access!")
return false
end
if IsValid(target) then
if not Repetitions or Repetitions == 1 then
ExecuteSlap(target, Amount, ply)
else
for i = 1, Repetitions, 1 do
timer.Simple(i * 0.7, function()
ExecuteSlap(target, Amount, ply)
end)
end
end
end
end
FAdmin.Messages.FireNotification("slap", ply, targets)
return true, targets, Amount, Repetitions
end
FAdmin.StartHooks["Slap"] = function()
FAdmin.Messages.RegisterNotification{
name = "slap",
hasTarget = true,
receivers = "involved+admins",
message = {"instigator", " slapped ", "targets"},
}
FAdmin.Commands.AddCommand("Slap", Slap)
FAdmin.Access.AddPrivilege("Slap", 2)
end

View File

@@ -0,0 +1,35 @@
FAdmin.StartHooks["Slay"] = function()
FAdmin.Access.AddPrivilege("Slay", 2)
FAdmin.Commands.AddCommand("Slay", nil, "<Player>", "[Normal/Silent/Explode/Rocket]")
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Slay", function(ply)
RunConsoleCommand("_FAdmin", "slay", ply:UserID())
end)
FAdmin.ScoreBoard.Player:AddActionButton("Slay", "fadmin/icons/slay", Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Slay", ply) end,
function(ply)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Kill Type:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
for k, v in ipairs(FAdmin.PlayerActions.SlayTypes) do
local uid = ply:UserID()
menu:AddOption(v, function()
RunConsoleCommand("_FAdmin", "slay", uid, k)
end)
end
menu:Open()
end)
end

View File

@@ -0,0 +1,14 @@
FAdmin.PlayerActions.SlayTypes = {}
FAdmin.PlayerActions.SlayTypes[1] = "Normal"
FAdmin.PlayerActions.SlayTypes[2] = "Silent"
FAdmin.PlayerActions.SlayTypes[3] = "Explode"
FAdmin.PlayerActions.SlayTypes[4] = "Rocket"
FAdmin.StartHooks["Slaying"] = function()
FAdmin.Messages.RegisterNotification{
name = "slay",
hasTarget = true,
message = {"instigator", " slayed ", "targets"},
receivers = "involved+admins",
}
end

View File

@@ -0,0 +1,52 @@
local function Slay(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local SlayType = string.lower(FAdmin.PlayerActions.SlayTypes[tonumber(args[2])] or args[2] or "Normal")
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Slay", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) then
if SlayType == "normal" then
target:Kill()
elseif SlayType == "silent" then
target:KillSilent()
elseif SlayType == "explode" then
local effectdata = EffectData()
effectdata:SetStart(target:GetPos())
effectdata:SetOrigin(target:GetPos())
effectdata:SetScale(3)
util.Effect("HelicopterMegaBomb", effectdata)
target:EmitSound("ambient/explosions/explode_1.wav", 100, 100)
target:SetVelocity(Vector(math.Rand(-500, 500), math.Rand(-500, 500), math.Rand(200, 700)))
target:Kill()
elseif SlayType == "rocket" then
target:SetVelocity(Vector(0,0,1000))
timer.Simple(1, function()
local effectdata = EffectData()
effectdata:SetStart(target:GetPos())
effectdata:SetOrigin(target:GetPos())
effectdata:SetScale(3)
util.Effect("HelicopterMegaBomb", effectdata)
target:EmitSound("ambient/explosions/explode_1.wav", 100, 100)
target:SetVelocity(Vector(math.Rand(-500, 500), math.Rand(-500, 500), math.Rand(200, 700)))
target:Kill()
end)
end
end
end
FAdmin.Messages.FireNotification("slay", ply, targets)
return true, targets, SlayType
end
FAdmin.StartHooks["Slay"] = function()
FAdmin.Commands.AddCommand("Slay", Slay)
FAdmin.Access.AddPrivilege("Slay", 2)
end

View File

@@ -0,0 +1,16 @@
FAdmin.StartHooks["StripWeapons"] = function()
FAdmin.Messages.RegisterNotification{
name = "stripweapons",
hasTarget = true,
message = {"instigator", " stripped the weapons of ", "targets"},
}
FAdmin.Access.AddPrivilege("StripWeapons", 2)
FAdmin.Commands.AddCommand("StripWeapons", nil, "<Player>")
FAdmin.Commands.AddCommand("Strip", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton("Strip weapons", {"fadmin/icons/weapon", "fadmin/icons/disable"}, Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "StripWeapons", ply) end, function(ply, button)
RunConsoleCommand("_FAdmin", "StripWeapons", ply:UserID())
end)
end

View File

@@ -0,0 +1,32 @@
local function StripWeapons(ply, cmd, args)
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "StripWeapons", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) then
target:StripWeapons()
end
end
FAdmin.Messages.FireNotification("stripweapons", ply, targets)
return true, targets
end
FAdmin.StartHooks["StripWeapons"] = function()
FAdmin.Messages.RegisterNotification{
name = "stripweapons",
hasTarget = true,
receivers = "involved+admins",
message = {"instigator", " stripped the weapons of ", "targets"},
}
FAdmin.Commands.AddCommand("StripWeapons", StripWeapons)
FAdmin.Commands.AddCommand("Strip", StripWeapons)
FAdmin.Access.AddPrivilege("StripWeapons", 2)
end

View File

@@ -0,0 +1,63 @@
FAdmin.StartHooks["zz_Teleport"] = function()
FAdmin.Messages.RegisterNotification{
name = "goto",
hasTarget = true,
message = {"instigator", " teleported to ", "targets"}
}
FAdmin.Messages.RegisterNotification{
name = "bring",
hasTarget = true,
message = {"instigator", " brought ", "targets", " to them"}
}
FAdmin.Access.AddPrivilege("Teleport", 2)
FAdmin.Commands.AddCommand("Teleport", nil, "[Player]")
FAdmin.Commands.AddCommand("TP", nil, "[Player]")
FAdmin.Commands.AddCommand("Bring", nil, "<Player>", "[Player]")
FAdmin.Commands.AddCommand("goto", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton("Teleport", "fadmin/icons/teleport", Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Teleport") end,
function(ply, button)
RunConsoleCommand("_FAdmin", "Teleport", ply:UserID())
end)
FAdmin.ScoreBoard.Player:AddActionButton("Goto", "fadmin/icons/teleport", Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Teleport") and ply ~= LocalPlayer() end,
function(ply, button)
RunConsoleCommand("_FAdmin", "goto", ply:UserID())
end)
FAdmin.ScoreBoard.Player:AddActionButton("Bring", "fadmin/icons/teleport", Color(0, 200, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Teleport") and ply ~= LocalPlayer() end,
function(ply, button)
local menu = DermaMenu()
local Padding = vgui.Create("DPanel")
Padding:SetPaintBackgroundEnabled(false)
Padding:SetSize(1,5)
menu:AddPanel(Padding)
local Title = vgui.Create("DLabel")
Title:SetText(" Bring to:\n")
Title:SetFont("UiBold")
Title:SizeToContents()
Title:SetTextColor(color_black)
menu:AddPanel(Title)
local uid = ply:UserID()
menu:AddOption("Yourself", function() RunConsoleCommand("_FAdmin", "bring", uid) end)
for _, v in ipairs(DarkRP.nickSortedPlayers()) do
if IsValid(v) and v ~= LocalPlayer() then
local vUid = v:UserID()
menu:AddOption(v:Nick(), function() RunConsoleCommand("_FAdmin", "bring", uid, vUid) end)
end
end
menu:Open()
end)
end

View File

@@ -0,0 +1,169 @@
local function zapEffect(target)
local effectdata = EffectData()
effectdata:SetStart(target:GetShootPos())
effectdata:SetOrigin(target:GetShootPos())
effectdata:SetScale(1)
effectdata:SetMagnitude(1)
effectdata:SetScale(3)
effectdata:SetRadius(1)
effectdata:SetEntity(target)
for i = 1, 100, 1 do
timer.Simple(1 / i, function()
util.Effect("TeslaHitBoxes", effectdata, true, true)
end)
end
local Zap = math.random(1,9)
if Zap == 4 then Zap = 3 end
target:EmitSound("ambient/energy/zap" .. Zap .. ".wav")
end
local function TPToPos(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Teleport") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local x, y, z = string.match(args[1] or "", "([-0-9\\.]+),%s?([-0-9\\.]+),%s?([-0-9\\.]+)")
local vx, vy, vz = string.match(args[2] or "", "([-0-9\\.]+),%s?([-0-9\\.]+),%s?([-0-9\\.]+)")
local pos = Vector(tonumber(x), tonumber(y), tonumber(z))
local vel = Vector(tonumber(vx), tonumber(vy), tonumber(vz))
if not args[1] or not x or not y or not z then return false end
ply:SetPos(pos)
if vx and vy and vz then ply:SetVelocity(vel) end
zapEffect(ply)
return true, pos, vel
end
local function Teleport(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Teleport") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
targets = {ply}
end
for _, target in ipairs(targets) do
if IsValid(target) and target:Alive() then
target:ExitVehicle()
local tracedata = {}
tracedata.start = ply:GetShootPos()
tracedata.endpos = tracedata.start + ply:GetAimVector() * 10000
tracedata.filter = ply
local trace = util.TraceLine(tracedata)
local offset = Vector(0, 0, 1)
if trace.HitNormal ~= Vector(0, 0, 1) then
offset = trace.HitNormal * 16
end
local _, hull = ply:GetHull()
local InitialPosition = DarkRP.findEmptyPos(trace.HitPos + offset, {ply}, 600, 20, hull)
target:SetPos(InitialPosition)
zapEffect(target)
FAdmin.Log(string.format("FAdmin: %s (%s) teleported %s", ply:Nick(), ply:SteamID(), target:Nick()))
end
end
return true, targets, ply:GetEyeTrace().HitPos
end
local function Bring(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Teleport") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
local BringTo = FAdmin.FindPlayer(args[2])
BringTo = (BringTo and BringTo[1]) or ply
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not IsValid(target) or target == ply then continue end
target:ExitVehicle()
if not target:Alive() then target:Spawn() end
local PHYSGUN = false
if IsValid(target:GetActiveWeapon()) and target:GetActiveWeapon():GetClass() == "weapon_physgun" and target:KeyDown(IN_ATTACK) then
target:ConCommand("-attack") --release the stuff he's holding :)
target:GetActiveWeapon():Remove()
PHYSGUN = true
end
timer.Simple(0, function()
if not IsValid(target) then return end
local tracedata = {}
tracedata.start = BringTo:GetShootPos()
tracedata.endpos = tracedata.start + BringTo:GetAimVector() * 50
tracedata.filter = BringTo
local trace = util.TraceLine(tracedata)
if trace.HitPos:DistToSqr(BringTo:GetShootPos()) < 2025 then
tracedata.endpos = tracedata.start - BringTo:GetAimVector() * 50
trace = util.TraceLine(tracedata)
end
local _, hull = target:GetHull()
target:SetPos(DarkRP.findEmptyPos(BringTo:GetPos(), {target}, 600, 30, hull))
zapEffect(target)
if PHYSGUN then timer.Simple(0.5, function() target:Give("weapon_physgun") target:SelectWeapon("weapon_physgun") end) end
end)
end
FAdmin.Messages.FireNotification("bring", ply, targets)
return true, targets, BringTo
end
local function Goto(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Teleport") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[1] then return false end
local target = FAdmin.FindPlayer(args[1])
target = target and target[1]
if not IsValid(target) then return false end
ply:ExitVehicle()
if not ply:Alive() then ply:Spawn() end
local _, hull = ply:GetHull()
ply:SetPos(DarkRP.findEmptyPos(target:GetPos(), {ply}, 600, 30, hull))
zapEffect(ply)
FAdmin.Messages.FireNotification("goto", ply, target)
return true, target
end
FAdmin.StartHooks["zz_Teleport"] = function()
FAdmin.Access.AddPrivilege("Teleport", 2)
FAdmin.Messages.RegisterNotification{
name = "goto",
hasTarget = true,
receivers = "admins",
message = {"instigator", " teleported to ", "targets"},
}
FAdmin.Messages.RegisterNotification{
name = "bring",
hasTarget = true,
receivers = "admins",
message = {"instigator", " brought ", "targets", " to them"},
}
FAdmin.Commands.AddCommand("Teleport", Teleport)
FAdmin.Commands.AddCommand("TP", Teleport)
FAdmin.Commands.AddCommand("Bring", Bring)
FAdmin.Commands.AddCommand("Goto", Goto)
FAdmin.Commands.AddCommand("TPToPos", TPToPos)
end

View File

@@ -0,0 +1,82 @@
hook.Add("PlayerBindPress", "FAdmin_voicemuted", function(ply, bind, pressed)
if ply:FAdmin_GetGlobal("FAdmin_voicemuted") and string.find(string.lower(bind), "voicerecord") then return true end
-- The voice muting is not done clientside, this is just so people know they can't talk
end)
FAdmin.StartHooks["VoiceMute"] = function()
FAdmin.Messages.RegisterNotification{
name = "voicemute",
hasTarget = true,
message = {"instigator", " voice muted ", "targets", " ", "extraInfo.1"},
readExtraInfo = function()
local time = net.ReadUInt(16)
return {time == 0 and FAdmin.PlayerActions.commonTimes[time] or string.format("for %s", FAdmin.PlayerActions.commonTimes[time] or (time .. " seconds"))}
end
}
FAdmin.Messages.RegisterNotification{
name = "voiceunmute",
hasTarget = true,
message = {"instigator", " voice unmuted ", "targets"}
}
FAdmin.Access.AddPrivilege("Voicemute", 2)
FAdmin.Commands.AddCommand("Voicemute", nil, "<Player>")
FAdmin.Commands.AddCommand("UnVoicemute", nil, "<Player>")
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
if ply:FAdmin_GetGlobal("FAdmin_voicemuted") then return "Unmute voice globally" end
return "Mute voice globally"
end,
function(ply)
if ply:FAdmin_GetGlobal("FAdmin_voicemuted") then return "fadmin/icons/voicemute" end
return "fadmin/icons/voicemute", "fadmin/icons/disable"
end,
Color(255, 130, 0, 255),
function(ply) return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "Voicemute", ply) end,
function(ply, button)
if not ply:FAdmin_GetGlobal("FAdmin_voicemuted") then
FAdmin.PlayerActions.addTimeMenu(function(secs)
RunConsoleCommand("_FAdmin", "Voicemute", ply:UserID(), secs)
button:SetImage2("null")
button:SetText("Unmute voice globally")
button:GetParent():InvalidateLayout()
end)
else
RunConsoleCommand("_FAdmin", "UnVoicemute", ply:UserID())
end
button:SetImage2("fadmin/icons/disable")
button:SetText("Mute voice globally")
button:GetParent():InvalidateLayout()
end)
FAdmin.ScoreBoard.Player:AddActionButton(function(ply)
return ply.FAdminMuted and "Unmute voice" or "Mute voice"
end,
function(ply)
if ply.FAdminMuted then return "fadmin/icons/voicemute" end
return "fadmin/icons/voicemute", "fadmin/icons/disable"
end,
Color(255, 130, 0, 255),
true,
function(ply, button)
ply:SetMuted(not ply.FAdminMuted)
ply.FAdminMuted = not ply.FAdminMuted
if ply.FAdminMuted then button:SetImage2("null") button:SetText("Unmute voice") button:GetParent():InvalidateLayout() return end
button:SetImage2("fadmin/icons/disable")
button:SetText("Mute voice")
button:GetParent():InvalidateLayout()
end)
FAdmin.ScoreBoard.Main.AddPlayerRightClick("Mute/Unmute", function(ply, Panel)
ply:SetMuted(not ply.FAdminMuted)
ply.FAdminMuted = not ply.FAdminMuted
end)
end

View File

@@ -0,0 +1,76 @@
local function MuteVoice(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
local time = tonumber(args[2]) or 0
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Voicemute", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and not target:FAdmin_GetGlobal("FAdmin_voicemuted") then
target:FAdmin_SetGlobal("FAdmin_voicemuted", true)
if time == 0 then continue end
timer.Simple(time, function()
if not IsValid(target) or not target:FAdmin_GetGlobal("FAdmin_voicemuted") then return false end
target:FAdmin_SetGlobal("FAdmin_voicemuted", false)
end)
end
end
FAdmin.Messages.FireNotification("voicemute", ply, targets, {time})
return true, targets, time
end
local function UnMuteVoice(ply, cmd, args)
if not args[1] then return false end
local targets = FAdmin.FindPlayer(args[1])
if not targets or #targets == 1 and not IsValid(targets[1]) then
FAdmin.Messages.SendMessage(ply, 1, "Player not found")
return false
end
for _, target in ipairs(targets) do
if not FAdmin.Access.PlayerHasPrivilege(ply, "Voicemute", target) then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if IsValid(target) and target:FAdmin_GetGlobal("FAdmin_voicemuted") then
target:FAdmin_SetGlobal("FAdmin_voicemuted", false)
end
end
FAdmin.Messages.FireNotification("voiceunmute", ply, targets)
return true, targets
end
FAdmin.StartHooks["VoiceMute"] = function()
FAdmin.Messages.RegisterNotification{
name = "voicemute",
hasTarget = true,
receivers = "involved+admins",
writeExtraInfo = function(info) net.WriteUInt(info[1], 16) end,
message = {"instigator", " voice muted ", "targets", " ", "extraInfo.1"},
}
FAdmin.Messages.RegisterNotification{
name = "voiceunmute",
hasTarget = true,
receivers = "involved+admins",
message = {"instigator", " voice unmuted ", "targets"},
}
FAdmin.Commands.AddCommand("Voicemute", MuteVoice)
FAdmin.Commands.AddCommand("UnVoicemute", UnMuteVoice)
FAdmin.Access.AddPrivilege("Voicemute", 2)
end
hook.Add("PlayerCanHearPlayersVoice", "FAdmin_Voicemute", function(Listener, Talker)
if Talker:FAdmin_GetGlobal("FAdmin_voicemuted") then return false end
end)

View File

@@ -0,0 +1,10 @@
FAdmin.StartHooks["00RCon"] = function()
FAdmin.Access.AddPrivilege("RCon", 3)
FAdmin.Commands.AddCommand("RCon", "<command>", "<args>")
FAdmin.ScoreBoard.Server:AddServerAction("RCon", "fadmin/icons/rcon", Color(155, 0, 0, 255), function() return FAdmin.Access.PlayerHasPrivilege(LocalPlayer(), "RCon") end,
function(ply, button)
Derma_StringRequest("RCon comand", "Enter a command to be run on the server. Note: a lot of commands are blocked and they will not work!", "",
function(text) RunConsoleCommand("_FAdmin", "RCon", unpack(string.Explode(" ", text))) end)
end)
end

View File

@@ -0,0 +1,16 @@
local function RCon(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "RCon") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local CommandArgs = table.Copy(args)
CommandArgs[1] = nil
CommandArgs = table.ClearKeys(CommandArgs)
RunConsoleCommand(args[1], unpack(CommandArgs))
return true, args[1], CommandArgs
end
FAdmin.StartHooks["RCon"] = function()
FAdmin.Commands.AddCommand("RCon", RCon)
FAdmin.Access.AddPrivilege("RCon", 3) -- Root only
end

View File

@@ -0,0 +1,33 @@
local function FillMenu(menu, SpawnName, GroupName)
menu:AddOption("unrestrict", function() RunConsoleCommand("_FAdmin", "UnRestrictWeapon", SpawnName) end)
menu:AddSpacer("")
for k in SortedPairsByMemberValue(FAdmin.Access.Groups, "ADMIN", true) do
menu:AddOption(k, function() RunConsoleCommand("_FAdmin", "RestrictWeapon", SpawnName, k) end)
end
end
local function RestrictWeaponMenu()
local frame = vgui.Create("DFrame")
frame:SetTitle("Restrict weapons")
frame:SetSize(ScrW() / 2, ScrH() - 50)
frame:Center()
frame:SetVisible(true)
frame:MakePopup()
local WeaponMenu = vgui.Create("FAdmin_weaponPanel", frame)
WeaponMenu.HideAmmo = true
function WeaponMenu:DoGiveWeapon(SpawnName)
local menu = DermaMenu()
menu:SetPos(gui.MouseX(), gui.MouseY())
FillMenu(menu, SpawnName)
menu:Open()
end
WeaponMenu:BuildList()
WeaponMenu:StretchToParent(0,25,0,0)
end
FAdmin.StartHooks["Restrict"] = function()
FAdmin.Access.AddPrivilege("Restrict", 3)
FAdmin.ScoreBoard.Server:AddPlayerAction("Restrict weapons", "fadmin/icons/weapon", Color(0, 155, 0, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "Restrict") end, RestrictWeaponMenu)
end

View File

@@ -0,0 +1,59 @@
sql.Query("CREATE TABLE IF NOT EXISTS FADMIN_RESTRICTEDENTS('TYPE' TEXT NOT NULL, 'ENTITY' TEXT NOT NULL, 'ADMIN_GROUP' TEXT NOT NULL, PRIMARY KEY(TYPE, ENTITY));")
local Restricted = {}
Restricted.Weapons = {}
local function RetrieveRestricted()
local Query = sql.Query("SELECT * FROM FADMIN_RESTRICTEDENTS") or {}
for _, v in ipairs(Query) do
if Restricted[v.TYPE] then
Restricted[v.TYPE][v.ENTITY] = v.ADMIN_GROUP
end
end
end RetrieveRestricted()
local function DoRestrictWeapons(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Restrict") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local Weapon = args[1]
local Group = args[2]
if not Group or not FAdmin.Access.Groups[Group] or not Weapon then return false end
if Restricted.Weapons[Weapon] then
sql.Query("UPDATE FADMIN_RESTRICTEDENTS SET ADMIN_GROUP = " .. sql.SQLStr(Group) .. " WHERE ENTITY = " .. sql.SQLStr(Weapon) .. " AND TYPE = " .. sql.SQLStr("Weapons") .. ";")
else
sql.Query("INSERT INTO FADMIN_RESTRICTEDENTS VALUES(" .. sql.SQLStr("Weapons") .. ", " .. sql.SQLStr(Weapon) .. ", " .. sql.SQLStr(Group) .. ");")
end
Restricted.Weapons[Weapon] = Group
FAdmin.Messages.SendMessage(ply, 4, "Weapon restricted!")
return true, Weapon, Group
end
local function UnRestrictWeapons(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "Restrict") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
local Weapon = args[1]
sql.Query("DELETE FROM FADMIN_RESTRICTEDENTS WHERE ENTITY = " .. sql.SQLStr(Weapon) .. " AND TYPE = " .. sql.SQLStr("Weapons") .. ";")
Restricted.Weapons[Weapon] = nil
FAdmin.Messages.SendMessage(ply, 4, "Weapon unrestricted!")
return true, Weapon
end
local function RestrictWeapons(ply, Weapon, WeaponTable)
local Group = ply:GetUserGroup()
if not FAdmin or not FAdmin.Access or not FAdmin.Access.Groups or not FAdmin.Access.Groups[Group]
or not FAdmin.Access.Groups[Restricted.Weapons[Weapon]] then return end
local RequiredGroup = Restricted.Weapons[Weapon]
if Group ~= RequiredGroup and FAdmin.Access.Groups[Group].ADMIN <= FAdmin.Access.Groups[RequiredGroup].ADMIN then return false end
end
hook.Add("PlayerGiveSWEP", "FAdmin_RestrictWeapons", RestrictWeapons)
hook.Add("PlayerSpawnSWEP", "FAdmin_RestrictWeapons", RestrictWeapons)
FAdmin.StartHooks["Restrict"] = function()
FAdmin.Commands.AddCommand("RestrictWeapon", DoRestrictWeapons)
FAdmin.Commands.AddCommand("UnRestrictWeapon", UnRestrictWeapons)
FAdmin.Access.AddPrivilege("Restrict", 3)
end

View File

@@ -0,0 +1,78 @@
local function SetLimits()
local frame = vgui.Create("DFrame")
frame:SetTitle("Set Limits")
frame:SetSize(300, 460)
frame:Center()
frame:SetVisible(true)
frame:MakePopup()
local PanelList = vgui.Create("DPanelList", frame)
PanelList:StretchToParent(5, 25, 5, 5)
PanelList:EnableVerticalScrollbar(true)
local Form = vgui.Create("DForm", PanelList)
Form:SetName("")
local Settings = util.KeyValuesToTable(file.Read("gamemodes/sandbox/sandbox.txt", "GAME")) -- All SBox limits are in here :D
for _, v in SortedPairs(Settings.settings or {}) do
if v.type == "Numeric" then
local left, _ = Form:NumberWang(v.text, nil, v.low or 0, v.high or 1000, v.decimals or 0)
left:SetFloatValue(GetConVar(v.name):GetFloat())
left:SetValue(GetConVar(v.name):GetFloat())
function left:OnValueChanged(val)
if val == GetConVar(v.name):GetFloat() then
return
end
RunConsoleCommand("_FAdmin", "ServerSetting", v.name, val)
end
end
end
PanelList:AddItem(Form)
end
FAdmin.StartHooks["ServerSettings"] = function()
FAdmin.Access.AddPrivilege("ServerSetting", 2)
local sbox_godmode = GetConVar("sbox_godmode")
FAdmin.ScoreBoard.Server:AddServerSetting(function() return (sbox_godmode:GetBool() and "Disable" or "Enable") .. " global god mode" end,
function() return "fadmin/icons/god", sbox_godmode:GetBool() and "fadmin/icons/disable" end,
Color(0, 0, 155, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "ServerSetting") end, function(button)
local val = sbox_godmode:GetBool()
button:SetImage2((not val and "fadmin/icons/disable") or "null")
button:SetText((not val and "Disable" or "Enable") .. " global god mode")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_FAdmin", "ServerSetting", "sbox_godmode", val and 0 or 1)
end)
local sbox_playershurtplayers = GetConVar("sbox_playershurtplayers")
FAdmin.ScoreBoard.Server:AddServerSetting(function() return (sbox_playershurtplayers:GetBool() and "Disable" or "Enable") .. " player vs player damage" end,
function() return "fadmin/icons/weapon", sbox_playershurtplayers:GetBool() and "fadmin/icons/disable" end,
Color(0, 0, 155, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "ServerSetting") end, function(button)
local val = sbox_playershurtplayers:GetBool()
button:SetImage2(not val and "fadmin/icons/disable" or "null")
button:SetText((not val and "Disable" or "Enable") .. " player vs player damage")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_FAdmin", "ServerSetting", "sbox_playershurtplayers", val and 0 or 1)
end)
local sbox_noclip = GetConVar("sbox_noclip")
FAdmin.ScoreBoard.Server:AddServerSetting(function() return (sbox_noclip:GetBool() and "Disable" or "Enable") .. " global noclip" end,
function() return "fadmin/icons/noclip", sbox_noclip:GetBool() and "fadmin/icons/disable" end,
Color(0, 0, 155, 255), function(ply) return FAdmin.Access.PlayerHasPrivilege(ply, "ServerSetting") end, function(button)
local val = sbox_noclip:GetBool()
button:SetImage2(not val and "fadmin/icons/disable" or "null")
button:SetText((not val and "Disable" or "Enable") .. " global noclip")
button:GetParent():InvalidateLayout()
RunConsoleCommand("_FAdmin", "ServerSetting", "sbox_noclip", val and 0 or 1)
end)
FAdmin.ScoreBoard.Server:AddServerSetting("Set server limits", "fadmin/icons/serversetting", Color(0, 0, 155, 255), true, SetLimits)
end

View File

@@ -0,0 +1,45 @@
local Whitelist = {"sv_password"} -- Make sure people don't use FAdmin serversetting as easy RCON, only the SBOX commands are allowed
table.insert(Whitelist, "sbox_.*")
table.insert(Whitelist, "_FAdmin_.*")
sql.Query([[CREATE TABLE IF NOT EXISTS FAdmin_ServerSettings(setting STRING NOT NULL PRIMARY KEY, value STRING NOT NULL);]])
function FAdmin.SaveSetting(var, value)
sql.Query([[REPLACE INTO FAdmin_ServerSettings VALUES(]] .. MySQLite.SQLStr(var:lower()) .. [[, ]] .. MySQLite.SQLStr(value) .. ");")
end
hook.Add("InitPostEntity", "FAdmin_Settings", function()
local Settings = sql.Query("SELECT * FROM FAdmin_ServerSettings;") or {}
for _, v in pairs(Settings) do
RunConsoleCommand(v.setting, v.value)
end
end)
local function ServerSetting(ply, cmd, args)
if not FAdmin.Access.PlayerHasPrivilege(ply, "ServerSetting") then FAdmin.Messages.SendMessage(ply, 5, "No access!") return false end
if not args[2] then FAdmin.Messages.SendMessage(ply, 5, "Incorrect argument") return false end
local found = false
for _, v in pairs(Whitelist) do
if string.match(args[1], v) then
found = true
break
end
end
if not found then return false end
local CommandArgs = table.Copy(args)
CommandArgs[1] = nil
CommandArgs = table.ClearKeys(CommandArgs)
RunConsoleCommand(args[1], unpack(CommandArgs))
FAdmin.SaveSetting(args[1], CommandArgs[1])
FAdmin.Messages.ActionMessage(ply, player.GetAll(), "You have set " .. args[1] .. " to " .. unpack(CommandArgs),
args[1] .. " was set to " .. unpack(CommandArgs), "Set " .. args[1] .. " to " .. unpack(CommandArgs))
return true, args[1], CommandArgs
end
FAdmin.StartHooks["ServerSettings"] = function()
FAdmin.Commands.AddCommand("ServerSetting", ServerSetting)
FAdmin.Access.AddPrivilege("ServerSetting", 2)
end

View File

@@ -0,0 +1,82 @@
FAdmin = FAdmin or {}
FAdmin.PlayerActions = FAdmin.PlayerActions or {}
FAdmin.StartHooks = FAdmin.StartHooks or {}
--[[
Utilities!
]]
function FAdmin.FindPlayer(info)
if not info then return nil end
local pls = player.GetAll()
local found = {}
if string.lower(info) == "*" or string.lower(info) == "<all>" then return pls end
local InfoPlayers = {}
for A in string.gmatch(info .. ";", "([a-zA-Z0-9:_.]*)[;(,%s)%c]") do
if A ~= "" then
table.insert(InfoPlayers, A)
end
end
for _, PlayerInfo in ipairs(InfoPlayers) do
-- Playerinfo is always to be treated as UserID when it's a number
-- otherwise people with numbers in their names could get confused with UserID's of other players
if tonumber(PlayerInfo) then
if IsValid(Player(PlayerInfo)) and not found[Player(PlayerInfo)] then
found[Player(PlayerInfo)] = true
end
continue
end
for _, v in ipairs(pls) do
-- Find by Steam ID
if (PlayerInfo == v:SteamID() or v:SteamID() == "UNKNOWN") and not found[v] then
found[v] = true
end
-- Find by Partial Nick
if string.find(string.lower(v:Nick()), string.lower(tostring(PlayerInfo)), 1, true) ~= nil and not found[v] then
found[v] = true
end
if v.SteamName and string.find(string.lower(v:SteamName()), string.lower(tostring(PlayerInfo)), 1, true) ~= nil and not found[v] then
found[v] = true
end
end
end
local players = {}
local empty = true
for k in pairs(found or {}) do
empty = false
table.insert(players, k)
end
return not empty and players or nil
end
function FAdmin.SteamToProfile(ply) -- Thanks decodaman
return "https://steamcommunity.com/profiles/" .. (ply:SteamID64() or "BOT")
end
--[[
FAdmin global settings
]]
FAdmin.GlobalSetting = FAdmin.GlobalSetting or {}
--[[Dependency solver:
Many plugins are dependant of one another.
To prevent plugins calling functions from other plugins that haven't been opened yet
there will be a hook that is called when all plugins are loaded.
This way there will be no hassle with which plugin loads first, which one next etc.
]]
timer.Simple(0, function()
for k in pairs(FAdmin.StartHooks) do if not isstring(k) then FAdmin.StartHooks[k] = nil end end
for _, v in SortedPairs(FAdmin.StartHooks) do
v()
end
end)

View File

@@ -0,0 +1,107 @@
util.AddNetworkString("FAdmin_retrievebans")
util.AddNetworkString("FADMIN_SendGroups")
util.AddNetworkString("FAdmin_GlobalSetting")
util.AddNetworkString("FAdmin_PlayerSetting")
util.AddNetworkString("FAdmin_GlobalPlayerSettings")
local SortedPairs, ipairs, pairs = SortedPairs, ipairs, pairs
-- recursively adds everything in a directory to be downloaded by client
local function AddDir(dir)
local files, folders = file.Find(dir .. "/*", "GAME")
for _, fdir in ipairs(folders) do
-- don't spam people with useless .svn folders
if fdir ~= ".svn" then
AddDir(dir .. "/" .. fdir)
end
end
for _, v in ipairs(files) do
resource.AddFile(dir .. "/" .. v)
end
end
AddDir("materials/fadmin")
local function AddCSLuaFolder(fol)
fol = string.lower(fol)
local _, folders = file.Find(fol .. "*", "LUA")
for _, folder in SortedPairs(folders, true) do
if folder ~= "." and folder ~= ".." then
for _, File in SortedPairs(file.Find(fol .. folder .. "/sh_*.lua", "LUA")) do
AddCSLuaFile(fol .. folder .. "/" .. File)
include(fol .. folder .. "/" .. File)
end
for _, File in SortedPairs(file.Find(fol .. folder .. "/sv_*.lua", "LUA"), true) do
include(fol .. folder .. "/" .. File)
end
for _, File in SortedPairs(file.Find(fol .. folder .. "/cl_*.lua", "LUA"), true) do
AddCSLuaFile(fol .. folder .. "/" .. File)
end
end
end
end
AddCSLuaFolder(GM.FolderName .. "/gamemode/modules/fadmin/fadmin/")
AddCSLuaFolder(GM.FolderName .. "/gamemode/modules/fadmin/fadmin/playeractions/")
--[[---------------------------------------------------------------------------
FAdmin global settings
---------------------------------------------------------------------------]]
function FAdmin.SetGlobalSetting(setting, value)
if FAdmin.GlobalSetting[setting] == value then return end -- If the value didn't change, we don't need to resend it.
FAdmin.GlobalSetting[setting] = value
net.Start("FAdmin_GlobalSetting")
net.WriteString(setting)
net.WriteType(value)
net.Broadcast()
end
local plyMeta = FindMetaTable("Player")
function plyMeta:FAdmin_SetGlobal(setting, value)
self.GlobalSetting = self.GlobalSetting or {}
if self.GlobalSetting[setting] == value then return end -- If the value didn't change, we don't need to resend it.
self.GlobalSetting[setting] = value
net.Start("FAdmin_PlayerSetting")
net.WriteUInt(self:UserID(), 16)
net.WriteString(setting)
net.WriteType(value)
net.Broadcast()
end
function plyMeta:FAdmin_GetGlobal(setting)
return self.GlobalSetting and self.GlobalSetting[setting] or nil
end
hook.Add("PlayerInitialSpawn", "FAdmin_GlobalSettings", function(ply)
-- Not optimal in efficiency, but with the amount of global settings
-- it's not worth spending a lot of time on.
net.Start("FAdmin_GlobalPlayerSettings")
net.WriteUInt(table.Count(FAdmin.GlobalSetting), 8) -- assume max 255 settings
for k, v in pairs(FAdmin.GlobalSetting) do
net.WriteString(k)
net.WriteType(v)
end
local tPlayers = player.GetAll()
net.WriteUInt(#tPlayers, 8)
for _, target in ipairs(tPlayers) do
local targetSettings = target.GlobalSetting or {}
net.WriteUInt(target:UserID(), 16)
net.WriteUInt(table.Count(targetSettings), 8)
for k, v in pairs(targetSettings) do
net.WriteString(k)
net.WriteType(v)
end
end
net.Send(ply)
end)
FAdmin.SetGlobalSetting("FAdmin", true)

View File

@@ -0,0 +1,76 @@
--[[---------------------------------------------------------------------------
Create the tables used for banning
---------------------------------------------------------------------------]]
hook.Add("DatabaseInitialized", "FAdmin_CreateMySQLTables", function()
MySQLite.query("CREATE TABLE IF NOT EXISTS FAdminBans(SteamID VARCHAR(25) NOT NULL PRIMARY KEY, Nick VARCHAR(40), BanDate DATETIME, UnbanDate DATETIME, Reason VARCHAR(100), AdminName VARCHAR(40), Admin_steam VARCHAR(25));", function()
hook.Call("FAdmin_RetrieveBans", nil)
end)
end)
--[[---------------------------------------------------------------------------
Store a ban in the MySQL tables
---------------------------------------------------------------------------]]
hook.Add("FAdmin_StoreBan", "MySQLBans", function(SteamID, Nick, Duration, Reason, AdminName, Admin_steam)
local steam = MySQLite.SQLStr(SteamID)
local nick = Nick and MySQLite.SQLStr(Nick) or "NULL"
local bandate = MySQLite.isMySQL() and "NOW()" or "datetime('now')"
local reason = Reason and MySQLite.SQLStr(Reason) or "NULL"
local admin = AdminName and MySQLite.SQLStr(AdminName) or "NULL"
local adminsteam = Admin_steam and MySQLite.SQLStr(Admin_steam) or "NULL"
local duration
if MySQLite.isMySQL() then
duration = Duration == 0 and "NULL" or "DATE_ADD(NOW(), INTERVAL " .. tonumber(Duration or 60) .. " MINUTE)"
else
duration = Duration == 0 and "NULL" or "datetime('now', '+" .. tonumber(Duration or 60) .. " minutes')"
end
MySQLite.query("REPLACE INTO FAdminBans VALUES(" .. steam .. ", " .. nick .. ", " .. bandate .. ", " .. duration .. ", " .. reason .. ", " .. admin .. ", " .. adminsteam .. ");")
end)
--[[---------------------------------------------------------------------------
Unban someone
---------------------------------------------------------------------------]]
hook.Add("FAdmin_UnBan", "FAdmin_MySQLUnban", function(ply, steamID)
MySQLite.query("DELETE FROM FAdminBans WHERE steamID = " .. MySQLite.SQLStr(steamID))
end)
--[[---------------------------------------------------------------------------
Retrieve the bans from the MySQL server and put them into effect
Note: Must be called more than two seconds after InitPostEntity, because
that's when the database initializes
---------------------------------------------------------------------------]]
hook.Add("FAdmin_RetrieveBans", "getMySQLBans", function()
FAdmin.BANS = FAdmin.BANS or {}
-- Small SQLite and MySQL syntax difference
local diffSeconds = MySQLite.isMySQL() and "TIMESTAMPDIFF(SECOND, NOW(), UnbanDate)" or
"strftime('%s', UnbanDate) - strftime('%s','now')"
local now = MySQLite.isMySQL() and "NOW()" or "datetime('now')"
MySQLite.query("SELECT SteamID, Nick, " .. diffSeconds .. " AS duration, Reason, AdminName, Admin_steam FROM FAdminBans WHERE (UnbanDate > " .. now .. " OR UnbanDate IS NULL);", function(data)
if not data then return end
for _, v in ipairs(data) do
if tonumber(v.SteamID) or not v.SteamID then continue end
local duration = (not v.duration or v.duration == "NULL") and 0 or (os.time() + v.duration)
FAdmin.BANS[string.upper(v.SteamID)] = {
time = duration,
name = v.Nick,
reason = v.Reason,
adminname = v.AdminName,
adminsteam = v.Admin_steam
}
end
for _, v in ipairs(player.GetAll()) do
if not FAdmin.BANS[string.upper(v:SteamID())] then continue end
v:Kick("FAdmin ban evasion")
end
end)
end)