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)