Breaking a while loop within the same function

im trying to make a flashlight script with a limited battery but it keeps draining the battery after i turn it off
this is the code in a serverscript

battery = script.Parent.Parent:GetAttribute("battery")
efficiency = script.Parent.Parent:GetAttribute("efficiency")
game.ReplicatedStorage["battery script"].OnServerEvent:Connect(function(on, thing)
	print(on)
	print(thing)
	if thing then
		repeat
			battery -= 1
			print(battery)
			wait(efficiency)
		until not on
		
	elseif not thing then
		print("please turn off")
	end
	end)
1 Like

you should use an Attribute or variable set somewhere else and instead of sending the on variable that never changes once the function is fired send say the flashlight and have the attribute set on there to true if on and nil of off then just check until not flashlight:GetAttribute('OnStatus')

set using something like this
flashlight:SetAttribute('OnStatus', true)
turn off like this
flashlight:SetAttribute('OnStatus', nil)

1 Like

I would make a new attribute on the flashlight that dictates whether or not its on, and then whenever the remote is fired just switch the attribute to the other value
There are also some other issues,
After you get the battery value, editing it just edits the variable you set, not the original attribute
Also the player should be passed to the function If you are using remote events

local IDK = script.Parent.Parent
local efficiency = IDK:GetAttribute("efficiency")

game.ReplicatedStorage["battery script"].OnServerEvent:Connect(function(Player,on, thing)
	if IDK:GetAttribute("On") then
		IDK:SetAttribute("On",false)
	else
		IDK:SetAttribute("On",true)
		while IDK:GetAttribute("On") do
			Task.Wait(efficiency)
			IDK:SetAttribute("battery",IDK:GetAttribute("battery")-1)
		end
	end
end)
1 Like

When I spam click it starts counting down faster?

Didn’t think of that, this should fix that

local IDK = script.Parent.Parent
local efficiency = IDK:GetAttribute("efficiency")

game.ReplicatedStorage["battery script"].OnServerEvent:Connect(function(Player,on, thing)
	if IDK:GetAttribute("On") then
		IDK:SetAttribute("On",false)
	else
		IDK:SetAttribute("On",true)
		while IDK:GetAttribute("On") do
			local Connection = IDK:GetAttributeChangedSignal("On"):Connect(function()
				Connection:Disconnect()
			end)
			Task.Wait(efficiency)
			if Connection then
				IDK:SetAttribute("battery",IDK:GetAttribute("battery")-1)
					Connection:Disconnect()
				end
			end
		end
	end
end)

it gives me an error on line 11 saying connection is an unknown global

You should check out Fusion States… much cleaner in my opinion.

https://elttob.uk/Fusion/0.3

local Battery = Value(100)
local Efficiency = Value(5)
local IsDraining = Value(false)

game.ReplicatedStorage["battery script"].OnServerEvent:Connect(function(Player,on, thing)
    if not thing then
        print("please turn off")

        return;
    end

    IsDraining:set(on)
end)

Observer(IsDraining):onChange(function()
    local value = peek(IsDraining)

    if value then
        while peek(IsDraining) do
            Battery:set( peek(Battery) - 1 )
            task.wait( peek(Efficiency) )
        end
    end
end)

is there a way to do this without fusion states?

I saw there was a small bug in @LividDreaming 's code, this should fix it, try this first

local IDK = script.Parent.Parent
local efficiency = IDK:GetAttribute("efficiency")

game.ReplicatedStorage["battery script"].OnServerEvent:Connect(function(Player,on, thing)
	if IDK:GetAttribute("On") then
		IDK:SetAttribute("On",false)
	else
		IDK:SetAttribute("On",true)
		while IDK:GetAttribute("On") do
			local Connection;
            Connection = IDK:GetAttributeChangedSignal("On"):Connect(function()
				Connection:Disconnect()
			end)
			Task.Wait(efficiency)
			if Connection then
				IDK:SetAttribute("battery",IDK:GetAttribute("battery")-1)
					Connection:Disconnect()
				end
			end
		end
	end
end)
1 Like

It seems unnecessary to create a Connection and disconnect over and over in a loop when the loop itself is based off of that variable. I’d think this would suffice but I will say I did not test it:

local IDK = script.Parent.Parent
local efficiency = IDK:GetAttribute("efficiency")

game.ReplicatedStorage["battery script"].OnServerEvent:Connect(function(Player,on, thing)
	if IDK:GetAttribute("On") then
		IDK:SetAttribute("On",false)
	else
		IDK:SetAttribute("On",true)
		while IDK:GetAttribute("On") do
			task.wait(efficiency)
			IDK:SetAttribute("battery",IDK:GetAttribute("battery")-1)
		end
	end
end)
1 Like

I didn’t make the script, LividDreaming did. however you should check if efficiency changes and then i think the script should be good

Just add a task.spawn that has a debounce with matching timing to the rate the battery is falling, then only lower battery while the debounce is not active?

Sounds about right. Didn’t see @LividDreaming first code and just rewrote it, Whoops.

1 Like

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