Speed anticheat thing

my script checks every sec in a folder if theres a value with the players name if it does then it checks more stuff and then if it exceeds a certain speed limit its supposed to set the humanoid back to the old position but sometimes it work in 1 direction and sometimes it dosnt

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local SpeedList = ServerStorage.PlayerList.AntiCheat.Speed

while true do
	for i,v in pairs(Players:GetChildren()) do
		local HumanoidRootPart = v.Character:WaitForChild("HumanoidRootPart",60)
		
		if SpeedList:FindFirstChild(v.Name) then
			local NewX = HumanoidRootPart.Position.X
			local NewZ = HumanoidRootPart.Position.Z
			local OldX = SpeedList[v.Name].LastX
			local OldZ = SpeedList[v.Name].LastZ
			
			local DifferenceX = NewX - OldX.Value
			local DifferenceZ = NewZ - OldZ.Value
			
			if DifferenceX > 40 then -- max amount is 40
				HumanoidRootPart.Position = Vector3.new(OldX.Value,HumanoidRootPart.Position.Y,OldZ.Value)
			end
			
			if DifferenceZ > 40 then -- max amount is 40
				HumanoidRootPart.Position = Vector3.new(OldX.Value,HumanoidRootPart.Position.Y,OldZ.Value)
			end

			
			SpeedList[v.Name]:Destroy()
		else -- make a new folder with position and datstuff
			local NewFolder = Instance.new("Folder")
			NewFolder.Name = v.Name
			NewFolder.Parent = SpeedList
			
			local LastX = Instance.new("NumberValue")
			LastX.Name = "LastX"
			LastX.Value = HumanoidRootPart.Position.X
			LastX.Parent = NewFolder
			
			local LastZ = Instance.new("NumberValue")
			LastZ.Name = "LastZ"
			LastZ.Value = HumanoidRootPart.Position.Z
			LastZ.Parent = NewFolder
			
		end
		
	end
	wait(1)
end
local DifferenceX = math.abs(NewX - OldX.Value)
local DifferenceZ = math.abs(NewZ - OldZ.Value)
2 Likes

thanks this made it so it works in all directions now i think i need to make it more precise somehow for example i have the limit set to 40 but if i set my humanoid walkspeed to 35 it still triggers it is there a formula to figure out how studs per second or smth like that?

The walk speed is STS, I believe

ok good to know should i use this instead

if DifferenceX > Humanoid.WalkSpeed then

but in my game theres a sprint script thats local so it doesn’t change the humanoids actual walk speed should i make it on the server

Look, I’m not that Professional, but I believe this script can be circumvented by any exploiters, it’s simple, just deleting it, Depending on where it is, it may be that the person’s “Explorer” doesn’t have this location and it’s not possible delete it there.
I believe DarkDex People would delete it if they found out.

o forgot to mention this is in serverscriptservice lol

I don’t think they can delete things (nor access) things in SSS

  • the way you iterate over players is not recommended, use Players:GetPlayers() instead;
  • if a player somehow doesn’t have a HumanoidRootPart (e.g. an exploiter deletes it), your entire loop will stop (or halt for <= 60 seconds);
  • i don’t see why you wouldn’t use a table (instead of a folder) and numbers (instead of NumberValues) for this

ok i replaced the getchildren with getplayers

if not v.Character:FindFirstChild("HumanoidRootPart") then
			v:Kick("You dont have a humanoidrootpart lol")
		else
-- is dis good

tables are kinda confusing lol

keep in mind that it’s also possible for them to not have a character (if it checks them right as they are respawning)

also tables are way more memory efficient than instances

It is useful against some “Explorers”

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local SpeedList = ServerStorage.PlayerList.AntiCheat.Speed

Players.ChildAdded:Connect(function(child)
	for i,v in pairs(Players:GetChildren()) do
		local HumanoidRootPart = v.Character:WaitForChild("HumanoidRootPart",60)

		if SpeedList:FindFirstChild(v.Name) then
			local NewX = HumanoidRootPart.Position.X
			local NewZ = HumanoidRootPart.Position.Z
			local OldX = SpeedList[v.Name].LastX
			local OldZ = SpeedList[v.Name].LastZ

			local DifferenceX = math.abs(NewX - OldX.Value)
			local DifferenceZ = math.abs(NewZ - OldZ.Value)

			if DifferenceX > 40 then -- max amount is 40
				HumanoidRootPart.Position = Vector3.new(OldX.Value,HumanoidRootPart.Position.Y,OldZ.Value)
			end

			if DifferenceZ > 40 then -- max amount is 40
				HumanoidRootPart.Position = Vector3.new(OldX.Value,HumanoidRootPart.Position.Y,OldZ.Value)
			end


			SpeedList[v.Name]:Destroy()
		else -- make a new folder with position and datstuff
			local NewFolder = Instance.new("Folder")
			NewFolder.Name = v.Name
			NewFolder.Parent = SpeedList

			local LastX = Instance.new("NumberValue")
			LastX.Name = "LastX"
			LastX.Value = HumanoidRootPart.Position.X
			LastX.Parent = NewFolder

			local LastZ = Instance.new("NumberValue")
			LastZ.Name = "LastZ"
			LastZ.Value = HumanoidRootPart.Position.Z
			LastZ.Parent = NewFolder
		end
	end
end)

You shouldn’t be doing this in an infinite loop, instead in the above script I’ve opted to use the “ChildAdded” event on the players service folder, which is fired whenever a new child is added to the folder, resulting in the connected function being executed which performs all the same code which was present before.

This is a lot more efficient and will not enact unnecessary stress upon the server.