Safest way to prevent exploiting with a sword?

Currently, I have a sword system where the client can only control when they decide to swing the sword when the animation playing. As far as dealing with damage, I have a server script inside the tool that has a Touched event to handle that. It checks if the tool is inside the character. There are not Remote Events tied with anything of that. Is there a way that exploiters could somehow control the touching event to deal with damage or anything? I’ve given no control to the client-side with regards to damage.

(And yes, I’ve got a debounce to prevent spam on the server script)

2 Likes

Resizing the hitbox could cause a issue such as reach, but I am not entirely sure.

Yes actually! Exploiters can control Touched events of parts that their client controls, including parts connected to their characters with a joint. It sounds like you’re doing a good job with network security as well :+1:

I would suggest a simple distance check if you’d like to use Touched. This would be the easiest option, and would solve both latency, and security issues. I’d recommend checking with a distance slightly further than the length of their sword (e.g. 2-3 studs) to account for latency.

Alternatively you can do RayCasting which would make things reliant completely on the server. This might give players with high latency a bit of a bad experience, which is why I recommend the latter, however it’s up to you how you do things, and there are benefits to either method.

4 Likes

I was wondering, because if they change the position via the client, and move the hitbox to the enemy spawn while they are at their own spawn, would the server even register it? Considering that the server allows client full control over their position and speed…

Yep this would register a Touched event. The client has full control over Touched events for objects they have Network Ownership of. This even includes when that part touches an anchored part, however not the other way around (they can’t cause touches on an anchored part by locally moving a part they control to it)

So since the tool is in the character, when selected, they have full control. So then the ServerScript inside the tool that handles the touched event becomes obsolete without the distance checker? Right?

Yes. The Tool itself is connected to the player’s arm with a Weld instance. Their arm (obviously) is connected to their body, which is connected to their HumanoidRootPart, which they have Network Ownership of. That means they are able to cause Touched events for the tool on any other part, so they can cause hits for players super far away

So this kinda makes it more difficult to find if the player is not moving the hitbox… To find the distance i’m using magnitude, what would you recommend I use to find the distance with the hitbox, HumanoidRootPart, Torso etc.

Or DistanceFromCharacter?

I would recommend finding the distance using the hitbox. You can use Magnitude fine for this, but there is actually a slightly more performant way to check distance. I’m fairly sure DistanceFromCharacter checks Magnitude between the HumanoidRootPart and the target. Magnitude uses the pythagorean theorum, which square roots its results. Square roots are super inefficient even on modern hardware, but you can actually skip the square root entirely. I don’t know the official name for this, but I call it the “squared distance” check.

You can do it like this:

local difference = pos1 - pos2
local distSq = difference.X^2 + difference.Y^2 + difference.Z^2
local distCompare = 10^2 -- Less than 10 studs

if distSq < distCompare then
    -- Distance is less than 10
else
    -- Distance is greater than 10
end

This would be a bit overkill for this, since you aren’t checking distance too often. Usually it’s only useful to use a faster distance check when you’re doing thousands of distance checks per frame or something.

1 Like

Yeah, lol. I totally forgot about DistanceFromCharacter. It seems to be the most efficient way to use for this case. Looked it up, Player | Documentation - Roblox Creator Hub

:DistanceFromCharacter only counts the distance from the head.

This means if someone attacks a player and the tip of their sword hits the character under 0 ping conditions the distance from the sword and the head is sqrt(2)/2 studs.

Here is a crude drawing showing the concept:
image

This problem gets much worse for say if someone jumps upwards. Now the distance is from the bottom of their leg to the head. The roblox character is 6 studs tall so lets go with a guess of the distance now being 5.5 studs. If the distance from the sword from the head is roughly 5.5 studs then from the server it appears the person is laggy, or hitbox extending in some form. This would be bad because you would be falsely classifying the character’s actual movements.

I suggest using the distance from the limb hit, and the tip of the sword instead of using :DistanceFromCharacter

2 Likes

Well I figured they would use the head, because if the head is moved out the character, doesn’t the character die? If not, should I just use the HumanoidRootPart and the tip of the sword of the character?

Using the HumanoidRootPart can still result in the same issue.

So it seems like, when the weapon touches the enemy, check the distance between the enemy and the person attacking?

Yes. When an enemy touches someone check the distance of the closest point of the weapon to the point of contact of the weapon. This would be more reliable.

1 Like

I made a small edit, I forgot to return the result for the local function.
Try this friend, I wrote this out during your discussion that popp up in my Suggested Messages!
I was looking into this last year and I did something similar not long ago.

function SwordCheck(hit,sword,margin)
	local Allowed = false
	local function Nearest(H,TO)
		local HalfSize = H.Size * 0.5
		local PTOS = H.CFrame:pointToObjectSpace(TO)
		local Result = H.CFrame * Vector3.new(math.clamp(PTOS.x, -HalfSize.x, HalfSize.x), math.clamp(PTOS.y, -HalfSize.y, HalfSize.y), math.clamp(PTOS.z, -HalfSize.z, HalfSize.z))
		return Result
	end
	local HitNear = Nearest(hit,sword.Position)
	local SwordNear = Nearest(sword,hit.Position)
	if (HitNear - SwordNear).magnitude <= margin then
		Allowed = true
	end
	return Allowed
end
3 Likes

Also quick question to you about the code,
I don’t post on the forum often if at all.
Am I allowed to just give you the code like this? Or should I just beat around the bush until maybe you figure it out? If the former is true then you’re welcome! If the latter is true then uhh… Look at my code and uhh… “Learn” from it!

I’ll admit that security is an area in which I lack on the platform as I generally work from a Authoriaritive server model and bring someone experienced in the sector to come on and look over my codebase, correct whats needed for protection and give me the green light. But couldn’t you set the network owner of the character model as by default the client has access to all objects within it, including scripts.

I don’t understand what you mean. If you mean setting the player’s Network Ownership to the server, this will cause extreme latency issues.

@Virvek I would suggest using the Handle of the sword. You can check the distance from the handle’s center, and make sure the distance is <= to half the sword’s length (height) give or take a few studs.

1 Like