How can I pause a function (countdown function)

I have a script that has a countdown function, it runs when a player gets downed. What I want to achieve is being able to pause the countdown function when another player is interacting with the proximity prompt I created inside of the script. Everything is already created apart from the countdown pause. Here is the script:

game.Players.PlayerAdded:Connect(function(p)
	
	local Timer = 30

	local function startTimer()
		local remainingTime = Timer

		while remainingTime > 0 do
			BillboardGuiEvent:FireAllClients(remainingTime)
			wait(1)
			remainingTime -= 1
		end
	end
	
	p.CharacterAdded:Connect(function(c)
		
		c:WaitForChild("Humanoid").HealthChanged:Connect(function(health)
			
			if health <= 1 and not c:FindFirstChild("Revived") then 
				
				c.Humanoid.MaxHealth = math.huge
				c.Humanoid.Health = math.huge
				
				c.HumanoidRootPart.Anchored = true
				
				startTimer()
				
				local proximityPrompt = Instance.new("ProximityPrompt")
				proximityPrompt.HoldDuration = 3
				proximityPrompt.ActionText = "Hold E to Revive"
				proximityPrompt.ObjectText = c.Name .. "'s corpse"
				proximityPrompt.RequiresLineOfSight = false
				proximityPrompt.Parent = c.HumanoidRootPart
				
				game.ReplicatedStorage:WaitForChild("ReviveRE"):FireClient(p, proximityPrompt)
				
				
				proximityPrompt.Triggered:Connect(function(plr)
					
					local revived = Instance.new("BoolValue", c)
					revived.Name = "Revived"
					
					proximityPrompt.Enabled = false
					proximityPrompt:Destroy()
					
					c.Humanoid.MaxHealth = 100
					c.Humanoid.Health = c.Humanoid.MaxHealth
					c.HumanoidRootPart.Anchored = false
					
					-- stop the timer
					
					game.ReplicatedStorage:WaitForChild("ReviveRE"):FireClient(p)
				end)
				
				proximityPrompt.PromptButtonHoldBegan:Connect(function()
					-- Pause the timer
				end)
				proximityPrompt.PromptButtonHoldEnded:Connect(function()
					-- Resume the timer
				end)
				
				
				wait(20)
				
				if not c:FindFirstChild("Revived") then
					
					local revived = Instance.new("BoolValue", c)
					revived.Name = "Revived"
					
					c.Humanoid.Health = 0
				end
			end
		end)
	end)
end)

The comments show what I want to do.

1 Like

You can use coroutines for that, or bindable events.

1 Like

I am not good with coroutines. Can you give me an example on how to pause, resume and stop an argument?

local coroutinestuff = coroutine.create(function()
      --do stuff
end

event.Fired:Connect(function()
    coroutine.resume(coroutinestuff) --to add arguments do coroutine.resume(coroutinestuff, argument1, argument2 --etc)
end)
event2.Fired:Connect(function()
    coroutine.yield(coroutinestuff)
end)

and since u said u dont know much about coroutines
to start the coroutine.create(function() u need to do coroutine.resume(coroutinestuff) first

local coroutinestuff = coroutine.create(function()
      --do stuff
end
coroutine.resume(coroutinestuff)

event.Fired:Connect(function()
    coroutine.resume(coroutinestuff) --to add arguments do coroutine.resume(coroutinestuff, argument1, argument2 --etc)
end)
event2.Fired:Connect(function()
    coroutine.yield(coroutinestuff)
end)

Ok I have been working on the revive system for a while now. Included the coroutines and fixed up the script a little. However, I have a few issues with it when I tested it. First of all the timer gets displayed on a “BillboardGui” through a local script and the countdown only shows for the player who is knocked. Second issue is that the coroutines (resume, yield) don’t seen to have any effect on the timer or maybe they aren’t functioning. Third issue: I have to trigger the Proximity Prompt twice for the player to get fully revived, the first trigger only stops the animation.
ServerScript (Named: ReviveServer):

game.Players.PlayerAdded:Connect(function(p)
	
	local RS = game:GetService("ReplicatedStorage")
	local BillboardGuiEvent = RS.RemoteEvents.BillboardGuiEvent
	local SS = game:GetService("ServerStorage")
	local Billboard = SS.BillboardGui
	
	local Timer = 30
	
	p.CharacterAdded:Connect(function(c)
		c:WaitForChild("Humanoid").HealthChanged:Connect(function(health)
			if health <= 1 and not c:FindFirstChild("Revived") then 
				
				c.Humanoid.MaxHealth = math.huge
				c.Humanoid.Health = math.huge
				
				c.HumanoidRootPart.Anchored = true
				
				local ClonedBB = Billboard:Clone()
				ClonedBB.Parent = c.Head
				
				local function startTimer()
					local remainingTime = Timer

					while remainingTime > 0 do
						BillboardGuiEvent:FireAllClients(remainingTime)
						wait(1)
						remainingTime -= 1
						if remainingTime <= 0 then
							c.Humanoid.Health = 0
							print("Timer ran out, Humanoid died")
							ClonedBB:Destroy()
						end
					end
				end
				
				local CoroutineTimer = coroutine.wrap(startTimer)
				CoroutineTimer()
				
				local proximityPrompt = Instance.new("ProximityPrompt")
				proximityPrompt.HoldDuration = 3
				proximityPrompt.ActionText = "Hold E to Revive"
				proximityPrompt.ObjectText = c.Name .. "'s corpse"
				proximityPrompt.RequiresLineOfSight = false
				proximityPrompt.Parent = c.HumanoidRootPart
				
				game.ReplicatedStorage:WaitForChild("ReviveRE"):FireClient(p, proximityPrompt)
				
				
				proximityPrompt.Triggered:Connect(function(plr)
					
					local revived = Instance.new("BoolValue", c)
					revived.Name = "Revived"
					
					proximityPrompt.Enabled = false
					proximityPrompt:Destroy()
					
					c.Humanoid.MaxHealth = 100
					c.Humanoid.Health = c.Humanoid.MaxHealth
					c.HumanoidRootPart.Anchored = false
					
					ClonedBB:Destroy()
					print("Revived the Humanoid and added a tag so they die the next time")
					
					coroutine.yield(CoroutineTimer())
					
					game.ReplicatedStorage:WaitForChild("ReviveRE"):FireClient(p)
				end)
				
				proximityPrompt.PromptButtonHoldBegan:Connect(function()
					coroutine.yield(CoroutineTimer())
					print("Timer Has Been Paused, Someone is reviving")
				end)
				proximityPrompt.PromptButtonHoldEnded:Connect(function()
					coroutine.resume(CoroutineTimer())
					print("Timer Has Been Resumed, Not Completed Hold")
				end)
				
				wait(20)
				
				if not c:FindFirstChild("Revived") then
					
					local revived = Instance.new("BoolValue", c)
					revived.Name = "Revived"
					
					c.Humanoid.Health = 0
					print("Humanoid died, already revived before")
				end
			end
		end)
	end)
end)

LocalScript (Named: ReviveClient):

local anim = script.Parent.Humanoid:LoadAnimation(script:WaitForChild("DeadAnimation"))

game.ReplicatedStorage:WaitForChild("ReviveRE").OnClientEvent:Connect(function(proximityPrompt)
	
	if proximityPrompt then
		
		proximityPrompt.Enabled = false
	
		anim:Play()
		
	else
	
		anim:Stop()
	end
end)

LocalScript inside of the “TextLabel” inside of the “BillboardGui” (Named: LocalScript):

local replicatedStorage = game:GetService("ReplicatedStorage")
local BillBoardGuiEvent = replicatedStorage.RemoteEvents.BillboardGuiEvent

local textlabel = script.Parent

BillBoardGuiEvent.OnClientEvent:Connect(function(remainingTime)
	textlabel.Text = tostring(remainingTime)
end)

im also not even good with coroutines but why use coroutine.wrap when we said coroutine.create also for coroutine.yield and resume change it from
(CoroutineTimer())
to

Example: coroutine.yield(CoroutineTimer)
Example: coroutine.resume(CoroutineTimer)

So Remove the brackets. I think

Coroutines can certainly be used, but the original code could easily have just added a
local paused = false
right below local Timer = 30

and then something like:

if not paused then
    ...
    remainingTime -= 1
    ...
end

in the countdown loop, with paused being set true or false from the proximity prompty begin/ended respectively. A variable declared near the top, where Timer is declared, will be an upvalue for all the code below it. I mean, all you really want here is to not do the counting down when someone is doing the revive, right?

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.