Hey so I’ve been trying to find a fix to this bug I’m experiencing, but I still couldn’t find one. Here’s both of the scripts for anybody who wants to examine it.
The bug makes the bindable events not connect with each other, so it prevents me from actually using the handlers. I know this because I was using print(), but again if anybody knows the fix to this please let me know.
Another thing is that these handlers are in ServerScriptService, and the SpecialEvents folder is located in ReplicatedStorage.
Main Handler:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SpecialEvents = ReplicatedStorage.SpecialEvents
local CountdownBegin = SpecialEvents.CountdownBegin
local CountdownStop = SpecialEvents.CountdownStop
local GameResults = SpecialEvents.GameResults
local GameHandlerRestart = SpecialEvents.GameHandlerRestart
local NighttimeFunction = SpecialEvents.NighttimeFunction
local Minutes = ReplicatedStorage.GameConfiguration.Minutes
local Seconds = ReplicatedStorage.GameConfiguration.Seconds
local GameHandlerMessage = ReplicatedStorage.GameConfiguration.GameHandlerMessage
local NighttimeRemote = ReplicatedStorage.Event.NighttimeRemote
local LastOneStandingRemote = ReplicatedStorage.Event.LastOneStanding
local NighttimeEvent = require(game.ServerStorage.Events.ModuleScript)
local playerList = {}
local IsIntermission = ReplicatedStorage.GameConfiguration.IsIntermission.Value
IsIntermission = true
function RoundHandler()
local PlayersInGroup = Players:GetPlayers()
if #PlayersInGroup > 1 then
CountdownStop:Fire()
Minutes.Value = 0
Seconds.Value = 0
GameHandlerMessage.Value = ""
local randomIndex = math.random(1, #PlayersInGroup)
local randomPlayer = PlayersInGroup[randomIndex]
task.wait(2)
Minutes.Value = 3
Seconds.Value = 25
CountdownBegin:Fire()
NighttimeFunction:Fire()
else
GameHandlerMessage.Value = "Game requires another person to start the round."
Minutes.Value = 0
Seconds.Value = 30
task.wait(30)
RoundHandler()
end
end
local function IsIntermissionChecker()
Minutes.Value = 1
Seconds.Value = 25
CountdownBegin:Fire()
print("Hey I'm going through")
task.wait(85)
RoundHandler()
end
IsIntermissionChecker()
Countdown Handler:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Minutes = ReplicatedStorage.GameConfiguration.Minutes
local Seconds = ReplicatedStorage.GameConfiguration.Seconds
local TextColor = ReplicatedStorage.GameConfiguration.TextColor
local SpecialEvents = ReplicatedStorage.SpecialEvents
local CountdownBegin = SpecialEvents.CountdownBegin
local CountdownStop = SpecialEvents.CountdownStop
local Countdown = coroutine.create(function()
while true do
if Seconds.Value <= 0 then
Minutes.Value = Minutes.Value - 1
Seconds.Value = 59
else
Seconds.Value = Seconds.Value - 1
end
wait(1)
end
end)
--[[if Minutes.Value < 1 and Seconds.Value <= 15 then
TextColor.Value = Color3.new(1, 0.329412, 0.341176)
else
TextColor.Value = Color3.new(1, 1, 1)
end]]
CountdownBegin.Event:Connect(function()
coroutine.resume(Countdown)
print("Went through")
end)
CountdownStop.Event:Connect(function()
print("Went through")
coroutine.yield(Countdown)
end)
You could just use seconds instead of minutes and seconds:
os.time() returns the number of seconds since the unix epoch.
if we save one os.time() and subtract it from one os.time() in the future, we know how many seconds have passed between these points in time.
we can then do something like this:
local startTick = os.time()
while task.wait() do
local currentSeconds = os.time() - startTick
end
This will be going up as time passes (by one each second) - however we want the timer to count down. We can accomplish that by subtracting a maximum by the current seconds.
local maximum = 60 --one minute
local timeLeft = maximum - currentSeconds
To convert the seconds into a string with minutes and seconds we can use this function:
local function addLeadingZero(s)
s = (s:len() == 1 and "0"..s) or s --if string length is 1 then string is gonna be "0"..rest of string
return s
end
local function formatSeconds(seconds)
seconds = math.clamp(seconds, 0, math.huge)
local minutes = math.floor(seconds/60)
seconds -= minutes*60
return addLeadingZero(tostring(minutes))..":"..addLeadingZero(tostring(seconds))
end
Honestly I do find the code very complex for me to understand. I want to have a system that’s like the coroutine that I’ve set up. I want it to be turned off and turned back on without any change to it.
It must be inside the coroutine itself in order to yield. I recommend that you just put the while loop at the very end of the script instead of a coroutine, and create a variable that is like a toggle. Only run the loop when that variable is true.
Countdown Handler:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Minutes = ReplicatedStorage.GameConfiguration.Minutes
local Seconds = ReplicatedStorage.GameConfiguration.Seconds
local TextColor = ReplicatedStorage.GameConfiguration.TextColor
local SpecialEvents = ReplicatedStorage.SpecialEvents
local CountdownBegin = SpecialEvents.CountdownBegin
local CountdownStop = SpecialEvents.CountdownStop
--[[if Minutes.Value < 1 and Seconds.Value <= 15 then
TextColor.Value = Color3.new(1, 0.329412, 0.341176)
else
TextColor.Value = Color3.new(1, 1, 1)
end]]
CountdownBegin.Event:Connect(function()
print("Went through")
countdownToggle = true
end)
CountdownStop.Event:Connect(function()
print("Went through")
countdownToggle = false
end)
while true do
if countdownToggle == true then
if Seconds.Value <= 0 then
Minutes.Value -= 1
Seconds.Value = 59
else
Seconds.Value -= 1
end
end
task.wait(1)
end
and that would be over-engineering (unless you want to do something after starting the loop) so it’s recommended that you just create a toggle variable and only do something in the loop if that variable is true
It doesn’t seem to restart. I did get print logs of the game going through the bindable events, and it did tick down, but it doesn’t restart the loop after it was toggled off.
This is the module script (you don’t have to change anything in here):
local Countdown = {}
Countdown.__index = Countdown
local function addLeadingZero(s)
s = (s:len() == 1 and "0"..s) or s --if string length is 1 then string is gonna be "0"..rest of string
return s
end
local function format(unix)
unix = math.clamp(unix, 0, math.huge)
local minutes = math.floor(unix/60)
unix -= minutes*60
return addLeadingZero(tostring(minutes))..":"..addLeadingZero(tostring(unix))
end
function Countdown.new(maxTime : number, startWithMax : boolean)
startWithMax = (startWithMax == nil and true) or startWithMax
local self = {}
self.MaxTime = maxTime
self.TimeRemaining = {
unix = ((startWithMax == true and 0) or 1)*maxTime,
format = format(self.MaxTime)
}
self.Finished = Instance.new("BindableEvent")
self.Updated = Instance.new("BindableEvent")
setmetatable(self, Countdown)
return self
end
function Countdown:Start(...)
local args = {...}
if self.PauseThread then
task.cancel(self.PauseThread)
end
self.Thread = task.spawn(function()
self.StartTick = args[1] or os.time()
while task.wait() do
local currentSeconds = os.time() - self.StartTick
local remainder = self.MaxTime - currentSeconds
if remainder < 0 then
self.TimeRemaining = {
unix = 0,
format = format(0)
}
self.Updated:Fire()
self.Finished:Fire()
return
end
if remainder ~= self.TimeRemaining.unix then
self.TimeRemaining = {
unix = remainder,
format = format(remainder)
}
self.Updated:Fire()
continue
end
self.TimeRemaining = {
unix = remainder,
format = format(remainder)
}
end
end)
end
function Countdown:Stop()
task.cancel(self.Thread)
self.Finished:Fire()
end
function Countdown:Continue()
task.cancel(self.PauseThread)
self:Start(self.StartTick)
end
function Countdown:Pause()
task.cancel(self.Thread)
self.PauseThread = task.spawn(function()
local distance = os.time() - self.StartTick
while task.wait() do
self.StartTick = os.time() - distance
end
end)
end
function Countdown:AddTime(delta)
self.StartTick += delta
end
function Countdown:Destroy()
setmetatable(self, nil)
self = nil
end
return Countdown
And this is an example Server script:
local Counter = require(script.Counter)
local count = Counter.new(70)
count:Start()
count:Pause()
count:Continue()
count.Updated.Event:Connect(function()
print(count.TimeRemaining.format)
end)
count.Finished.Event:Connect(function()
print("counter done!")
end)