I want to make a function where if the player uses the key X it will fire a remote event in a loop and if the player uses X again it will stop.
The problem is that even with the corrountine the event will not fire as if the thread was occuped
that’s my code:
local UIS = game:GetService("UserInputService")
local db = os.clock()
local Inputing = false
local function Meditate(Input,gp)
if gp or (os.clock() - db) < 1 then return end
if Input.KeyCode == Enum.KeyCode.X then
if Inputing == false then
Inputing = true
print(" X Pressed")
coroutine.resume(FireMeditation)
db = os.clock()
elseif Inputing == true then
coroutine.yield(FireMeditation)
print("hm")
Inputing = false
MeditateEvent:FireServer("Stop")
db = os.clock()
end
end
end
FireMeditation = coroutine.create(function()
while true do
task.wait(1)
MeditateEvent:FireServer("Meditate")
print("Test")
end
end)
UIS.InputBegan:Connect(Meditate)
the first time I tested the function I used corrountine.close to stop and it worked.
unfortunately you can’t yield a coroutine outside of a coroutine. Why are you firing the server every one second to begin with tho?
Regardless you want to create the coroutine when you want to actually use it
local UIS = game:GetService("UserInputService")
local db = os.clock()
local Inputing = false
local MeditationThread
--^^Define the local variable to show it will be in this context
local function Meditate(Input,gp)
if gp or (os.clock() - db) < 1 then return end
if Input.KeyCode == Enum.KeyCode.X then
if Inputing == false then
Inputing = true
print(" X Pressed")
--Define the coroutine when you actually want to create it
--Using task.spawn because you need to coroutine.resume threads
MeditationThread = task.spawn(function()
while true do
task.wait(1)
MeditateEvent:FireServer("Meditate")
print("Test")
end
end)
db = os.clock()
elseif Inputing == true then
--Check if meditation thread and if so then close it
if MeditationThread then
coroutine.close(MeditationThread)
MeditationThread = nil
end
print("hm")
Inputing = false
MeditateEvent:FireServer("Stop")
db = os.clock()
end
end
end
UIS.InputBegan:Connect(Meditate)
I wouldn’t have the client firing the server every second tho, as that’s a huge security risk (exploiters can fire the event when they arent supposed to and also fire it multiple times per second)
Instead I would suggest firing a remote event when the player toggles their meditation and then having the server handle it
If your script is in ServerScriptService then you will need a cache of player inputs however which is complicated. But if you put the localscript and serverscript in StarterPlayerScripts then you can have it per player. (but thats cringe so ill show you how to cache)
Client
MeditationRemote:FireServer("Meditate")
Server
--create our meditation cache to begin with
local MeditationCache = {}
MeditationRemote.OnServerEvent:Connect(function(plr)
--grab the meditation cache for this player
local PlayerMeditationCache = MeditationCache[plr]
--simple statement saying if the player's cache doesnt exist then return and do nothing
if not PlayerMeditationCache then return end
--clear the old coroutine
--we will always want just one coroutine
--so this ensures the slate is wiped clean whether we are turning it off or on
if PlayerMeditationCache.MeditationThread then
coroutine.close(PlayerMeditationCache.MeditationThread)
PlayerMeditationCache.MeditationThread = nil
end
if PlayerMeditationCache.IsMeditating then
--IsMeditating is true, toggle it off
PlayerMeditationCache.IsMeditating = false
else
--IsMeditating is false, toggle it on
PlayerMeditationCache.IsMeditating = true
PlayerMeditationCache.MeditationThread = task.spawn(function()
repeat
task.wait(1)
--do stuff here
until false
end)
end
end)
--player added to add in the player's data
game.Players.PlayerAdded:Connect(function(plr)
--set the player's meditation cache to blank data
MeditationCache[plr] = {
IsMeditating = false;
MeditationThread = nil;
}
end)
--player removing to clean up memory leaks
--we want to clean the player cache when they leave
--or else the player object will remain in memory forever and thats cringe
game.Players.PlayerRemoving:Connect(function(plr)
MeditationCache[plr] = nil
end)
But there’s something I didn’t understand, in “MeditationCache[plr]” what is the value between the “[ ]” ? a index? I couldn’t understand it even in the roblox documentation.
the value between the [] is an index. With dictionaries you have indexes and values. However indexes do not always need to be strings. In this case the indexes are the player objects while the value is the data you want to cache
local Dict = {
[game.Workspace] = "goofy ahh"
--game.workspace for key, goofy ahh for value
}
print(Dict[game.Workspace])--prints "goofy ahh"
Okay, thanks bro, I thought that the index in a dictionary was the keys, so the only way to make a different dictionary for every player was with arrays or something like that.