How to make a timer that resets a weapon combo after a specific time

I’m working on a game with melee combat, and I’ve got all the attacking and things done (thanks to Clientcast) and I have a very simple combo script, but the problem is no matter how long you wait it always plays the next combo animation after the previous, but I want it to reset after the player has not swung for a certain amount of time. Here is the script:

local clientcast = require(game.ServerStorage.ClientCast)

local db = false

local hasbeenhit = false

local slash
local slash2
local slash3
local combo = 1

local casterParams = RaycastParams.new()
casterParams.FilterDescendantsInstances = {script.Parent.Parent.Parent.Character or script.Parent.Parent.Parent.Parent.Character, script.Parent.Handle}
casterParams.FilterType = Enum.RaycastFilterType.Blacklist

local slashCaster = clientcast.new(script.Parent.Handle, casterParams)

slashCaster.HumanoidCollided:Connect(function(result, hithumanoid)
	if hasbeenhit == false and script.Parent.Equipped then
		hithumanoid.Health = hithumanoid.Health - 20
		hasbeenhit = true
		wait(.6)
		hasbeenhit = false
	end
end)


script.Parent.Equipped:Connect(function()
	local humanoid = script.Parent.Parent:FindFirstChild("Humanoid")
	if not slash then slash = humanoid:LoadAnimation(script.Parent.Animations.Swing1); slash.Priority = Enum.AnimationPriority.Action end
	if not slash2 then slash2 = humanoid:LoadAnimation(script.Parent.Animations.Swing2); slash2.Priority = Enum.AnimationPriority.Action end
	if not slash3 then slash3 = humanoid:LoadAnimation(script.Parent.Animations.Swing3); slash3.Priority = Enum.AnimationPriority.Action end
	equip = humanoid:LoadAnimation(script.Parent.Animations.Draw)
	equip:Play()
	idle = humanoid:LoadAnimation(script.Parent.Animations.Idle); idle.Priority = Enum.AnimationPriority.Idle
	idle:Play()
	db = true
	if slashCaster then
		slashCaster:Stop()
	end
	wait(.2)
	db = false
end)

script.Parent.Activated:Connect(function()
	if not db then
		if combo == 1 then
		db = true
		slash:Play()
		wait(.1)
		slashCaster:Start()
		wait(.5)
		slashCaster:Stop()
		db = false
		combo = combo + 1
		elseif combo == 2 then
		db = true
		slash2:Play()
		wait(.1)
		slashCaster:Start()
		wait(.5)
		slashCaster:Stop()
		db = false
		combo = combo + 1
		elseif combo == 3 then
		db = true
		slash3:Play()
		wait(.1)
		slashCaster:Start()
		wait(.5)
		slashCaster:Stop()
		db = false
		combo = combo + 1
		elseif combo == 4 then
		combo = 1
		end
	end
end)

script.Parent.Unequipped:Connect(function()
	if slash then slash:Stop() end
	slashCaster:Stop()
	equip:Stop()
	idle:Stop()
end)

Its all in one server script, I thought about maybe using tick()? But I have no idea how to use tick() in this type of situation, I also previously tried making a custom counter but it seemed like a waste of resources and made my code messy, and it didn’t even work (I created functions for starting, stopping, and resetting a timer, to use in the combo section)

1 Like

It is pretty easy, save the variable, lastTimeSwong outside of any functions,
then basically every time you swing do check if it’s within a certain time period which you want after that set the lastTimeSwong as the current time:

local lastTimeSwong = 0

local function onSwing ()
   if (lastTimeSwong - tick()) > .5 then -- timePeriod within swing period; suggest to do this client-sidedly
      -- add to the combo
   end
   
   lastTimeSwong = tick()
end
1 Like

You mentioned in the script that its recommended to be client sided, why is that?

Let me explain, imagine someone “disconnects” or has connection issues, basically the server and client are desynced, when this occurs and you check the time change (this being .5 in the script I wrote), then the time could be higher than the time recorded on client.

Even though I dislike having much at the client, this & the animation is basically “required”.

2 Likes

So should I just make a separate local script that handles the animations and includes the script you provided?