Review on some hitbox thigny

Was thinking about combat warriors and was thinking about how they probably handle hit detection on client for it to be that accurate

So with the only thing in mind of making some sort of hitbox that has detections on client i tried making one

Only works for tools (Somewhat) but overall it works
(no debounce / range check currently as i just was working on getting it to work in general)

Code

Module script

-- Variables
local Hitboxes = {}
local Event = script.HitboxEvent
local SendOnlyHumanoids = true

-- Functions
local function StartingHitbox(hb, t)
	if not Hitboxes[hb] or Hitboxes[hb] ~= true then Hitboxes[hb] = true end
	if not Hitboxes[hb] and Hitboxes[hb] ~= true then Hitboxes[hb] = true end
	
	while task.wait(.01) do
		if Hitboxes[hb] and Hitboxes[hb] == true then
			local ThingsTouching = workspace:GetPartsInPart(hb, if t["Op"] then t["Op"] else OverlapParams.new())   --workspace:GetPartBoundsInBox(hb.CFrame, hb.Size, if t["Op"] then t["Op"] else OverlapParams.new())
			if #ThingsTouching > 0 then
				if SendOnlyHumanoids == true then
					local temptable = {}
					for i,v in ipairs(ThingsTouching) do
						if v.Parent:FindFirstChild("Humanoid") and not table.find(temptable, v.Parent) then
							table.insert(temptable, v.Parent)
						end
					end
					if #temptable > 0 then Event:FireServer(temptable) end
				else
					Event:FireServer(ThingsTouching)
				end
			end
		else
			break
		end
	end
end

local function AttachPositions(Model)
	local PartSize, PartPosition = nil, nil
	
	local PartSize = Model:GetExtentsSize()
	local PartPosition = Vector3.new(
		Model:GetPivot().X,
		Model:GetPivot().Y,
		Model:GetPivot().Z
	)
	
	return PartSize, PartPosition 
end


-- Module
local HitBoxM = {}
HitBoxM.__index = HitBoxM

HitBoxM.CreateHitbox = function(Tool : Tool, Model : Model)
	local tabled = {}
	local PartHitbox = Instance.new("Part")
	PartHitbox.Anchored = true
	PartHitbox.CanCollide = false
	PartHitbox.Transparency = 1
	PartHitbox.Color = Color3.new(255,255,255)
	
	local HitboxWeld = Instance.new("Weld")
	local PartSize, PartPosition = AttachPositions()
	PartHitbox.Size = PartSize
	PartHitbox.Position = PartPosition
	HitboxWeld.Part0 = Tool.Handle
	HitboxWeld.Part1 = PartHitbox
	PartHitbox.Parent = Tool
	
	tabled["HitBoxPart"] = PartHitbox
	setmetatable(tabled, HitBoxM)
	return tabled
end

HitBoxM.SetupHitbox = function(Hitbox : Part)
	local t = {}
	t["HitBoxPart"] = Hitbox
	setmetatable(t, HitBoxM)
	return t
end

function HitBoxM:StartHitbox()
	if not self["HitBoxPart"] or self["HitBoxPart"].ClassName ~= "Part" then warn("Tried Starting a hitbox without setup/creation") return end
	local Hitbox = self["HitBoxPart"]
	
	local d = coroutine.create(StartingHitbox)
	coroutine.resume(d, Hitbox, self)
end

function HitBoxM:StopHitbox()
	if not self["HitBoxPart"] or self["HitBoxPart"].ClassName ~= "Part" then warn("Tried Stopping a hitbox without setup/creation") return end
	local Hitbox = self["HitBoxPart"]
	
	if Hitboxes[Hitbox] then Hitboxes[Hitbox] = false else warn("There was no hitbox detected for: " .. Hitbox.Name .. ", Creating Detection"); Hitboxes[Hitbox] = false end
end

function HitBoxM:CreateParams(Tool)
	local Op = OverlapParams.new()
	Op.FilterType = Enum.RaycastFilterType.Blacklist
	Op.MaxParts = 0
	Op.FilterDescendantsInstances = {Tool.Parent, Tool}
	for i, v in Tool:GetChildren() do
		if v.ClassName == "Part" then table.insert(Op.FilterDescendantsInstances, v) end
		if v.ClassName == "Model" then for i, v in ipairs(v:GetChildren()) do table.insert(Op.FilterDescendantsInstances, v) end end
	end
	print(Op.FilterDescendantsInstances)
	self["Op"] = Op
end


return HitBoxM

Client

repeat wait() until game:IsLoaded()

local tool = script.Parent
local Handle = tool.Handle
local SwordModel = tool["Realistc Sword"]
local T_SwordParts = SwordModel:GetChildren()
local Hitboxmod = game.ReplicatedStorage.SimpleHitboxModule
local HBM = require(Hitboxmod)

local Hitbox = HBM.SetupHitbox(tool.HitBox)

local debounce = false

function UseTool()
	if debounce == true then return end
	Hitbox:StartHitbox()
	debounce = true
	print("Started Hitbox")
	task.wait(2)
	debounce = false
	print("Stopped Hitbox")
	Hitbox:StopHitbox()		
end

function Equipped()
	Hitbox:CreateParams(tool)
end

function Unequipped()
	Hitbox:StopHitbox()
end

tool.Activated:Connect(UseTool)
tool.Equipped:Connect(Equipped)
tool.Unequipped:Connect(Unequipped)

Server

local event = game.ReplicatedStorage.SimpleHitboxModule:WaitForChild('HitboxEvent')
local tb = {}

local function CoolDown(v)
	task.wait(2)
	table.remove(tb, table.find(tb, v))
end

event.OnServerEvent:Connect(function(player : Player, t)
	for i, v in ipairs(t) do
		if not table.find(tb, v) and player.Character and player.Character:FindFirstChildWhichIsA("Tool") and (player.Character:FindFirstChildWhichIsA("Tool").Handle.Position - v.HumanoidRootPart.Position).Magnitude < 10 then
			print((player.Character:FindFirstChildWhichIsA("Tool").Handle.Position - v.HumanoidRootPart.Position).Magnitude)
			table.insert(tb, v)
			v:WaitForChild("Humanoid"):TakeDamage(10)
			local d = coroutine.wrap(CoolDown)
			d(v)
		end
	end
end)

with SendOnlyHumanoids set to false

With SendOnlyHumanioids set to true

(edit 1)
updated local script code & included server code

3 Likes