Last active
October 31, 2018 09:53
-
-
Save Cuyler36/7c6b77073e06881357fce713af76d1d3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Players = game:GetService("Players"); | |
local MaximumMovementDistance = 50; -- How many studs a Player can move in one server game tick. | |
local TeleportDistanceThreshold = 2; -- How many studs away from the estimated teleport position the player needs to be. | |
local InfractionsBeforeBan = 2; -- How many times a Player needs to be caught before a ban will occur. This helps prevent possible false bans. | |
local BannedPlayers = {}; | |
local InfractionTable = {}; | |
local LastPositionsTable = {}; | |
Players.PlayerAdded:Connect(function(player) | |
if (BannedPlayers[player.UserId] == true) then | |
player:Kick(); | |
return; | |
end | |
player.CharacterAdded:Connect(function(character) | |
local enabled = true; | |
local rootPart = character:WaitForChild("HumanoidRootPart"); | |
LastPositionsTable[player] = rootPart.Position; -- Set this every time the character is added to avoid false flagging issues. | |
character:WaitForChild("Humanoid").Died:Connect(function() | |
enabled = false; -- Disable on death so flying body parts don't cause a false trigger. | |
end); | |
rootPart:GetPropertyChangedSignal("CFrame"):Connect(function() | |
if (enabled) then | |
local cframe = rootPart.CFrame; | |
if (LastPositionsTable[player] == nil) then | |
LastPositionsTable[player] = cframe.Position; | |
end | |
if ((LastPositionsTable[player] - cframe.Position).Magnitude >= MaximumMovementDistance) then | |
warn(string.format("Player [%s] moved more than the threshold distance of %d in one server game tick! Checking for exploiters.", tostring(player), MaximumMovementDistance)); | |
for _, otherPlayer in ipairs(Players:GetPlayers()) do | |
if (otherPlayer ~= player and otherPlayer.Character ~= nil) then | |
local otherRootPart = otherPlayer.Character:WaitForChild("HumanoidRootPart"); | |
local exploitedCFrame = otherRootPart.CFrame + otherRootPart.CFrame.LookVector; | |
if ((exploitedCFrame.Position - cframe.Position).Magnitude <= TeleportDistanceThreshold) then | |
InfractionTable[otherPlayer] = InfractionTable[otherPlayer] and InfractionTable[otherPlayer] + 1 or 1; | |
warn(string.format("It appears player [%s] is exploiting and attempting to kill others! Current infractions: %d", tostring(otherPlayer), InfractionTable[otherPlayer])); | |
if (InfractionTable[otherPlayer] >= InfractionsBeforeBan) then | |
warn(string.format("Player [%s] has reached the infraction ban threshold and is now banned!", otherPlayer)); | |
BannedPlayers[otherPlayer.UserId] = true; | |
otherPlayer:Kick(); -- I don't suggest adding a message here so they don't know why they were banned immediately. | |
end | |
end | |
end | |
end | |
end | |
LastPositionsTable[player] = cframe.Position; -- Update the position of the player in the position table for next frame. | |
end | |
end); | |
end); | |
end); | |
-- Clean up table entries to reduce memory usage. | |
Players.PlayerRemoving:Connect(function(player) | |
LastPositionsTable[player] = nil; | |
InfractionTable[player] = nil; | |
end); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment