my hitbox class
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Signal = require(script.Parent.Signal)
local Hitbox = {}
Hitbox.__index = Hitbox
function Hitbox.new(Size: Vector3, CF: CFrame, Lifetime: number, Visualizer: boolean, Params: OverlapParams, OnHit: (Model) -> ())
local self = setmetatable({}, Hitbox)
self.Size = Size
self.CFrame = CF
self.Lifetime = Lifetime
self.Visualizer = Visualizer
self.Active = false
self.Stopped = Signal.new()
self.Hit = Signal.new()
self.Params = Params
self.HitConn = self.Hit:Connect(OnHit)
return self
end
function Hitbox:_start()
local result = workspace:GetPartBoundsInBox(self.CFrame, self.Size, self.Params)
for _, instance in ipairs(result) do
if instance then
local Character = instance:FindFirstAncestorOfClass("Model")
if Character then
self.Hit:Fire(Character)
end
end
end
if self.Lifetime and self.Lifetime > 0 then
task.delay(self.Lifetime, function()
if self.Active then
self:deactivate()
end
end)
end
end
function Hitbox:activate()
if self.Active then return end
self.Active = true
self:_start()
end
function Hitbox:deactivate()
if self.Active == false then return end
self.Active = false
self:_stop()
end
function Hitbox:_stop()
self.Stopped:Fire()
end
return Hitbox
server validation
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Debris = game:GetService("Debris")
local Tagger = require(ReplicatedStorage.Modules.Tagger)
local Hitbox = require(ReplicatedStorage.Modules.Utilities.Hitbox)
local Conn
ReplicatedStorage.Events.ValidateHitbox.OnServerEvent:Connect(function(Player, CF, timestamp)
local Character = Player.Character
if not Character or not Character.PrimaryPart then return end
local CurrentTime = tick()
if CurrentTime - timestamp > 0.5 then
return
end
if (Character.PrimaryPart.Position - CF.Position).Magnitude > 10 then
return
end
if not Player then
warn("what the cheese is lil bro tryna do")
return
end
local Params = OverlapParams.new()
Params.FilterType = Enum.RaycastFilterType.Exclude
Params.FilterDescendantsInstances = {Character}
print("Validation completed")
ReplicatedStorage.Events.HandleClientHitbox:FireAllClients(CF, Player)
end)
client input manager
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local Debris = game:GetService("Debris")
local RunService = game:GetService("RunService")
local Tagger = require(ReplicatedStorage.Modules.Tagger)
local FC = require(ReplicatedStorage.Modules.Utilities.FunctionUtils)
local Hitbox = require(ReplicatedStorage.Modules.Utilities.Hitbox)
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
repeat task.wait() until Character:FindFirstChildOfClass("Tool")
local Tool = Character:FindFirstChildOfClass("Tool")
local SwingAnim = Character.Humanoid.Animator:LoadAnimation(ReplicatedStorage.Assets.Swing)
UserInputService.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if Tagger:HasTag("Attacking", Character) then return end
local Timestamp = tick()
local HitboxCF = Character.PrimaryPart.CFrame * CFrame.new(0, 0, -3)
Tagger:TagObject("Attacking", Character)
ReplicatedStorage.Events.ValidateHitbox:FireServer(HitboxCF, Timestamp)
task.delay(0.5, function()
Tagger:RemoveTag("Attacking", Character)
end)
end
end)
ReplicatedStorage.Events.HandleClientHitbox.OnClientEvent:Connect(function(CF, attackingPlayer)
print("Passed handleclienthitbox")
if attackingPlayer == Player then
SwingAnim:Play()
end
local Params = OverlapParams.new()
Params.FilterType = Enum.RaycastFilterType.Exclude
local attackerChar = attackingPlayer.Character
if attackerChar then
Params.FilterDescendantsInstances = {attackerChar}
end
local VisualHB = FC.HitboxVisualizer(Vector3.new(5,6,5), CF, 0.06, Player)
Debris:AddItem(VisualHB, 0.06)
local HB = Hitbox.new(Vector3.new(5,6,5), CF, .06, true, Params, function(Instance)
if Instance and Instance:FindFirstChild("Humanoid") then
if Instance ~= attackerChar then
Instance.Humanoid:TakeDamage(5)
end
end
end)
HB:activate()
end)
i think the modules like FunctionUtils and Tagger are self explanatory, the HitboxVisualizer function just creates a visual hitbox and the Tagger module I have no idea why I made it but it just tags stuff so i can keep track of a players state
i heard about clientsided prediction and velocity prediction and whatever there is but its a bit complicated for me but give literally any feedback even if its on the prediction topics its all appreciated since im trying to make the most accurate hitbox i can