Issues With my Combat System

I’m trying to make a combat system that fits the players equip style, Single or Dual wield. What I want is for the enemy to take damage based on the damage value that the blade has.

The first attack deals the exact amount of damage that the blade does, however on the second and third swing, it seems to multiply the values making each hit a 1hit ko. Obviously I’m not receiving any errors since it believes the system is working 100%. Any Ideas on how to fix this?

I’ve tried looking up examples of combat scripts through the dev forums but didn’t seem to find exactly what I needed.

Local Script:

Server Script:

Not really meant to answer your question completely, but sending the damage to the server is a huge no no, you’re trusting the client. An exploiter can decide to send 1e9 (1 billion) or any huge number which is probably impossible to get in your game

Also if you could give more info like properties values, and not post screenshots of code and instead pasting in code blocks, that would be of major help

```lua

```

(just copy and paste that if you don’t know how to)

So should I put the Touched function within the server script and reference the damage from there?

Perhaps try to create a physical IntValue for damage in your weapon and have the server read the damage from there.

Except it doesn’t have the lua in it.

@DeadGambit this is why you add cooldowns to weapons. Even a sword needs one.

The reason for this is that while your blade is swinging through the enemy, you’re actually touching the enemy multiple times, which, without a cooldown/debounce, makes it run the hit logic multiple times per swing.

To fix this, simply add a variable for the debounce, e.g. local debounce = tick().
After adding the variable, you need to make it actually work. To do this, add an if statement in the Touched event:

if tick() - debounce < cooldown then return end

You could make a variable for the cool down, or simply replace in the script.

Furthermore, as others have mentioned, having the client handle the entirety of the hit logic may result in exploiters abusing your code to deal massive amounts of damage to everyone, or even godding themselves.

You should have the remote server logic handle this instead, having a fixed amount of damage in the server, and a magnitude based position checker (to ensure people are actually close to you when you hit them)

Hope this helps.

1 Like

I already have a cooldown. Here is the full LocalScript:

wait()
local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()
local char = plr.Character
local events = game.ReplicatedStorage:FindFirstChild("Events")
local UIS = game:GetService("UserInputService")
countingdown = false
cantattack = plr.Character.Settings.AttackReady
attacking = plr.Character.Settings.Attacking
ticc = 0
attack = 1
local style = Instance.new("StringValue")
dual = false

function Delaye()
	wait(.3)
	attacking.Value = false
end

function Tick()
	if countingdown == false then
		countingdown = true
		ticc = 1
		while true do
			wait(.1)
			if ticc > 0 then
				ticc = ticc - .1
			else
				break
			end
		end
	elseif countingdown == true then
		ticc = 1
	end
end

UIS.InputBegan:Connect(function(key, processed)
	if processed then
		return
	end
	if key.UserInputType == Enum.UserInputType.MouseButton1 then
		if plr.Character.Settings.CanAttack.Value == true then
			for index, class in pairs(plr.Classes:GetChildren()) do
				if class.Value == 1 then
					if class.Name == "Ranger" then
						if plr.Character.Settings.DualWield.Value == true then
							if cantattack.Value == true then
								game.ReplicatedStorage.Remotes.Attacked:FireServer()
								plr.Character.Settings.CanAttack.Value = false
								local anim = char.Humanoid:LoadAnimation(plr.Character.Anim.Ranger.Dual["Attack"..attack])
								anim:Play()
								attacking.Value = true
								if attack == 1 then
									for index, sword in pairs(plr.Character.Equipped:GetChildren()) do
										--sword.Blade.Trail.Enabled = true
									end
								end
								if attack == 4 then
									game.ReplicatedStorage.Remotes.FourthAttack:FireServer()
								end
								spawn(Tick)
								if attack < 4 then
									attack = attack + 1
									cantattack.Value = false
									wait(.5)
									cantattack.Value = true
									plr.Character.Settings.CanAttack.Value = true
								else
									attack = 1
									countingdown = false
									ticc = 1
									for index, sword in pairs(plr.Character.Equipped:GetChildren()) do
										--sword.Blade.Trail.Enabled = false
									end
									cantattack.Value = false
									spawn(Delaye)
									wait(.6)
									cantattack.Value = true
									plr.Character.Settings.CanAttack.Value = true
								end
							end
						elseif plr.Character.Settings.Right.Value == true then
								if cantattack.Value == true then
									game.ReplicatedStorage.Remotes.Attacked:FireServer()
									plr.Character.Settings.CanAttack.Value = false
									local anim = char.Humanoid:LoadAnimation(plr.Character.Anim.Ranger.Single["Attack"..attack])
									anim:Play()
									attacking.Value = true
									if attack == 1 then
										for index, sword in pairs(plr.Character.Equipped:GetChildren()) do
											--sword.Blade.Trail.Enabled = true
										end
									end
									if attack == 4 then
										game.ReplicatedStorage.Remotes.FourthAttack:FireServer()
									end
									spawn(Tick)
									if attack < 4 then
										attack = attack + 1
										cantattack.Value = false
										wait(.5)
										cantattack.Value = true
										plr.Character.Settings.CanAttack.Value = true
									else
										attack = 1
										countingdown = false
										ticc = 1
										for index, sword in pairs(plr.Character.Equipped:GetChildren()) do
											--sword.Blade.Trail.Enabled = false
										end
										cantattack.Value = false
										spawn(Delaye)
										wait(.6)
										cantattack.Value = true
										plr.Character.Settings.CanAttack.Value = true
									end
								end
							end
						end
					end
				end
			end
		if plr.Character.Settings.Right.Value == true then
			style = "Single"
			local single = plr.Character.Equipped:FindFirstChildOfClass("Model")
			local dmg = single.Config.Dmg.Value
			single.Blade.Touched:Connect(function(hit)
				if attacking.Value == true then
					if hit.Parent:FindFirstChild("Humanoid") ~= nil then
						game.ReplicatedStorage.Remotes.Damage:FireServer(style, hit.Parent, dmg)
					end
				end
			end)
		end
	end
end)

while true do
	wait()
	--[[
	local count = tostring(countingdown)
	print(count.."-"..ticc)--]]
	if ticc <= 0 and countingdown == true then
		countingdown = false
		attack = 1
		ticc = 1
		attacking.Value = false
		for index, sword in pairs(plr.Character.Equipped:GetChildren()) do
			sword.Blade.Trail.Enabled = false
		end
	end
end