Need help fixing part of this combat script

Hello once again, people of the DevForum.

I need your help getting part of this script to work. Firstly, here’s the whole script:

-- // Variables
local tool = script.Parent
local anims = script.Parent.Animations
local ws = game:GetService("Workspace")
local box = tool.box
local box2 = tool.box2
local oparams = OverlapParams.new()
oparams.FilterType = Enum.RaycastFilterType.Exclude
oparams.MaxParts = math.huge
local effect = script.Parent.Handle.Blood
local btrail = script.Parent.Handle.BloodTrail

-- // Controls
local equip
local slash
local idle
local db = false
local canHit = false
local hitboxed = false
local randomSlash = 1
local boxc
local value
local slashval = tool.Slash
local dewit = true
local resetthread = nil


-- // Animation Startup
script.Parent.Equipped:Connect(function()
	tool.Handle.Equip:Play()
	local humanoid = script.Parent.Parent:FindFirstChild("Humanoid")
	if not equip then equip = humanoid:LoadAnimation(anims.Equip) end
	equip:Play()
	if not idle then idle = humanoid:LoadAnimation(anims.Idle) end
	idle.Priority = Enum.AnimationPriority.Movement
	idle:Play()
end)

-- // Animation Shutdown
script.Parent.Unequipped:Connect(function()
	if idle then idle:Stop() end
	if equip then equip:Stop()
		if slash then slash:Stop() end
	end
end)

-- // Light Attack Reset CD
local animCD = function()
	print("combo cd has begun")
	task.wait(2)
		randomSlash = 1
		slashval.Value = randomSlash
		print("combo has been reset")
end

--// Prevent Combo Reset
slashval.Changed:Connect(function()
	if resetthread == nil then print("combo reset perceived nil") return end
	coroutine.close(resetthread)
	print("combo reset cancelled")
end)

-- // Light Attacks
script.Parent.Activated:Connect(function()

	local char = tool.Parent
	local root = char:WaitForChild("HumanoidRootPart")
	local hum = char:WaitForChild("Humanoid")

	if char.Stunned.Value or char.Dashing.Value or db then return end
		db = true


		local function Attack()
			if canHit or not db or hitboxed then return end
					canHit = true
					hitboxed = true
					
					if randomSlash == 1 or randomSlash == 2 or randomSlash == 5 then
						boxc = box:Clone()
						value = -3
					elseif randomSlash == 3 or randomSlash == 4 then
						boxc = box2:Clone()
						value = -5
					end

					oparams.FilterDescendantsInstances = {char}

					local humanoidsDamaged = {}
					
					tool.ClickEvent.OnServerEvent:Connect(function(plr, cf)					
						boxc.Parent = ws.Scripted
						boxc.CFrame = cf * CFrame.new(0,0,value)
						game:GetService("Debris"):AddItem(boxc,0.3)
						
						local hits = ws:GetPartsInPart(boxc,oparams)

						for i = 1, #hits do

							if hits[i].Parent ~= char and hits[i].Parent:FindFirstChild("Humanoid") and hits[i].Parent:FindFirstChild("Dashing") and char.Stunned.Value == false then
								if hits[i].Parent.Dashing.Value == false and not table.find(humanoidsDamaged, hits[i].Parent.Parent) then
									table.insert(humanoidsDamaged, hits[i].Parent.Parent)
									local hitSFX = Instance.new("Sound",hits[i].Parent.Head);
									hitSFX.SoundId = "rbxassetid://566593606"; hitSFX:Play()
											hits[i].Parent.Humanoid:TakeDamage(5)
											hits[i].Parent:FindFirstChild("Hitstun"):Fire()

									effect.Enabled = true
									btrail.Enabled = true

									local slashfx = tool.Effects.Slash.Attachment:Clone()
									slashfx.Parent = hits[i].Parent:FindFirstChild("HumanoidRootPart")
									local r = math.random(-360,360)
									slashfx.slash.Rotation = NumberRange.new(r)
									task.delay(0.3,function()
										slashfx:Destroy()
									end)

								end
								task.delay(0.2,function()
									effect.Enabled = false
									btrail.Enabled = false
								end)
							end
							
						end
					end)
					task.delay(0.3,function()
						canHit = false
						hitboxed = false
					end)
		end
		
		Attack()
		
		if not slash then
			slash = hum:LoadAnimation(anims["Attack".. randomSlash])

			if randomSlash == 5 then
				randomSlash = 1
				slashval.Value = randomSlash
				print("randomslash set to "..randomSlash)
			else
				randomSlash += 1
				slashval.Value = randomSlash
				print("randomslash set to "..randomSlash)
			end
		end

		local val = tool.Parent.Attacking
		val.Value = true
		
		slash:Play()
		
		script.Parent.Handle.Trail.Enabled = true
		task.wait(.15)
		tool.Handle.Slash:Play()
		
		if randomSlash == 5 or randomSlash == 4 then
			tool.Handle.Chain:Play()
		end
		task.wait(.15)
		hitboxed = false
	
		if slash then
			slash = nil
		end
	
		script.Parent.Handle.Trail.Enabled = false
		resetthread = coroutine.create(animCD)
		print("combo reset coroutine created")
	
		if randomSlash == 1 then
			task.wait(2)
			db = false
		else
			db = false
		end
	
		task.delay(.15,function()
			val.Value = false
		end)
end)

The part I need help with isn’t to do with the Attack() function, but rather getting the whole Combo Reset part to work. Basically, the behavior I want is this:

There are 5 hits in a combo. If you finish the combo fully, you have to wait 2 seconds before you can start another. If you stop mid-way into a combo, a 2 second timer silently ticks down and if it finishes before you swing again, it’ll reset the combo back to the first hit. That way, combat is more intuitive.

The silent timer is what’s giving me trouble. You can see here the whole combo works, including the cooldown after:

But here, I wait long enough that the combo SHOULD reset, but it doesn’t. Instead, it continues where I left off when I start clicking again.

Here’s the output:

For some context, this is a server script inside a tool and the coroutine that controls the combo reset starts towards the end of the .Activated function.

I tried to tidy up my code a bit for you all, but I know it’s probably still messy. I hope it’s still readable and you can help me out, cause anything is appreciated! Thanks!

P.S: Feel free to ask me anything in regards to what certain variables or objects are, or anything I didn’t specify.

1 Like