Any comments on my Walkspeed detection? (Exploit Speed Detection)

This is my first attempt at making a walkspeed detector. Any comments or suggestions?
(I am using Thread Util as an alternative to spawn(function() as I am not familiar with using coroutines)

Note: This doesn’t account players being moved by an object or walking on a moving platform yet.

game.Players.PlayerAdded:Connect(function(plr)
	local Noitice = 0
	local Flags = 0
	local HeadStart = 0
	
	local function CharacterAdded(Character)
		local Humanoid = Character:WaitForChild("Humanoid")
		local RootPart = Character:WaitForChild("HumanoidRootPart")
		
		local startedTime = tick()
		local startedPos = RootPart.Position
		local distCovered = ( (RootPart.Position - startedPos ) * Vector3.new(1,0,1) ).magnitude
		
		local Loop
		Loop = Thread.DelayRepeat(0.1, function()
			distCovered = ( (RootPart.Position - startedPos ) * Vector3.new(1,0,1) ).magnitude
			startedPos = RootPart.Position
			
			if Humanoid:GetState() ~= Enum.HumanoidStateType.Seated
				or Humanoid:GetState() ~= Enum.HumanoidStateType.Climbing 
				or Humanoid:GetState() ~= Enum.HumanoidStateType.Ragdoll 
				or Humanoid:GetState() ~= Enum.HumanoidStateType.FallingDown then
				
				if distCovered == 0 and startedTime ~= nil then
					startedTime = tick()
					-- Standing, reset tick
				elseif distCovered > 0 and startedTime ~= nil then
					-- Running
					if math.round(distCovered / (tick() - startedTime)) == Humanoid.WalkSpeed then
						Noitice = 0 -- If distance covered is the same as Humanoid Walkspeed then reset Notice
					elseif math.round(distCovered / (tick() - startedTime)) > Humanoid.WalkSpeed 
						and math.round(distCovered / (tick() - startedTime)) ~= 0 then
						
						HeadStart += 1 -- When the player first joins the game give them 1.5 sec until walkspeed is detected
						if HeadStart >= 15 then
							HeadStart = 15
							Noitice += 1
							if Noitice == 10 then -- After 1 sec of consecutive Walkspeed change, flag the player
								Flags += 1
								print("Flagged!")
							end
						end
						print("Diff Walkspeed", Flags)
					end
				end
			end
			
			startedTime = tick()
		end)
		
		Humanoid.Died:Connect(function()
			startedTime = tick()
			Noitice = 0 -- When the player dies, reset Notice and disconnect Loop
			Loop:Disconnect()
		end)
	end
	
	local character = plr.Character or plr.CharacterAdded:wait()
	Thread.Spawn(function()
		CharacterAdded(character)
	end)
	
	plr.CharacterAdded:Connect(CharacterAdded)
end)
2 Likes

Why u dont make only

local character = -- character
while true do
   wait()
   if character.Humanoid.WalkSpeed > 16 then
      print(character.Humanoid.WalkSpeed)
   end
end
2 Likes
local Player = PathToPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

Humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
    if Humanoid.WalkSpeed > 16 then
        print(Humanoid.WalkSpeed)
    end
end)

don’t use a loop for this

2 Likes

Oh ok, thank you, before I didn’t know about the

That wouldn’t work because the server cannot detect walkspeed changes on the client, which is why I am using distance to calculate how fast the player is moving.

7 Likes

This seems like an unneeded psudothread you’re spawning. The function does not yield, therefore you should not treat it as it is.


Now, for the code itself: it’s not great, to be honest.

There are a large number of issues, which I’ll list:

  • No edge cases for different frame times – you assume the loop will be exactly 0.1 time, every time.
  • A complex solution to a simple problem; use RunService instead of a loop.
  • No flexibility for changes. Always make it easy for yourself, both present and future!
  • Repeated code where it doesn’t need to be repeated.
  • Other issues that break [programming rules](https://clone:SetPrimaryPartCFrame(cframe) clone.Parent = game.Workspace), such as improper variable/function naming, no exception handling, etc.

Walkspeed does not replicate across the server-client boundary. Instead, you have to find the delta between the positions to estimate a speed.

1 Like

But the client (local script) can detect the walkspeed if it’s changed in client

Exploiters can easily delete the localscript, defeating the whole purpose of an anti-cheat

8 Likes

Just calcualte the speed the player moves at, this would anti all kinds if speed glitches and teleports, dont ban players from this though as there are still ways roblox physics can fling a player.

Speed = Distance / Time

You can also add a checker so that you can allow your own scripts to stop it or alter the speed. This means even with games where you give the players speed or teleport them they cant get around your set limits.

This means nothing will need to be on the client so it wont be bypassable either

If you look at one of my recent posts you can find how I have done it.

2 Likes

To add more protection you could have a client script which bans/kick the player since many exploiters are just firing random paste bin scripts and won’t be able to do anything about it. Would help if you put it inside a main client script so they can’t just find a script which is called “no walkspeed” or “anti exploit” and delete it.

Do not attempt client always trust the server the client is in hands of the hacker the rule is
my client == my rules

to catch players use velocity checks and sanity checks
and to protect innocent players from getting banned use a code that allows you to bypass

but never try on the client if it works then it gets patched

Although your implementation is rather good, it is not foolproof. Never trust humanoid states, they can be spoofed from the client. An exploiter can change their state to Seated, Climbing, Ragdoll or FallingDown and use their advantage of network ownership to fly or use other movement-enhancing exploits.

There are methods to solve this issue, such as implementing sanity checks for each state to ensure that conditions are met and followed for each of the states, such as being able to identify how a player falls. You can also sometimes disregard the negative change in a player character’s Y coordinates as that is a simple solution to prevent falling from being tagged.

As others have stated, never rely on client anticheats. Work on your serversided checks and experiment with different concepts of being able to detect cheats and to justify normal behavior.

1 Like

True but the “hacker” 90% of the time is running a random pastebin script and has no clue on how anti exploits work.

The client side one is only to stop the 90% and the server side is to prevent the other 10% from exploiting.

This is true, to an extent.
99% of exploiters are script kiddies who don’t know what a variable is.
1% of exploiters are talented programmers who usually distribute specialised exploits for x game.

Your security will always get bypassed if there is enough need.

5 Likes

What I do is listen to the humanoid state change on the server and check that humanoid walkSpeed and if any of the stats that I contain in a table are greater then they are supposed to be I ban the player. As this could get mistaken for a player who may of accidentally gotten flunged.

Still most dont use random pastebin stuff they use scripts from a popular site known as [DATA EXPUNGED - link has been erased user can’t acess removing traces…]
which has a big community even most videos link it the codes they provide has best anti exploit breaker and help guides to help get rid of anti script if the code can’t do it automatically and you got to do it manually.

still client scripts may work but they are not the best for long term solution and dont put your anti script bulk on it

Client anticheats are a complete waste of time, it is factual that they cannot in any meaningful way prevent exploiters. The simple truth is that by developing both a client-sided and server-sided anticheat you waste time on infinite hopeless client sanity-checks which can reduce performance and disregard that about infinite methods there are to achieve advantageous behavior.
Server anticheats function very differently from client-sided ones. With serversided ones you mainly aim for logical checks to ensure that the client complies with laws of movement and Roblox physics, thus making your anticheat reliable and fairly small. The result of a good serversided anticheat is that you are practically able to stop most or all movement exploits and make your entire system unbypassable, meanwhile all client-sided anticheats can be bypassed.
The client has untold power, exploits themselves enhance this power even more. Exploits are able to manipulate property and function indexes, intercept remote events, disable scripts, alter physics and more. It is simply futile to attempt to control an environment which is way more powerful than your scripts.

1 Like

Exactly but most exploiters don’t even know that half of that is possible.
Ofcourse it’s a waste of time making an in depth client sided exploit.
A simple ban/kick on walkspeed change for the percentage of users who can’t (or haven’t yet) bypassed it. It has to be combined with a server side anti exploit.
Just a simple if statement and boom. half of all the exploiters in your game are gone. The other half has to be warded off with server anti cheats.

1 Like

I hope you realize how you’re contradicting yourself. If you have a sufficient serversided anticheat you do not need to provide “special treatment for the 80%”. It is not just a waste of time to develop an “in-depth” client-sided anticheat, it is a waste of time to make one in the first place. There is no logical reason to have one if your serversided variant is effective. The practice you’re suggesting is bloated and bad practice, simple as that.

1 Like

I never meant to say that you should only rely on client side exploits.
There’s always going to be false positives considering lower spec devices and bad internet connections might behave suspiciously for the server side detection. In my opinion something is better than nothing.