local CATEGORY_NAME = "Utility" CreateConVar("ulx_warnkick_num", 3, FCVAR_ARCHIVE, "Number of warnings a player needs before they are kicked/banned.") CreateConVar("ulx_warnkick_decayrate", 30, FCVAR_ARCHIVE, "Minutes a player needs to be connected before their warning count is decreased by 1.") CreateConVar("ulx_warnkick_ban", 0, FCVAR_ARCHIVE, "If this is set to 1, the script will issue a temp ban instead of a kick.") CreateConVar("ulx_warnkick_bantime", 30, FCVAR_ARCHIVE, "How long in minutes a player is banned if ulx_warkick_ban is set to 1.") if !file.Exists( "ulx", "DATA" ) then file.CreateDir( "ulx" ) end if !file.Exists( "ulx/Warnings", "DATA" ) then file.CreateDir( "ulx/Warnings" ) end --[[ ulx.warn( calling_ply, target_ply, reason ) calling_ply : PlayerObject : Player who ran the command. target_ply : PlayerObject : Player who is being warned. reason : String : Reason player is being warned. This function is the ULX function that allows for a warning of a player. ]] function ulx.warn( calling_ply, target_ply, reason ) if reason and reason ~= "" then ulx.fancyLogAdmin( calling_ply, "#A warned #T (#s)", target_ply, reason ) else reason = nil ulx.fancyLogAdmin( calling_ply, "#A warned #T", target_ply ) end ulx.AddWarning( target_ply, calling_ply, reason ) end local warn = ulx.command( CATEGORY_NAME, "ulx warn", ulx.warn, "!warn" ) warn:addParam{ type=ULib.cmds.PlayerArg } warn:addParam{ type=ULib.cmds.StringArg, hint="reason", ULib.cmds.optional, ULib.cmds.takeRestOfLine } warn:defaultAccess( ULib.ACCESS_ADMIN ) warn:help( "Warn a player." ) --[[ ulx.AddWarning( target_ply, calling_ply, reason ) target_ply : PlayerObject : Player who is being warned. calling_ply : PlayerObject : Admin or player who did the warning. reason : String : Reason player is being warned. This helper function is what adds the warning to the player's table and calls the save helper function. ]] function ulx.AddWarning( target_ply, calling_ply, reason ) if target_ply.warntable == nil then target_ply.warntable = {} end if target_ply.warntable["wcount"] == nil then target_ply.warntable["wcount"] = 0 end if target_ply.warntable["warnings"] == nil then target_ply.warntable["warnings"] = {} end table.insert(target_ply.warntable["warnings"], {os.date(), calling_ply:Nick(), reason}) target_ply.warntable["wcount"] = target_ply.warntable["wcount"] + 1 ULib.tsayColor(target_ply, Color(0,0,0,255), "AWarn: " , Color(255,255,255,255), "You were warned by ", Color(0,0,0,255), "(", Color(0,255,0,255), calling_ply:Nick(), Color(0,0,0,255), ")", Color(255,255,255,255), " for: ", Color(255,0,0,255), reason) if target_ply.warntable["wcount"] >= GetConVarNumber( "ulx_warnkick_num" ) then if GetConVarNumber( "ulx_warnkick_ban" ) == 0 then target_ply.warntable["wcount"] = target_ply.warntable["wcount"] - 1 ulx.WarningSave( target_ply ) ULib.kick( target_ply, "Warning threshold exceeded" ) else local btime = tostring( GetConVarNumber( "ulx_warnkick_bantime" ) ) target_ply.warntable["wcount"] = target_ply.warntable["wcount"] - 1 ulx.WarningSave( target_ply ) ULib.kickban( target_ply, GetConVarNumber( "ulx_warnkick_bantime" ), "Warning threshold exceededm Banned for (" .. btime .. ") minutes.", calling_ply ) end else ulx.WarningSave( target_ply ) end end --[[ ulx.DecayWarnings() This function runs on a timer and removes 1 active warning from a players warning count. The player needs to be playing on the server when this is called to have a warning removed. ]] function ulx.DecayWarnings() print("Decay timer running") for _, pl in pairs ( player.GetAll() ) do if pl.timewarned == 0 then pl.timewarned = 1 end -- prevents the line bellow from being 0 ever if pl:TimeConnected( ) <= GetConVarNumber( "ulx_warnkick_decayrate" ) * 60 * pl.timewarned then continue end if pl.warntable == nil then continue end if pl.warntable["wcount"] == nil then continue end if pl.warntable["wcount"] <= 0 then continue end pl.warntable["wcount"] = pl.warntable["wcount"] - 1 ulx.WarningSave( pl ) pl.timewarned = pl.timewarned + 1 ULib.tsayColor(pl, Color(0,0,0,255), "AWarn: " , Color(255,255,255,255), "Your total warning count has been reduced by ", Color(255,0,0,255), "1") end timer.Create( "ULX_DecayTimer", 60, 1, ulx.DecayWarnings ) --timer.Create( "ULX_DecayTimer", GetConVarNumber( "ulx_warnkick_decayrate" ) * 60, 1, ulx.DecayWarnings ) -- keeping as a backup end timer.Create( "ULX_DecayTimer", 1, 1, ulx.DecayWarnings ) --[[ ulx.WarningSave( pl ) pl : PlayerObject : Player whos warnings are being saved This helper function saves the player's warnings to a text file for future use. ]] function ulx.WarningSave( pl ) local tbl = pl.warntable local SID = pl:SteamID64() toencode = util.TableToJSON(tbl) file.Write("ulx/Warnings/"..SID..".txt", toencode) end --[[ ulx.WarningsLoad( pl ) pl : PlayerObject : Player whos warnings are being loaded This helper function loads a player's saved warnings from their file to their player object. ]] function ulx.WarningsLoad( pl ) local SID = pl:SteamID64() if file.Exists( "ulx/Warnings/" .. SID .. ".txt", "DATA" ) then local todecode = file.Read( "ulx/Warnings/" .. SID .. ".txt", "DATA" ) local tbl = util.JSONToTable( todecode ) pl.warntable = tbl end end hook.Add( "PlayerAuthed", "WarningsLoad", ulx.WarningsLoad ) --[[ ulx.seewarns( calling_ply, target_ply ) calling_ply : PlayerObject : Admin or player who runs the command. target_ply : PlayerObject : Target player whos warnings are being displayed. This function allows an admin or whoever is granted access to see the history of warnings on a target player. ]] function ulx.seewarns( calling_ply, target_ply ) if not IsValid(calling_ply) then return end if not IsValid(target_ply) then return end if target_ply.warntable == nil then target_ply.warntable = {} end if target_ply.warntable["warnings"] == nil then ULib.console( calling_ply, "Showing warning history for player: " .. target_ply:Nick() ) ULib.console( calling_ply, "this player does not currently have any warnings." ) else ULib.console( calling_ply, "Showing warning history for player: " .. target_ply:Nick() ) ULib.console( calling_ply, "Date Admin Reason" ) ULib.console( calling_ply, "-------------------------------------------------------------------------------------------" ) for k, v in pairs( target_ply.warntable[ "warnings" ] ) do local date = v[1] local admin = v[2] local reason = v[3] line = date .. string.rep(" ", 25 - date:len()) .. admin .. string.rep(" ", 35 - admin:len()) .. reason ULib.console( calling_ply, line ) end end end local seewarns = ulx.command( CATEGORY_NAME, "ulx seewarns", ulx.seewarns ) seewarns:addParam{ type=ULib.cmds.PlayerArg } seewarns:defaultAccess( ULib.ACCESS_ADMIN ) seewarns:help( "Lists all warnings for a player to console." ) --[[ ulx.RemoveWarning( calling_ply, target_ply, warning_count ) calling_ply : PlayerObject : Admin or player who runs the command. target_ply : PlayerObject : Target player whos warnings are being displayed. warning_count : Integer : Amount of active warnings to remove from the player. This function will allow an admin to remove active warnings from a target player. ]] function ulx.RemoveWarning( calling_ply, target_ply, warning_count ) if not IsValid(calling_ply) then return end if not IsValid(target_ply) then return end if target_ply.warntable == nil then target_ply.warntable = {} end if target_ply.warntable["wcount"] == nil then ULib.console( calling_ply, "Player " .. target_ply:Nick() .. " does not currently have any active warnings.") return end if target_ply.warntable["wcount"] == 0 then ULib.console( calling_ply, "Player " .. target_ply:Nick() .. " does not currently have any active warnings.") return end local total_warnings = target_ply.warntable["wcount"] local to_remove = warning_count if to_remove > total_warnings then to_remove = total_warnings end target_ply.warntable["wcount"] = total_warnings - to_remove ulx.fancyLogAdmin( calling_ply, "#A removed active warnings from #T.", target_ply ) ULib.console( calling_ply, "You removed (" .. to_remove .. ") warnings from " .. target_ply:Nick() .. ". Player current has (" .. target_ply.warntable["wcount"] .. ") active warnings remaining.") end local removewarn = ulx.command( CATEGORY_NAME, "ulx removewarning", ulx.RemoveWarning ) removewarn:addParam{ type=ULib.cmds.PlayerArg } removewarn:addParam{ type=ULib.cmds.NumArg, hint="active warnings to remove" } removewarn:defaultAccess( ULib.ACCESS_ADMIN ) removewarn:help( "Removes active warnings from a player." ) --[[ ulx.RemoveWarningHistory( calling_ply, target_ply ) calling_ply : PlayerObject : Admin or player who runs the command. target_ply : PlayerObject : Target player whos warnings are being removed. This function removes all warning history from a player. ]] function ulx.RemoveWarningHistory( calling_ply, target_ply ) if not IsValid(calling_ply) then return end if not IsValid(target_ply) then return end local SID = target_ply:SteamID64() if file.Exists( "ulx/Warnings/"..SID..".txt", "DATA" ) then file.Delete( "ulx/Warnings/"..SID..".txt" ) target_ply.warntable = nil ULib.console( calling_ply, "You removed all warning records for player: " .. target_ply:Nick() .. "." ) ulx.fancyLogAdmin( calling_ply, "#A removed all warning records for player #T.", target_ply ) else ULib.console( calling_ply, "Unable to find any warning records for player: " .. target_ply:Nick() .. "." ) end end local deletewarnings = ulx.command( CATEGORY_NAME, "ulx deletewarnings", ulx.RemoveWarningHistory ) deletewarnings:addParam{ type=ULib.cmds.PlayerArg } deletewarnings:defaultAccess( ULib.ACCESS_SUPERADMIN ) deletewarnings:help( "Deletes all warning records from a target player." ) --[[ ulx.ListAllWarnings( calling_ply ) calling_ply : PlayerObject : Admin or player who runs the command. Shows a list of all players on the server and how many total warnings and active warnings they have. ]] function ulx.ListAllWarnings( calling_ply ) ULib.console( calling_ply, "Showing total warnings for all players:" ) ULib.console( calling_ply, "Player Name Total Warnings Active Warnings" ) ULib.console( calling_ply, string.rep( "-", 75 ) ) for _, pl in pairs( player.GetAll() ) do if pl.warntable == nil then continue end if pl.warntable[ "wcount" ] == nil then continue end local totalwarns = tostring( table.Count( pl.warntable[ "warnings" ] ) ) local activewarns = tostring( pl.warntable[ "wcount" ] ) ULib.console( calling_ply, pl:Nick() .. string.rep(" ", 37 - pl:Nick():len()) .. totalwarns .. string.rep(" ", 23 - totalwarns:len()) .. activewarns ) end end local listwarnings = ulx.command( CATEGORY_NAME, "ulx listwarnings", ulx.ListAllWarnings ) listwarnings:defaultAccess( ULib.ACCESS_ADMIN ) listwarnings:help( "Returns a list of all connected players and their warning counts." )