Artic's Anti-WalkSpeed - Detecting and punishing illegal walkspeed using players


Hello Developers!

Introduction

What are we talking about today?


Today I’d like to introduce to you my Anti-WalkSpeed detection system which also punishes players by kicking them but anyways you are going to be allowed to change my code and use it for free as it is an open-source as well in which everyone can contribute at it at GitHub. I also designed an automatic detection of calling your default game walk speed by checking the server-sided walk speed and not client one, so basically everything you have to do is just paste the script in ServerScriptService and I am completely serious about it. :slight_smile:

Functionality

How does this anti-exploit even work?


I am going to start with an idea about which values this anti-exploit creates. It creates three values, first one is to determine which player we are checking in-game, second is int value which determines how much time passed since the last update of third value which determines how many times this anti-exploit caught player exploiting. Of course, I added a reset in the script so that’s why I added those two values as well. Now let’s go on the basic anti-exploit system which is constantly every second detecting local player’s position and it calculates the magnitude out of it. We know that default walk speed determines how many studs player creates by max. For example: 16 is set as default walk speed and that means that player can maximum creates 16 studs every second. Then when we have magnitude calculated we compare it with the local player’s walk speed from the server-side of course. At the same time, we check if the player is touching the ground and not the air so we get rid of Roblox’s bounces which are pretty popular nowadays. If the player passes all of those values then anti-exploit adds a (+1) value to caught value, the max value of those is 3 by default in the script which you can change it on your own.

Documentation and source code


local MaxCaughts = 3 -- This is max value of how many times anti-exploit can detect player exploiting.

local MaxSinceLastCaughtChange = 10 -- This is max time for how long 'caughts' value wasn't changed.

--IMPORTANT: You can leave everything by default this Anti-Exploit is going to automatically detect what is your game's default WalkSpeed by reading the walk speed from server-side.

--               _   _      _                      _   _     __          __   _ _     _____                     _ 
--    /\        | | (_)    ( )         /\         | | (_)    \ \        / /  | | |   / ____|                   | |
--   /  \   _ __| |_ _  ___|/ ___     /  \   _ __ | |_ _ _____\ \  /\  / /_ _| | | _| (___  _ __   ___  ___  __| |
--  / /\ \ | '__| __| |/ __| / __|   / /\ \ | '_ \| __| |______\ \/  \/ / _` | | |/ /\___ \| '_ \ / _ \/ _ \/ _` |
-- / ____ \| |  | |_| | (__  \__ \  / ____ \| | | | |_| |       \  /\  / (_| | |   < ____) | |_) |  __/  __/ (_| |
--/_/    \_\_|   \__|_|\___| |___/ /_/    \_\_| |_|\__|_|        \/  \/ \__,_|_|_|\_\_____/| .__/ \___|\___|\__,_|
--                                                                                         | |                    
--                                                                                         |_|                    

game:GetService("Players").PlayerAdded:Connect(function(plr)
	
	local PlayerName = Instance.new("StringValue") -- Just a value to determine localplayer name
	PlayerName.Parent = script
	PlayerName.Name = plr.Name
	
	local SinceLastChange = Instance.new("IntValue")
	SinceLastChange.Parent = PlayerName
	SinceLastChange.Name = "SinceLastChange"
     
    local counter = Instance.new("IntValue") -- Anti-Exploit detection caughts 
    counter.Parent = PlayerName
    counter.Name = "Counter"
	
	plr.CharacterAdded:Connect(function(char)
		
		while true do
			
			SinceLastChange.Value = SinceLastChange.Value + 1
			
		     if counter.Value ~= 0 then -- if counter variable is not 0
			   if SinceLastChange.Value > MaxSinceLastCaughtChange then -- If time from last change is higher than selected variable then
				   counter.Value = 0 -- set counter to 0
				   SinceLastChange.Value = 0 -- set time from last change to 0
			    end
			  end
			
			if char:FindFirstChild("HumanoidRootPart") ~= nil then
			local FirstCFrame = char:FindFirstChild("HumanoidRootPart").Position -- Get player's first position
			wait(1)
			local SecondCFrame = char:FindFirstChild("HumanoidRootPart").Position -- Get player9s second position after wait(1)
			
			local CFrameDifference = (FirstCFrame - SecondCFrame).Magnitude --Get the difference of positions
			
			if CFrameDifference < 0 then -- If difference is below 0
				local CFrameDifference =  (FirstCFrame - SecondCFrame) * (-1) -- Change it to positive value
			end
			
			if char:FindFirstChild("Humanoid") then --If Humanoid exists then
				local LocalWalkspeed = char:FindFirstChild("Humanoid").WalkSpeed -- Get players local walkspeed (local walkspeed determines how many studs player create on second)
                if math.floor(CFrameDifference) > LocalWalkspeed then -- If difference of positions is higher then his local walkspeed then
	                if char:FindFirstChild("Humanoid").FloorMaterial ~= Enum.Material.Air then -- If player is touching the ground
		                counter.Value = counter.Value + 1 -- Add a caught to counter
	                end
                end
			end
			
			if counter.Value > MaxCaughts then -- If player passes max counter then
				if char:FindFirstChild("Humanoid") then -- If Humanoid still exsits
					warn("Exploit detected at player: " .. plr.Name) -- warn it to console
					plr:Kick("We caught you exploiting.") -- Kick player from game
					-- Do whatever you want to do to player who was detected exploiting
					if script:FindFirstChild(plr.Name) then 
					   script[plr.Name]:Destroy() -- Destroy player from script in ServerScriptService (IMPORTANT: Make sure you keep this in this if statment)
					   break
				    end
				end
		     end
				 
			  else
				
			if char:FindFirstChild("Humanoid") then -- If Humanoid still exsits
					warn("Exploit detected at player: " .. plr.Name) -- warn it to console
					plr:Kick("We caught you exploiting.") -- Kick player from game
					-- Do whatever you want to do to player who was detected exploiting
					if script:FindFirstChild(plr.Name) then 
					   script[plr.Name]:Destroy() -- Destroy player from script in ServerScriptService (IMPORTANT: Make sure you keep this in this if statment)
					   break
				    end
				end
			end
		end
	end)
end)

False positives

Those are only going to be seen if player is bounced and is touching the ground at the same time.


License

I use MIT License in this open source which means you have permissions to:

:white_check_mark: Commercial use
:white_check_mark: Modification
:white_check_mark: Distribution
:white_check_mark: Private use

:x: Liability
:x: Warranty


As this is everything I have to say for you guys, I hope you are having an amazing Christmas.
And most importantly from me,
Stay creative everyone! :herb:

5 Likes
local CFrameDifference = (FirstCFrame - SecondCFrame).Magnitude --Get the difference of positions

if CFrameDifference < 0 then -- If difference is below 0
	local CFrameDifference =  (FirstCFrame - SecondCFrame) * (-1) -- Change it to positive value
end

You are making a new local called CFrameDifference inside of the do block, which doesnt change anything. I reccomend changing it to this:

local CFrameDifference = math.abs((FirstCFrame - SecondCFrame).Magnitude) --Get the difference of positions
1 Like

What exactly do you mean by it doesn’t change anything? I mean my idea still works but yeah I didn’t know about this function so yeah maybe it would be a better idea. Thank you for contribution.

It doesn’t change anything because you are setting it as a local inside of the if statement instead of just assigning it to the new value.

It’s worth noting that the GPL license is a “viral” license. If you include GPL-licensed code in your project, your project is considered a “derivative work” and also subject to the terms of the GPL license. This means if you distribute this code to others (i.e., you have it as a LocalScript in your game) then you are obligated to make the source of your game available to them.

This is distinct from most other open source licenses, like MIT, Apache2, MPLv2, which do not have this “viral” nature.

You should always be aware of the terms of licenses of code you use. This isn’t legal advice though, talk to a lawyer if you want to be sure.

7 Likes

Thank your for reply about this. I will try my best to fix that. I didn’t really know that so I’ll change it today for sure.

1 Like

You haven’t changed the license to this to a less restrictive variant, so until then I will not use this in my game.

1 Like

I am sorry but I totally forgot about this. I am going to change it right now, I was also stressed this month with studying and depression at the same time. It would be nicer to DM me about this but anyways thanks for your warning. I hope you do understand my absent.

3 Likes

I see two problems with this, the first being a minor bad practice, setting parent before setting properties. It’s the same as using Instance.new with the parent argument, which could cause delays. The second problem is that exploiters can delete their Humanoid if they wanted (It replicates thanks Roblox.) making your detection completely useless. You can simply check ChildRemoved to see if they remove their Humanoid while alive.
also pls fix your indention.

1 Like