-- Anti-Camping with AFK -- Idea inspired by Kennan afk_time = 45 -- Time in seconds before a player is considered to be AFK (used for the function isafk). afk_warn_time = 240 -- Time in seconds before a player is warned that they will be kicked for being AFK (use nil to disable). afk_kick_time = 300 -- Time in seconds before a player should be kicked for being AFK (use nil to disable). if afk_warn_time then afk_warn_message = "**Warning**: You will be kicked in " .. afk_kick_time - afk_warn_time .. " seconds for being AFK!" end if afk_kick_time then afk_kick_message = " has been kicked for being AFK." -- Player's name will be concatenated to the beginning of this string. end afk = {} xy_area_size = 4 -- XY size of sphere which a player must exit within area_timelimit seconds before they are considered to be camping. z_area_size = 2 -- Z size of sphere which a player must exit within area_timelimit seconds before they are considered to be camping. area_timelimit = 30 -- Amount of time in seconds a player is allowed to be within the same area before he/she is considered to be camping. camp_warning = 20 -- Amount of time in seconds before a player receives a warning that the server is about to consider them to be camping. camp_penalty = 0.1 -- Percentage of maximum health in damage done to player per second they are considered to be camping. Use 1 to kill the player. warning_message = "**Warning**: You will be considered to be camping in " .. area_timelimit - camp_warning .. " seconds!" camping_message = "**Warning**: The server will now apply " .. camp_penalty * 100 .. "% damage per second while you are camping!" function GetRequiredVersion() return 200 end function OnScriptLoad(processId, game, persistent) end --[[ function OnScriptUnload() end --]] --[[ function OnNewGame(map) end --]] --[[ function OnGameEnd(stage) end --]] function OnServerChat(player, type, message) if player and type < 4 then afk[player].time = -1 afk[player].boolean = false end end --[[ function OnServerCommandAttempt(player, command, password) --return true end --]] --[[ function OnServerCommand(admin, command) --return true end --]] --[[ function OnNameRequest(hash, name) --return true, name end --]] --[[ function OnBanCheck(hash, ip) --return true end --]] timers = {} location = {} camping = {} function OnPlayerJoin(player) afk[player] = {} afk[player].orientation = {} afk[player].response = true afk[player].time = 0 afk[player].boolean = false afk[player].timerid = registertimer(1000, "AFKTimer", player) location[player] = {} camping[player] = false timers[player] = registertimer(1000, "CampingTimer", player) end function AFKTimer(id, count, player) local m_player = getplayer(player) if m_player then local objId = readdword(m_player, 0x34) local m_object = getobject(objId) if m_object then local x_aim = readfloat(m_object, 0x230) local y_aim = readfloat(m_object, 0x234) local z_aim = readfloat(m_object, 0x238) local bool = true if x_aim == (afk[player].orientation.x or x_aim) and y_aim == (afk[player].orientation.y or y_aim) and z_aim == (afk[player].orientation.z or z_aim) then local walking = readbyte(m_object, 0x4D2) if walking == 0 then bool = false end end afk[player].orientation.x = x_aim afk[player].orientation.y = y_aim afk[player].orientation.z = z_aim afk[player].response = bool if afk[player].response == false then afk[player].time = afk[player].time + 1 else afk[player].time = 0 end if afk[player].time == 0 then afk[player].boolean = false elseif afk[player].time == afk_time then afk[player].boolean = true elseif afk[player].time == afk_warn_time then privatesay(player, afk_warn_message, false) elseif afk[player].time == afk_kick_time then say(getname(player) .. afk_kick_message, false) svcmd("sv_kick " .. resolveplayer(player)) end else afk[player].orientation.x = nil afk[player].orientation.y = nil afk[player].orientation.z = nil end end return true end function CampingTimer(id, count, player) local m_player = getplayer(player) if m_player then local objId = readdword(m_player, 0x34) local m_object = getobject(objId) if m_object then if not isafk(player) then local x, y, z = getobjectcoords(objId) location[player][count] = {x, y, z} local seconds = 0 for i = count, count - area_timelimit, -1 do if location[player][i] then local inside = inellipse(location[player][i], location[player][count]) if inside then seconds = seconds + 1 else for x = 1,i do location[player][x] = nil end break end else break end end if seconds == camp_warning then privatesay(player, warning_message, false) elseif seconds == area_timelimit then privatesay(player, camping_message, false) camping[player] = true end if seconds >= area_timelimit then -- 1 dmg = 4 / 300 health local total_damage = 1 / (4 / 300) local damage = camp_penalty * total_damage * 2 local shields = readfloat(m_object, 0xE4) local health = readfloat(m_object, 0xE0) if shields == 0 and health < camp_penalty then kill(player) else applydmg(objId, damage) end else camping[player] = false end end end end return true end function inellipse(t1, t2) local x1, y1, z1 = table.unpack(t1) local x2, y2, z2 = table.unpack(t2) local xdist = x2 - x1 local ydist = y2 - y1 local zdist = z2 - z1 if zdist / 2 <= z_area_size then local xy_dist = math.sqrt(xdist ^ 2 + ydist ^ 2) if xy_dist <= xy_area_size then return true end end return false end function OnPlayerLeave(player) removetimer(timers[player]) location[player] = nil camping[player] = nil removetimer(afk[player].timerid) afk[player] = nil end function OnPlayerKill(killer, victim, mode) if mode == 0 then if camping[victim] then say(getname(victim) .. " was killed for camping!", false) camping[victim] = false return false end end end --[[ function OnKillMultiplier(player, multiplier) -- Multipliers: -- 7: Double Kill -- 9: Triple Kill -- 10: Killtacular -- 11: Killing Spree -- 12: Running Riot -- 16: Double Kill w/ Score -- 17: Triple Kill w/ Score -- 14: Killtacular w/ Score -- 18: Killing Spree w/ Score -- 17: Running Riot w/ Score end --]] --[[ function OnPlayerSpawn(player) end --]] --[[ function OnPlayerSpawnEnd(player) end --]] --[[ function OnWeaponAssignment(player, objId, slot, weapId) --return mapId end --]] function OnWeaponReload(player, weapId) afk[player].time = -1 afk[player].boolean = false end function OnObjectCreationAttempt(mapId, parentId, player) if player then local tagname, tagtype = gettaginfo(mapId) if tagtype == "proj" then if afk[player] then afk[player].time = -1 afk[player].boolean = false end end end end --[[ function OnObjectCreation(objId) end --]] --[[ function OnObjectInteraction(player, objId, mapId) end --]] --[[ function OnTeamDecision(team) --return team end --]] --[[ function OnTeamChange(player, old_team, new_team, voluntary) --return true end --]] --[[ function OnDamageLookup(receiver, causer, mapId) --return true end --]] --[[ function OnDamageApplication(receiver, causer, mapId, location, backtap) --return true end --]] function OnVehicleEntry(player, vehiId, seat, mapId, voluntary) afk[player].time = -1 afk[player].boolean = false end function OnVehicleEject(player, voluntary) afk[player].time = -1 afk[player].boolean = false end function OnClientUpdate(player) local m_player = getplayer(player) if m_player then local objId = readdword(m_player, 0x34) local m_object = getobject(objId) if m_object then local melee_key = readbit(m_object, 0x208, 0) local action_key = readbit(m_object, 0x208, 1) local flashlight_key = readbit(m_object, 0x208, 3) local jump_key = readbit(m_object, 0x208, 6) local crouch_key = readbit(m_object, 0x208, 7) local right_mouse = readbit(m_object, 0x209, 3) if melee_key or action_key or flashlight_key or jump_key or crouch_key or right_mouse then afk[player].time = -1 afk[player].boolean = false end end end end function isafk(player) if player then if afk[player] then return afk[player].boolean end end end