Anti Aimbot / Aimlock detection

For more mega awesome detections join my AC discord

Info:

Instead of using complex trignometric functions or math.

Just detect when the player's camera is moving without the mouse moving. Simple, right?

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer

local lastCameraLook = nil
local isRotatingCamera = false
local gameStartTime = tick()
local lastDetectionDecreaseTime = tick() 
local initialDelay = 1
local lastMovementTime = 0 -- Last time mouse moved
local timeThreshold = 1 -- Time in seconds to wait before considering camera as "not moving"
local detections = 0 
local Detected = false 
local detectionDecreaseInterval = 1 

local camera = workspace.CurrentCamera
local lastMouseDelta = Vector2.zero

local isRotationInput = function(input)
	return input.UserInputType == Enum.UserInputType.MouseButton1 or
		input.UserInputType == Enum.UserInputType.MouseButton2 or
		input.UserInputType == Enum.UserInputType.MouseButton3 or
		input.KeyCode == Enum.KeyCode.Left or
		input.KeyCode == Enum.KeyCode.Right or
		input.KeyCode == Enum.KeyCode.Up or
		input.KeyCode == Enum.KeyCode.Down or
		input.KeyCode == Enum.KeyCode.Q or
		input.KeyCode == Enum.KeyCode.E
end

local isOnPC = function()
	return UserInputService.KeyboardEnabled and UserInputService.MouseEnabled and not UserInputService.TouchEnabled
end

local roundVector3 = function(v3) -- due to floating point precision issues
	return Vector3.new(
		math.round(v3.X * 10^4) / 10^4,
		math.round(v3.Y * 10^4) / 10^4,
		math.round(v3.Z * 10^4) / 10^4
	)
end

local connection:RBXScriptConnection;
local connection2:RBXScriptConnection;
local connection3:RBXScriptConnection;

local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local checkForAimbot = function()
	if detections > 75 and not Detected then
		Detected = true

		connection:Disconnect()
		connection2:Disconnect()
		connection3:Disconnect()

		LocalPlayer:Kick('Banned')

		return
	end

	if not Character then
		Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
		return
	end

	if tick() - gameStartTime < initialDelay then return end -- add a delay for loading in

	local currentCameraLook = roundVector3(camera.CFrame.LookVector)
	local MouseDelta = UserInputService:GetMouseDelta()

	-- Decrease detections over time (every detectionDecreaseInterval seconds)
	if tick() - lastDetectionDecreaseTime >= detectionDecreaseInterval then
		if detections > 0 then -- Only decrease if there are detections to decrement
			detections -= 1
			print(`Decreased detection count to: {detections} `)
			lastDetectionDecreaseTime = tick()
		end
	end

	if not lastCameraLook then
		lastCameraLook = currentCameraLook
		lastMovementTime = tick()
		return
	end

	if 
		currentCameraLook ~= lastCameraLook 
		and MouseDelta == Vector2.zero 
		and not isRotatingCamera 
		and not Character.Humanoid.Sit 
		and lastMouseDelta == Vector2.zero 
	then
		detections += 1
		print(`Detection: {detections}`)
		lastMovementTime = tick()
	elseif tick() - lastMovementTime > timeThreshold and not isRotatingCamera then
		return -- Camera hasn't moved significantly for a while and no rotation input.
	end

	lastMouseDelta = MouseDelta -- Update mouse delta for next frame check to prevent moving the mouse fast and stopping false flag.
	lastCameraLook = currentCameraLook -- Update camera look vector for next frame check.
end

if not isOnPC() then
	return
end
-- Input connections for detecting rotation input
connection = RunService.RenderStepped:Connect(checkForAimbot)

connection2 = UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if not gameProcessed and isRotationInput(input) then
		isRotatingCamera = true
	end
end)

connection3 = UserInputService.InputEnded:Connect(function(input, gameProcessed)
	if not gameProcessed and isRotationInput(input) then
		isRotatingCamera = false
	end
end)


Unproductive things not to say under this topic:

  • Just delete the script
  • Just hookfunction (INSERT FUNCTION NAME HERE)
  • Never trust the client
  • It only takes one person to bypass blah blah blah

I made this without ANY protection against hookfunctions, deleting the script, etc. These are your responsibility to protect the code since this is a RESOURCE. Instead of commenting this, try to identify weak points or false flags.

and yes obviously if the cheater artifically moves the mouse this wont work. instead of thinking just this think about how many hundreds of aimbot scripts dont do this

False Flags:

I have found 0 false flags that caused you to be kicked unless you move the camera externally.

Aimbot Script to pentest

Aimbot.rbxm (12.3 KB)

9 Likes

What if the player is using arrow keys to move the camera?

2 Likes
local isRotationInput = function(input)
	return input.UserInputType == Enum.UserInputType.MouseButton1 or
		input.UserInputType == Enum.UserInputType.MouseButton2 or
		input.UserInputType == Enum.UserInputType.MouseButton3 or
		input.KeyCode == Enum.KeyCode.Left or
		input.KeyCode == Enum.KeyCode.Right or
		input.KeyCode == Enum.KeyCode.Up or
		input.KeyCode == Enum.KeyCode.Down or
		input.KeyCode == Enum.KeyCode.Q or
		input.KeyCode == Enum.KeyCode.E
end

It checks for the arrow keys in the isRotationInput function.

1 Like

exploiters can simulate inputs
VirtualInputManager | Documentation - Roblox Creator Hub
VirtualInputManager | Roblox API Reference

2 Likes

Most aimbots/aimlocks are going to use mousemoverel which is a function built into most of the execution software out there. So they move the mouse, which moves the camera.

5 Likes

Hi, please read the full post.

6 Likes

Would this detect users that joined on computer then afterwards plug-ined a controller?

2 Likes

if you’re acknowledging that your script can be easily bypassed then why post it, I’m not trying to be mean, but this seems like more of a hassle for the developer than an anti-cheat. A decent amount of scripts already use VirtualInputManager and mousemoverel which @CompilerError said.

Not only that, but this makes any custom camera movement unusable, for example, camera sway or gun recoil.


side note, i just tested the script and even without any type of aimbot script being used its still “detecting” and kicks me

5 Likes

Hi, as stated before, this is a resource for competent anticheat developers. I mostly misspoke since it cannot be easily bypassed as you have to use an entire different category of aimbot to bypass it. (Mouse aimbot)

It doesn’t false flag unless you have something moving the camera without it being approved by the anti aimbot. If this still isn’t working try using it in a baseplate.

Wow, did not think of that.
This would probably fix it.

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer

local lastCameraLook = nil
local isRotatingCamera = false
local gameStartTime = tick()
local lastDetectionDecreaseTime = tick() 
local initialDelay = 1
local lastMovementTime = 0 -- Last time mouse moved
local timeThreshold = 1 -- Time in seconds to wait before considering camera as "not moving"
local detections = 0 
local Detected = false 
local detectionDecreaseInterval = 1 

local camera = workspace.CurrentCamera
local lastMouseDelta = Vector2.zero

local isRotationInput = function(input)
	return input.UserInputType == Enum.UserInputType.MouseButton1 or
		input.UserInputType == Enum.UserInputType.MouseButton2 or
		input.UserInputType == Enum.UserInputType.MouseButton3 or
		input.KeyCode == Enum.KeyCode.Left or
		input.KeyCode == Enum.KeyCode.Right or
		input.KeyCode == Enum.KeyCode.Up or
		input.KeyCode == Enum.KeyCode.Down or
		input.KeyCode == Enum.KeyCode.Q or
		input.KeyCode == Enum.KeyCode.E
end

local isOnPC = function()
	return UserInputService.KeyboardEnabled and UserInputService.MouseEnabled and not UserInputService.TouchEnabled
end

local roundVector3 = function(v3) -- due to floating point precision issues
	return Vector3.new(
		math.round(v3.X * 10^4) / 10^4,
		math.round(v3.Y * 10^4) / 10^4,
		math.round(v3.Z * 10^4) / 10^4
	)
end

local connection:RBXScriptConnection;
local connection2:RBXScriptConnection;
local connection3:RBXScriptConnection;

local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local checkForAimbot = function()
	if not isOnPC() then
		return
	end

	if detections > 75 and not Detected then
		Detected = true

		connection:Disconnect()
		connection2:Disconnect()
		connection3:Disconnect()

		LocalPlayer:Kick('Banned')

		return
	end

	if not Character then
		Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
		return
	end

	if tick() - gameStartTime < initialDelay then return end -- add a delay for loading in

	local currentCameraLook = roundVector3(camera.CFrame.LookVector)
	local MouseDelta = UserInputService:GetMouseDelta()

	-- Decrease detections over time (every detectionDecreaseInterval seconds)
	if tick() - lastDetectionDecreaseTime >= detectionDecreaseInterval then
		if detections > 0 then -- Only decrease if there are detections to decrement
			detections -= 1
			print(`Decreased detection count to: {detections} `)
			lastDetectionDecreaseTime = tick()
		end
	end

	if not lastCameraLook then
		lastCameraLook = currentCameraLook
		lastMovementTime = tick()
		return
	end

	if 
		currentCameraLook ~= lastCameraLook 
		and MouseDelta == Vector2.zero 
		and not isRotatingCamera 
		and not Character.Humanoid.Sit 
		and lastMouseDelta == Vector2.zero 
	then
		detections += 1
		print(`Detection: {detections}`)
		lastMovementTime = tick()
	elseif tick() - lastMovementTime > timeThreshold and not isRotatingCamera then
		return -- Camera hasn't moved significantly for a while and no rotation input.
	end

	lastMouseDelta = MouseDelta -- Update mouse delta for next frame check to prevent moving the mouse fast and stopping false flag.
	lastCameraLook = currentCameraLook -- Update camera look vector for next frame check.
end

-- Input connections for detecting rotation input
connection = RunService.RenderStepped:Connect(checkForAimbot)

connection2 = UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if not gameProcessed and isRotationInput(input) then
		isRotatingCamera = true
	end
end)

connection3 = UserInputService.InputEnded:Connect(function(input, gameProcessed)
	if not gameProcessed and isRotationInput(input) then
		isRotatingCamera = false
	end
end)

yeah, it was labeled as a anti aimbot but you were still able to use aimbot with it

I found the issue I thought it edited it in, but I guess I forgot. anyways it was because I had my camera mode to follow which makes the camera follow the character, this is a default camera mode and is pretty commonly used, especially among mobile users


looking more into it, follow is the default setting for mobile


something else that popped up in my mind, what happens if you join in vr

Pretty sure most rage aimbots would get flagged by this, and while it may not flag 99.99% of all aimbots to exist, still a cool resource regardless :+1:

There is no 100% detection for every aimbot.

Didn’t think of that. Try VRService.VREnabled

1 Like

I wonder what would happen if I were to play on my surface laptop studio (with touch enabled)

One thing comes to mind, hooks. Many ways to hook.

The thing that stood out the most (because it’s quite common) is remote metamethod hook. Since a secure gun/projectile system requires a remote to shoot, it can easily be tampered. Just hook it so whenever the remote fired, then overwrite the arguments to shoot at the closest player to your cursor within a radius. I believe this is known as silent aim

this is a method to detect anti aimbot, and it doesnt send any remotes.

1 Like

I know, what I’m trying to say is, this is very bypassable, just do what I said and your detection method is unreliable. As I have said, a gun/projectile system has a remote to shoot, which can be tampered (unless you want your system to be fully client sided for some reason?)

Silent aim doesn’t tamper with the camera or mouse, it intercepts shoot remote calls.

So without changing or adding anything, silent aim will just pass right through

Unproductive things not to say under this topic:

  • Just delete the script
  • Just hookfunction (INSERT FUNCTION NAME HERE)
  • Never trust the client
  • It only takes one person to bypass blah blah blah

I made this without ANY protection against hookfunctions, deleting the script, etc. These are your responsibility to protect the code since this is a RESOURCE.

:thinking:

If we are talking about practicality here, this has the same energy as straight up telling people to make their own detection from scratch. It doesn’t contribute much if 99% of the effort goes into trying to circumvent the most common bypass methods. Don’t get me wrong, it’s great that you showed us how it works, but not really a way on how to use it effectively in a production setting which is what people really needed. Everyone is going to immediately hit a two kilometer long roadblock trying to implement this

Now that you mentioned it, think of how many hundreds of aimbot developers will see this thread and update their script specifically to add mouse movement emulation

Harsh reality is that the best anticheat is one that isn’t public

1 Like

Thanks a lot for this, as a new developer I’ve spent a while wondering how this could be achieved, thanks!