I’m trying to make a time limit for the player to answer the question, but it seems like the player is never able to answer. It will always return false from the countdown.
local function waitForAnswer(plr, answers)
timeUp = false
local count = 10
while timeUp == false do
wait(1)
sounds.Tick:Play()
count -= 1
print(count)
if count == 0 then
timeUp = true
sounds.Alarm:Play()
return false
end
end
local msg = plr.Chatted:Wait()
if table.find(answers, string.lower(msg)) and timeUp == false then
sounds.Guess:Play()
timeUp = true
return true
elseif not table.find(answers, string.lower(msg)) and timeUp == false then
sounds.Guess:Play()
timeUp = true
return false
end
end
You have return false inside the while loop. It returns false when count reaches 0, which will always happen, so it will always return false, exiting the function and not reaching the lines below.
I understand now, you meant to have both running at once. It won’t wait for the player to chat until after the while loop finishes, but that’s meant to indicate they’ve run out of time. You want these to run concurrently, so you’ll need to make use of concurrency methods like task.spawn
The code i’m using isn’t returning anything. I’m sure i’m doing something incorrect.
local function waitForAnswer(plr, answers)
timeUp = false
local count = 10
task.spawn(function()
while timeUp == false do
wait(1)
sounds.Tick:Play()
count -= 1
print(count)
if count == 0 then
timeUp = true
sounds.Alarm:Play()
break
end
end
return false
end)
local msg = plr.Chatted:Wait()
if table.find(answers, string.lower(msg)) and timeUp == false then
sounds.Guess:Play()
timeUp = true
return true
elseif not table.find(answers, string.lower(msg)) and timeUp == false then
sounds.Guess:Play()
timeUp = true
return false
end
end
The first return here is now inside another function, so it doesn’t influence the outer function. Something easy you could do is just set a variable to false if time runs out, and once the player does chat, check that variable and return false if they ran out of time before they chatted. If you want it to return immediately when thy either chat or run out of time then that’s a bit more complex.
local function waitForAnswer(plr,answers)
local timeUp = false
task.spawn(function()
for count = 10,0,-1 do
sounds.Tick:Play()
task.wait(1)
end
timeUp = true
sounds.Alarm:Play()
end)
local msg = plr.Chatted:Wait()
if (timeUp) then
return false;
end
timeUp = true
sounds.Guess:Play()
return (table.find(answers, string.lower(msg)) and not timeUp)
end
The more complex solution which returns immediately either when the player chats or runs out of time might look something like this (untested)
local function waitForAnswer(plr, answers)
local main = coroutine.running()
local chatted
local timeout = task.spawn(function()
for i = 1, 10 do
task.wait(1)
sounds.Tick:Play()
end
sounds.Alarm:Play()
chatted:Disconnect() -- stop waiting for the player to chat
coroutine.resume(main, false)
end)
chatted = plr.Chatted:Once(function(msg)
sounds.Guess:Play()
local foundAnswer = table.find(answers, msg:lower())
coroutine.close(timeout) -- cancel the countdown
coroutine.resume(main, foundAnswer ~= nil)
end)
return coroutine.yield()
end
coroutine.yield() returns whatever additional arguments were passed to coroutine.resume, so whenever either thing happens, it cancels the other and resumes the calling coroutine.
coroutine.running() gets the current coroutine so I can resume it from one of the others with coroutine.resume. task.spawn returns a coroutine, so when I want to cancel the countdown because the player chatted, I can call coroutine.close on it so it doesn’t continue running. task.cancel might be more appropriate, I’m not sure what the difference is.