ClientSide Hitbox Checks?

Since I create Hitboxes on the Client, I’m concerned of Exploitation as I dont have any checks to prevent lag switching, hitbox expanding etc…

I know there are multiple solutions, However I am looking for the most Convenient/Most suited for my situation

The Project Im Having Trouble On:
Definitive Battlegrounds

Solution Examples:

Solution Examples

Magnitude Checks…
Max Hitbox Size…
RunService Checks…

Resources I Use:

Resources

MuchachoHitbox(Located In Replicated Storage)

FastSignal (Used to communicate between related client controllers.)

Maid (Used to clean any discontinued or cancelled hitbox, As well as managing the spawn functions for the Hitboxes)

Template Module For Hitboxes ( What I Require to Create Hitboxes)
HitboxTemplates.rbxm (2.0 KB)

Hitbox Code:

Code

Functions

local HitboxTemplate = {}

HitboxTemplate.__index = HitboxTemplate 

--//Services
local Players = game:GetService("Players")
local DebrisService = game:GetService("Debris")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local StarterPlayer = game:GetService("StarterPlayer")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")


--//Modules
local Modules = ReplicatedStorage.Modules

local HitboxModule = require(Modules.Hitbox.Hitbox)

local BaseTemplates = require(script.Base)

local MaidModule = require(Modules.Utility.Maid)
local Maid = MaidModule.new()


--//Hitboxes{}


--//M1 Hitbox
function HitboxTemplate:M1Hitbox(RootPart,Humanoid,Sound)
	BaseTemplates:Hitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,2)
	BaseTemplates:SoundHitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,Sound)
end

function HitboxTemplate:DashHitbox(RootPart,Humanoid,Sound)
	BaseTemplates:Hitbox(RootPart,Humanoid,.4,Vector3.new(4,5,4),CFrame.new(0,0,-3),.2,4)
	BaseTemplates:SoundHitbox(RootPart,Humanoid,.4,Vector3.new(4,5,4),CFrame.new(0,0,-3),.2,Sound)
end

function HitboxTemplate:GroundSlamHitbox(RootPart,Humanoid,Sound)
	BaseTemplates:Hitbox(RootPart,Humanoid,.1,Vector3.new(5,5,4),CFrame.new(0,0,-3),.1,4)
	BaseTemplates:SoundHitbox(RootPart,Humanoid,.1,Vector3.new(5,5,4),CFrame.new(0,-1,-3),.1,Sound)
end


--//SkillHitbox

--Hero
function HitboxTemplate:CleaveHitbox(Character,RootPart,Humanoid,Sound)
	BaseTemplates:MoverEnemyHitbox(Character,RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,5)
	BaseTemplates:SoundHitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,Sound)
end

function HitboxTemplate:SplitHitbox(RootPart,Humanoid,Sound)
	BaseTemplates:Hitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,2)
	BaseTemplates:SoundHitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,Sound)
end

function HitboxTemplate:RushHitbox(RootPart,Humanoid,Sound)
	HitboxTemplate:Hitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,2)
	HitboxTemplate:SoundHitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,Sound)
end

function HitboxTemplate:TwoFoldKickHitbox(RootPart,Humanoid,Sound)
	BaseTemplates:Hitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,2)
	BaseTemplates:SoundHitbox(RootPart,Humanoid,0,Vector3.new(4,5,4),CFrame.new(0,0,-3),.1,Sound)
end

return HitboxTemplate

Base Hitbox Creation

local BaseTemplates = {}

BaseTemplates.__index = BaseTemplates 

--//Services
local Players = game:GetService("Players")
local DebrisService = game:GetService("Debris")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local StarterPlayer = game:GetService("StarterPlayer")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")


--//Modules
local Modules = ReplicatedStorage.Modules

local HitboxModule = require(Modules.Hitbox.Hitbox)
local CooldownModule = require(Modules.Utility.Cooldown)

local BodyMover = require(Modules.Character.Utility.BodyMover)

local MaidModule = require(Modules.Utility.Maid)
local Maid = MaidModule.new()


function BaseTemplates:Hitbox(RootPart,Humanoid,DelayBeforeStart,Size,Offset,Duration,Damage)

	Maid:GiveTask(task.spawn(function()
		
		task.wait(DelayBeforeStart)
		
		local Hitbox = HitboxModule.CreateHitbox()
		
		Hitbox.Size = Size
		Hitbox.Offset = Offset
		Hitbox.CFrame = RootPart

		Hitbox.Touched:Connect(function(Part)
			local Enemy = Part.Parent
			local EnemyHumanoid = Enemy:WaitForChild("Humanoid")

			if EnemyHumanoid ~= Humanoid then
				EnemyHumanoid:TakeDamage(Damage)
			end

		end)


		Hitbox:Start()
		task.wait(Duration)
		Hitbox:Stop()
		
	end))
end

function BaseTemplates:MoverEnemyHitbox(Character,RootPart,Humanoid,DelayBeforeStart,Size,Offset,Duration,Damage)

	Maid:GiveTask(task.spawn(function()
		
		task.wait(DelayBeforeStart)
		
		local Hitbox = HitboxModule.CreateHitbox()
		
		Hitbox.Size = Size
		Hitbox.Offset = Offset
		Hitbox.CFrame = RootPart

		Hitbox.Touched:Connect(function(Part)
			local Enemy = Part.Parent
			local EnemyHumanoid = Enemy:WaitForChild("Humanoid")
			local EnemyRootPart= Enemy:WaitForChild("HumanoidRootPart")

			if EnemyHumanoid ~= Humanoid then
				EnemyHumanoid:TakeDamage(Damage)
				BodyMover:EnemyFaceCharacter(Character,Enemy,"HumanoidRootPart","HumanoidRootPart",Vector3.new(0,-180,0),.5)
			end

		end)


		Hitbox:Start()
		task.wait(Duration)
		Hitbox:Stop()
		
	end))
end

function BaseTemplates:SoundHitbox(RootPart,Humanoid,DelayBeforeStart,Size,Offset,Duration,Sound)

	Maid:GiveTask(task.spawn(function()
		
		task.wait(DelayBeforeStart)
		
		local Hitbox = HitboxModule.CreateHitbox()
		
		Hitbox.Size = Size
		Hitbox.Offset = Offset
		Hitbox.CFrame = RootPart

		Hitbox.Touched:Connect(function(Part)
			local Enemy = Part.Parent
			local EnemyHumanoid = Enemy:WaitForChild("Humanoid")

			if EnemyHumanoid ~= Humanoid then
				Sound:Play()
			end

		end)


		Hitbox:Start()
		task.wait(Duration)
		Hitbox:Stop()
		
	end))
	
end

return BaseTemplates

Client Code To Run Hitbox

		Maid:GiveTask(task.spawn(function()

			local CurrentHitSound = M1HitSounds:FindFirstChild(OldM1)

			task.wait(0.1)

			HitboxTemplates:M1Hitbox(RootPart,Humanoid,CurrentHitSound)
			
		end))

Honestly the best solutions I’ve found for stuff like this is basic magnitude checks and player report system.

Ah thank you, do you have any examples of a magnitude check?

Currently I am doing:

if (RootPart.Position - EnemyRootPart.Position) .Magnitude <= Size.Z +1 then
1 Like

+1 is way too low. You need to determine what a proper upper bound for distance could be if the player is on high ping and their movements aren’t the most accurate or you will run into a ton of false positives. Basically get the fastest speed a player can move at (dashing or whatever) and then set their ping really high and test out different max bounds until you get one with 0 false positives. Magnitude check is only really useful to figure out if the exploiter is on the other side of the map killing people, but other than that it’s not the best because of lag.

1 Like