Do you see any obvious flaws in this anti fly exploit script?

Greetings,

I am making a script to prevent flying exploits in game and this is what i came up with.

It’s all server side, every second i fire a ray below the player long enough to not be triggered by jumping, if this ray fails to hit anything, then an invisible explosion is created at their feet, if it hits something then it’s all good, if it doesn’t then it adds 1 to the number of detections, these detections are reset to 0 every 45 seconds, if they reach 10 then the player is respawned(probably will be tp in final version) and the count is back to 0. The goal is not to punish flying in order not to hurt legitimate players but to make it useless so that they stop trying to exploit.

I’ve not done any extensive testing, there maybe be need to adjust some values, however,
my main concerns are,

  • how will this affect performance
  • is there an obvious loophole
  • is this overall a poor strategy
  • will this actually be effective
  • should i add a listener for body movers in the character as well

Thank you for your time

local WaitCalculator = require(ReplicatedStorage.WaitCalculator) --fastwait by Clonetrooper1019
local Detections = game:GetService("ServerStorage").Detections --folder containing number values for each player

local function CreateExplosion(Position, character)
	
	local Explosion = Instance.new("Explosion")
	Explosion.Position = Position
	Explosion.BlastPressure = 0
	Explosion.BlastRadius = 5
	Explosion.DestroyJointRadiusPercent = 0
	Explosion.ExplosionType = Enum.ExplosionType.NoCraters
	Explosion.Visible = false
	Explosion.Parent = workspace
	
	local hitsomething = false 				--start with a false
	
	Explosion.Hit:Connect(function(hit)
		
		if hitsomething then return end
		
		if hit:FindFirstAncestorWhichIsA("Model") ~= character then
			
			hitsomething = true					--if it hit something change it to true

		end
		
	end)
	
	WaitCalculator(.1)							--wait a bit for explosion hit to register
	
	if hitsomething == false then				--if it stayed false then no hits
		
		Detections:FindFirstChild(character.Name).Value += 1 
                                       --add 1 detection to their detection count
		print(Detections:FindFirstChild(character.Name).Value)
	end
	
	Explosion:Destroy()							--destroy the explosion(the automatic cleanup is too slow)
	
end

Detections.ChildAdded:Connect(function(child)	--do some stuff when a player's detection count is added to the folder
	
	child.Changed:Connect(function()
		
		if child.Value == 10 then	--if they reach maxium detection count
			
			Players:FindFirstChild(child.Name):LoadCharacter()--reset their character
			
			child.Value = 0		--reset count to 0
			
		end
		
	end)
	
	while true do
		
		WaitCalculator(45)--reset count every 45 seconds to 
		                              --reduce chance of false positives
		child.Value = 0
		
	end
	
end)

Players.PlayerAdded:Connect(function(player)
	
	local Connection
	
	local DetectionCount = Instance.new("NumberValue")	--add their detection count to the folder
	DetectionCount.Value = 0
	DetectionCount.Name = player.Name
	DetectionCount.Parent = Detections
	
	player.CharacterAdded:Connect(function(character)
		
		Connection = character.AncestryChanged:Connect(function(child, parent) --make sure the the character is in workspace
			
			if parent == workspace then		--if the parent is workspace then start a loop
				
				while character.Parent ~= nil do --while the parent is workspace run the loop

					WaitCalculator(1)
			
					local RaycastingParams = RaycastParams.new()
					RaycastingParams.FilterType = Enum.RaycastFilterType.Blacklist
					RaycastingParams.FilterDescendantsInstances = {character, workspace.Folder}
									
					local Center = character.LowerTorso.WaistCenterAttachment.WorldPosition
					local Root = character.HumanoidRootPart.Position
						
					local RayCastResult = workspace:Raycast(Center, CFrame.new(Center, Center + Vector3.new(0,-1,0)).LookVector * 10, RaycastingParams)

					if RayCastResult then 
						--there is a part below them
					else-------------------------------------------

						CreateExplosion(Center + CFrame.new(Center, Center + Vector3.new(0,-1,0)).LookVector * 3, character)
						--if no part below then create an explosion at their feet
					end
				
				end
			
			else
				
				Connection:Disconnect() -- if the ancestry changed and the parent is not workspace then disconnect
				
			end
	
		end)
		
	end)
	
end)

Players.PlayerRemoving:Connect(function(player)
	
	Detections:FindFirstChild(player.Name):Destroy()  --remove the detection count from the folder
	
end)
2 Likes

It’s hard to read the code because it’s not formatted correctly.

2 Likes

what do you mean? i’d be happy to edit

Put all the code like this:
image

So that it looks like this:

-- amogus
print('It\'d look like this')
2 Likes

aah sry, i always forget that’s a thing on the forum

1 Like

Try to format your code by the ROBLOX Lua conventions (see Roblox Lua Style guide). This will make your code easier to read. Also, your code style will become more consistent.

Why wait for an explosion to hit something if you already have a callback for explosion.Hit? The callback already gets the thing that you hit as a parameter.

1 Like

ahh well my style is pretty consistent and readable to me :frowning: i guess it’s not for others, but i separate most lines because it makes it easier for me to see.

As for the wait, well correct me if i’m wrong, but woudn’t it check if hitsomething is false as soon as possible if i didn’t add that wait? meaning the explosion could go off after i check if it’s false

EDIT: indeed i’ve just tested and it does not register a hit without the wait

Won’t this blow someone up if they jump off a fence or whatever? Ten studs off the ground is not a particularly hard height to reach.

1 Like

this is why it takes 10 detections before any action is taken, and the number of detections is reset every 45 seconds to stop such incidents from stacking up and causing a false positive

It is better to follow the code style conventions, since it will allow others to read your code with more ease. You do not have to take this too seriously, cause this is rather just a pro tip.

This is probably not an issue as your script is not triggering any intensive processes.

In this case, you should generally avoid to use wait(), since it is not the prettiest solution (and not required I think).

You can improve your code by dividing bits of functionality into functions, so that it is easier to understand and read.

1 Like

i see we’ll i’ll take it to heart, obviously i’ll benefit from a style that is consistent with others

i’m glad to hear you think it won’t impact performance, i’m unsure how much resources explosions demand

well this is why i use the wait module by clonetrooper1019 which is a timer using runservice

as for the last bit, yes that’s a valid point i’ll change that now

thank you for taking the time to review my script

There’s a lot of stuff to unpack in the script, but I would like to point out that there are a lot of memory leaks caused by creating connections inside connections.

how can i get around this? Where am I going wrong? I disconnect each one at some point