Hey, and thanks for reading in advance.
I’m helping to code a class-based fighter in which a select few classes are able to attack and teleport simultaneously (or teleport and then attack almost immediately afterwards).
Problem is, doing sanity checks keeping possible teleports in mind is hard. The server’s idea of your position and the client’s idea of your position are fractions of a second apart, and since the legal teleports are done locally (as they should be in order to maximize responsiveness), all the server sees for a few milliseconds is a gigantic gap between where you are and where the server thinks you should be. Additionally, remote signal traffic tends to be quicker than the server’s subroutine of updating each player’s global position.
This quickly becomes an issue when attempting to verify hitboxes, as the server denies hitbox requests if the location the client sends the server for creation of a hitbox is too far away from the server’s recorded position for the player. I don’t have the option of allowing a certain number of ‘fishy’ hitboxes, either - how could the server distinguish between a legal and illegal teleportation?
Sauce:
function Core:Hitbox(player, offset, size, ignore, maxparts)
local targets = {}
local ping = (player:FindFirstChild("Ping") or {Value = 50}).Value
local character = player.Character or player.CharacterAdded:Wait()
local hume = character:WaitForChild("Humanoid", 5)
local hrp = character:WaitForChild("HumanoidRootPart", 5)
if hrp and hume then
if ping >= 200 then
local hitbox = RotR3.new(hrp.CFrame * offset, size)
if ShowBoxes then
local box = Instance.new("Part")
box.BrickColor = BrickColor.new("Really blue")
box.Material = Enum.Material.Neon; box.Transparency = .6
box.TopSurface = "Smooth"; box.BottomSurface = "Smooth"
box.Size = size; box.CFrame = hitbox.cframe
box.Anchored = true; box.CanCollide = false
box.Name = "Hitbox"; box.Parent = workspace
game:GetService("Debris"):AddItem(box, 1)
end
for _,part in pairs(hitbox:cast(ignore, maxparts or 100)) do
local Humanoid = part.Parent:FindFirstChild("Humanoid")
if Humanoid and Humanoid.Health > 0 then
if not FindInTable(targets, part.Parent) then
targets[#targets + 1] = part.Parent
end
end
end
else spawn(function()
local hitData = ClientRemotes.Hitbox:InvokeClient(player, offset, size, ignore, maxparts)
local region, hits = hitData.Region, hitData.Targets
local factor_v = hrp.Velocity.Magnitude * math.clamp(ping/50, 1, 1.25)
local factor_s = hume.WalkSpeed * math.clamp(ping/50, 1, 1.25)
if region.size == size
and (region.cframe.p - hrp.Position).Magnitude <= math.max(factor_s, factor_v) then
local serverBox = RotR3.new(region.cframe, size * math.clamp(ping/20, 1, 1.5))
local serverHits = {}
if ShowBoxes then
local box = Instance.new("Part")
box.BrickColor = BrickColor.new("Really blue")
box.Material = Enum.Material.Neon; box.Transparency = .6
box.TopSurface = "Smooth"; box.BottomSurface = "Smooth"
box.Size = serverBox.size; box.CFrame = serverBox.cframe
box.Anchored = true; box.CanCollide = false
box.Name = "Hitbox"; box.Parent = workspace
game:GetService("Debris"):AddItem(box, 1)
end
for _,part in pairs(serverBox:cast(ignore, maxparts or 100)) do
local Humanoid = part.Parent:FindFirstChild("Humanoid")
if Humanoid and Humanoid.Health > 0 then
if not FindInTable(targets, part.Parent) then
serverHits[#serverHits + 1] = part.Parent
end
end
end
for _,target in pairs(hits) do
if FindInTable(serverHits, target) then
targets[#targets + 1] = target
end
end
else warn("Client hitbox either mismatched size or too far away")
end
end)
end
end
return targets
end
Edit - A quick breakdown of how this works:
- Server performs hitcheck instead of the player if their ping is above 200, otherwise;
- Server sends a signal to the client to create a hitbox with provided size and offset
- Client returns the hitbox it created plus any targets it caught inside it
- Server verifies this information and then creates an identical hitbox at the client’s provided location
- Server drops any targets found in the client’s hitbox that are not also found in the server’s hitbox
Any help or advice is appreciated.