Combo reset after not attacking for a second

So i created a combo script, It works great, one issue. Whenever i attack, the combo picks up on the next animation that i left off at. I need it to reset after not clicking for 1 second

local punchcd = false
local punchcombo = 1
function punch()
	if activu == true then return end
	if punchcd == true then return end
	activu = true
	human.JumpPower = 0
	if punchcombo == 1 then
		punchcombo = 2
		anim3:Play(0.1, 1, 1.5)
		wait(0.15)
		coroutine.resume(coroutine.create(function()
			for _ = 1, 5 do
				wait()
				damage(rightarm, rightarm.CFrame * CFrame.new(0, -1, 0) * CFrame.new(math.random(-0.25, 0.25), math.random(-0.25, 0.25), math.random(-0.25, 0.25)) ,5.4, 5, 0.5, 0.25, hrp.CFrame.lookVector * 10,"rbxassetid://743886825",1)
			end
		end))
	elseif punchcombo == 2 then
		punchcombo = 3
		anim1:Play(0.1, 1, 1.5)
		wait(0.15)
		coroutine.resume(coroutine.create(function()
			for _ = 1, 5 do
				wait()
				damage(leftarm, leftarm.CFrame * CFrame.new(0, -1, 0) * CFrame.new(math.random(-0.25, 0.25), math.random(-0.25, 0.25), math.random(-0.25, 0.25)) ,5.4, 5, 0.5, 0.25, hrp.CFrame.lookVector * 10,"rbxassetid://743886825",1)
			end
		end))
	elseif punchcombo == 3 then
		punchcombo = 4
		anim3:Play(0.1, 1, 1.5)
		wait(0.15)
		coroutine.resume(coroutine.create(function()
			for _ = 1, 5 do
				wait()
				damage(rightarm, rightarm.CFrame * CFrame.new(0, -1, 0) * CFrame.new(math.random(-0.25, 0.25), math.random(-0.25, 0.25), math.random(-0.25, 0.25)) ,5.4, 5, 0.5, 0.25, hrp.CFrame.lookVector * 10,"rbxassetid://743886825",1)
			end
		end))
	elseif punchcombo == 4 then
		punchcombo = 5
		anim4:Play(0.1, 1, 1.5)
		wait(0.15)
		coroutine.resume(coroutine.create(function()
			for _ = 1, 5 do
				wait()
				damage(leftarm, leftarm.CFrame * CFrame.new(0, -1, 0) * CFrame.new(math.random(-0.25, 0.25), math.random(-0.25, 0.25), math.random(-0.25, 0.25)) ,5.4, 5, 0.5, 0.25, hrp.CFrame.lookVector * 10,"rbxassetid://743886825",1)
			end
		end))
	elseif punchcombo == 5 then
		punchcombo = 1
		anim5:Play(0.1, 1, 1.5)
		wait(0.2)
		coroutine.resume(coroutine.create(function()
			for _ = 1, 5 do
				wait()
				damage(rightleg, rightleg.CFrame * CFrame.new(0, -1, 0) * CFrame.new(math.random(-0.25, 0.25), math.random(-0.25, 0.25), math.random(-0.25, 0.25)) ,6, 6, 0.5, 0.25, hrp.CFrame.lookVector * 40,"rbxassetid://743886825",.7)
			end
		end))
		punchcd = true
		wait(1.1)
		punchcd = false
	end
	wait(0.255)
	activu = false
	human.JumpPower = 50

end

I’ve been brainstorming but i can’t really think of a good way to do this

4 Likes

I think you can use a coroutine timer. Also CCing @Roastdbacon who is also working on a similar problem last time I saw using the same method I suggested to him with a timer.

Also Credits to @Lightlimn for the timer module required to run the code in this post. Make sure to require the module in the below script

Try this out, put in a tool

local tool = script.Parent
tool.RequiresHandle = false

local Timer = require(script.Timer)

local comboResetTimer -- store the previous start punching timer
local function punch() 
	print("Pawnch")

	if comboResetTimer and comboResetTimer.IsRunning then
		comboResetTimer:Reset() -- resets the timer
	else
		--if none created, create and start a new one
		comboResetTimer = Timer.new(1)
		comboResetTimer.Completed:Connect(function()
			print("Combo Reset!")
		end)
		comboResetTimer:Start()
	end
end

tool.Activated:Connect(function()
	punch()
end)

Module script required posted here made by @Lightlimn:

Timer Module
--[[
	------------
	TIMER MODULE
	------------
	
	Timer.new(duration,count)
		Returns a new timer with the specified duration.
		'Completed' event will fire when the timer finishes.
		'Count' event will fire every 'count' seconds, until the timer finishes.
	
	Timer:Start()
		Starts a timer.
		
	Timer:Stop()
		Cancels a timer early, destroying it.
		
	Timer:Reset()
		Resets a timer, starting it counting from 0.
	
	Timer.Completed(actualDuration)
		An event fired when the specified timer ends.
	
	Timer.Count(timeElapsed)
		An event fired when the specified count ticks (default 1).
		This means every x seconds, the event will be fired.
	
	--------------
	EXAMPLE OF USE
	--------------
	
	local Timer = require(game.ReplicatedStorage.Timer)
	
	local tenSeconds = Timer.new(10,1) -- second argument can be ignored
	
	tenSeconds.Completed:Connect(function()
		print("10 second timer completed.")
	end)
	
	tenSeconds.Count:Connect(function(elapsedTime)
		print(elapsedTime) -- an accurate, precise number. may not be too useful for visual things
	end)
	
	tenSeconds:Start()
	
	-------
	UPDATES
	-------
	02-Jan-2020:
	-Added Count event
	
	29-Mar-2021:
	-Unscuffed the scuffed stuff
	-Oh it was so bad. I'm so sorry. It starts when you call the Start method now. Why did I do this?
	-Added Reset() method (timer continues from 0 once reset)
	
	-----
	NOTES
	-----
	
	This might be updated at some point. This is one of my first OOP style modules I've worked on
	so things could be a little messy - this seems to work fine though.
	
	The main issue this has is that the timer will always be slightly longer than the duration
	intended (by a few ms). This is because it depends on framerate (just like regular wait())
	and if the framerate is slower, the last step will go over the duration length.
	Pretty sure there isn't a way around this, but tell me if you find something!
	
	Lightlim#8531
	
--]]

local Timer = {}
Timer.__index = Timer

local runS = game:GetService("RunService")

function Timer.new(duration,count) -- Creates a new timer
	local newTimer = {}
	setmetatable(newTimer,Timer)
	newTimer.Duration = duration
	newTimer.IsRunning = true
	newTimer.StartTime = tick()
	local completedEvent = Instance.new("BindableEvent")
	newTimer.CompletedEvent = completedEvent
	newTimer.Completed = completedEvent.Event
	newTimer.CountStep = count or 1 -- defaults to 1
	newTimer.LastStep = newTimer.StartTime -- instead of tick() because code is run before this
	local countEvent = Instance.new("BindableEvent")
	newTimer.CountEvent = countEvent
	newTimer.Count = countEvent.Event
	return newTimer
end


function Timer:Reset()
	self.StartTime = tick()
	self.LastStep = self.StartTime
end


function Timer:Start() -- Begins a timer
	self.StartTime = tick()
	self.LastStep = self.StartTime
	self.Countdown = runS.Heartbeat:Connect(function()
		local currentTime = tick()-self.StartTime
		if self.CountStep then
			if tick()-self.LastStep >= self.CountStep then
				self.CountEvent:Fire(currentTime) -- return current time
				self.LastStep = self.LastStep+self.CountStep
			end
		end
		if currentTime >= self.Duration then
			-- fire event, cancel timer
			self.IsRunning = false
			self.CompletedEvent:Fire(currentTime)
			self:Stop()
		end
	end)
end

function Timer:Stop() -- Cancels a timer, destroying the data
	if self.Countdown then
		self.Countdown:Disconnect()
	end
	if self.CompletedEvent then
		self.CompletedEvent:Destroy()
	end
	if self.CountEvent then
		self.CountEvent:Destroy()
	end
end


return Timer

Results of me spam clicking the combo and me clicking only once:

image

Edit: Just realized an alternative made by @ValonAedrovulf, of using tween service as a timer as you can just :Cancel() then :Play() to reset the timer, plus it’s built into the engine so you don’t need the extra module, pretty cool alternative.

13 Likes

Thank you, great response! Put a lot of effort into it

2 Likes