Feedback On Basic Sword

So I have scripted a sword. How it works is when you swing, a remote event is fired to the server, then the server calculates a region onto the blade of the sword/tool, and cycles through the parts inside of that region, damaging any players (inside of that region).

My main concerns are:
. The cool-down variable (for when you swing) is inside of the local script so exploiters can change the cool-down variable and put it on something really low. However, I don’t know how to fix this.
. When I make the sword blade a more advanced object for example a complicated union etc., the region isn’t calculated properly and the sword does not work. So if they’re is any different concepts/ideas I could use other than using Region3, please suggest some to me.
. If I make 10 different swords, will I have to make 10 different scripts (under ServerScriptService, that are fired by 10 different remote events)? If so would that be messy?

Here is how my sword looks like in the explorer window:
Tool

Code Inside Of Local Script (in tool):

-- Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Objects
local tool = script.Parent
local blade = tool:WaitForChild("Blade")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")

-- Animation
local animation = tool.Animation
local animationTrack = humanoid:LoadAnimation(animation)

-- Remote Events
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")

-- Value Variables
local COOLDOWN = 0.8

local debounce = true

tool.Activated:Connect(function(mouse)
	if debounce then
		remoteEvent:FireServer(tool)
	
		animationTrack:Play()
		
		debounce = false
		wait(COOLDOWN)
		debounce = true
	end
end)

Code In ServerScriptService That is Fired by Remote Event:

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Workspace = game:GetService("Workspace")

-- Modules
local swordDamage = require(ServerScriptService.SwordDamage)

-- Remote Events
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")

-- Value Variables
local WOODEN_SWORD_DAMAGE = swordDamage.woodenSwordDamage

local function calculateRegion(tool)
	local blade = tool.Blade
	
	local position1 = blade.Position - (blade.Size / 2)
	local position2 = blade.Position + (blade.Size / 2)
	local region = Region3.new(position1, position2)
	
	return region
end

local function dealDamage(player, tool)
	local region = calculateRegion(tool)
	
	local partsToIgnore = {tool.Blade, tool.Handle, player.Character}
	
	local partsInRegion = Workspace:FindPartsInRegion3WithIgnoreList(region, partsToIgnore, 1000)
	
	-- Cycles through the region (calculated over the blade) for any enemies
	for _, part in pairs(partsInRegion) do
		if part.Parent:FindFirstChild("Humanoid") ~= nil then
			local humanoid = part.Parent.Humanoid
			humanoid.Health = humanoid.Health - WOODEN_SWORD_DAMAGE
		end
	end
end

remoteEvent.OnServerEvent:Connect(dealDamage)

Code In Module Script Under ServerScriptService:

local swordDamage = {
	woodenSwordDamage = 6,
	stoneSwordDamage = 11,
}

return swordDamage

This is one of my first times posting on the Dev Forum so if my question is unclear, I am sorry. Also I am new to scripting.

Thanks! BIaughing

You can fix your cool down variable by doing the cool down in the server registering each player into a table.

You do not have to make 10 different remote events for each sword of course if you use the argument sending to your advantage, it would make no difference for exploiters anyways since they could fire any remote event anything really so one remote event instead of ten would just benefit you in this case.

There are a different amount of ways other than Region3 to do swords such as raycasting, Touched event on an invisible hit box part, and magnitude check.

Region3 is probably not a good idea to use for swords and honestly for beginners, you could try the hit box idea most. Raycast is the most efficient I seen so far as it’s precise and not as unreliable as the Touched event sometimes.

I didn’t make code show to what I mean but if it’ll help you with a simplified code example, I can make it (for the cool down part).

Thanks for the reply! When you mean use Raycast, does that mean casting a ray from the sword going forward and seeing if the ray intersects another player? (sorry if the question doesn’t make sense) And also what is “hit box”? Could you maybe give me a link to the topic if there is one? And finally could you show me the re-written code for the cool-down part?

And also (sorry forgot to add this into my first reply), the reason I didn’t use touched event is because when you swing, the touched event fires multiple times in one swing. So I used Region3 because it only fires once, only damaging the player once per swing.

1 Like

Yes that is what I mean by raycasting, there’s a public raycast hit box module if you’re interested in that.

A hit box is exactly what it is, a box that hits something, you create an invisible part and it registers hits, usually by a Touched event.

A touched event could be modified to not hit multiple things such as putting humanoids you’ve hit so you can compare them during the attack to avoid multiple hits.

Cool down code example:

local playerdebouncestable = {} — alternatively, you can pre-create a table as table.create(#game.Players.MaxPlayers) to reserve space as desired.
server event function 
    if not table.find(playerdebouncestable, player) then
        table.insert(playerdebouncestable, player)
        — do code plus yields etc
        table.remove(playerdebouncestable, player)
    end
end

I think you shouldn’t use Remote Events there, I started to make a sword with these and after some swords it became so messy.