assert( _file.Exists( "lua/ULib/init.lua" ), "UAfk needs ULib to run!" )
_OpenScript( "ULib/init.lua" )
assert( ULib.VERSION >= 1.2, "UAfk requires ULib version 1.2 or higher to run!" )
local maxAfk = 300 -- Time from AFK to kick, 0 to disable kicking.
local minAfk = 60 -- Time required to be considered AFK.
local minPlayers = 4 -- The minimum number of players required before this script will start kicking (disabled if maxAfk is 0).
local checkTime = 1 -- How often, in seconds, it checks if you're afk.
local access = ACCESS_RESERVATION -- Access needed not to be kicked (if maxAfk is enabled).
local prefixAfk = "[AFK] " -- What to prefix the user's name with when they go AFK (requires the ULib server plugin).
local afkText = "This player is AFK!" -- What to show over player's head. Set to "" to disable.
local ucl = ULib.mainUcl
local rectKey = 678
local textKey = 679
-- Note: we're checking by angles, since that changes more often than position. We're also taking the tostring() so we get an approximation
-- Let's set up our information
local playerInfo = {}
for i=1, _MaxPlayers() do
playerInfo[ i ] = { ang=tostring(vector3( 0, 0, 0 )), time=0, afk=false }
end
local function checkPlayers()
local curTime = _CurTime()
local players = ULib.totalPlayers()
for i=1, _MaxPlayers() do
if _PlayerInfo( i, "connected" ) then
local curang = tostring( _EntGetAng( i ) )
if playerInfo[ i ].ang ~= curang then -- They are not AFK
if playerInfo[ i ].afk then -- If they just came back from AFK.
if ULib.pluginEnabled() and prefixAfk ~= "" then
ULib.cexec( i, "name \"" .. playerInfo[ i ].name .. "\"" )
end
_GModText_Hide( i, textKey )
_GModText_Hide( i, textKey + 1 )
_GModText_Hide( 0, textKey + 1 + i )
_GModRect_Hide( i, rectKey )
_PlayerGod( i, false ) -- Give them god so they can't be killed or moved
end
playerInfo[ i ] = { ang=curang, time=curTime, afk=false }
else -- They are AFK
local afkTime = curTime - playerInfo[ i ].time
if afkTime >= minAfk then -- They've hit AFK time
if not playerInfo[ i ].afk then -- They're just now going afk.
playerInfo[ i ].afk = true
if ULib.pluginEnabled() and prefixAfk ~= "" then
local name = _PlayerInfo( i, "name" )
if string.sub( name, 1, string.len( prefixAfk ) ) == prefixAfk then -- They already have the prefix for some reason
playerInfo[ i ].name = string.sub( name, string.len( prefixAfk ) + 1 )
else
playerInfo[ i ].name = _PlayerInfo( i, "name" )
ULib.cexec( i, "name \"" .. prefixAfk .. playerInfo[ i ].name .. "\"" )
end
end
ULib.sendRect( i, rectKey, 0, 0, 1, 1, 9999, 70, 70, 70, 200 )
ULib.sendText( i, textKey, 0.1, 0.4, "You are currently flagged as AFK", 9999, 0, 255, 0, 255, "ImpactMassive" )
if afkText ~= "" then
_GModText_Start( "Default" )
_GModText_SetColor( 255, 0, 0, 255 )
_GModText_SetTime( 9999, 0, 0 )
_GModText_SetEntityOffset( vector3( 0, 0, 60 ) )
_GModText_SetEntity( i )
_GModText_SetText( afkText )
_GModText_Send( 0, textKey + 1 + i )
end
_PlayerGod( i, true ) -- Give them god so they can't be killed or moved
end
if maxAfk > 0 and players >= minPlayers and not ucl:query( i, access ) then
if afkTime >= maxAfk and not ucl:query( i, access ) then -- Past kick time
if ULib.pluginEnabled() and prefixAfk ~= "" then -- Set their name back before kicking.
ULib.cexec( i, "name \"" .. playerInfo[ i ].name .. "\"" )
end
ULib.addTimer( 0.5, 1, ULib.kick, i, "AFK Timeout" ) -- This ensures the cexec will get to them
end
local timeLeft = maxAfk - afkTime
local h, m, s = ULib.sToHMS( timeLeft )
local timeText
if m > 0 then
timeText = m .. ":" .. string.format( "%02i", s ) .. " minutes"
else
timeText = s .. " seconds"
end
ULib.sendText( i, textKey + 1, 0.4, 0.25, "You have " .. timeText .. " left until you're kicked.", checkTime + 1, 255, 0, 0, 255, "ChatFont", 0, 0 )
end
end
end
end
end
end
ULib.addTimer( checkTime, 0, checkPlayers )
local function disconnect( name, userid ) -- Reset their information
playerInfo[ userid ] = { ang=tostring(vector3( 0, 0, 0 )), time=0, afk=false }
_GModText_Hide( 0, textKey + 1 + userid )
end
HookEvent( "eventPlayerDisconnect", disconnect )