Tracker tool beep loop beeps too fast when reequipping tool

Hello everyone! :wave::slightly_smiling_face:
I’m having issues with my script that is supposed to make a tool beep faster when the player is closer to, what’s here the entity, but when I quickly unequip and reequip the tool, the tool beeps twice as fast. And of course, I don’t want that to happen, because then the player thinks that the entity suddenly came really close to them.

This is the script:

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local ScreenPopup = Remotes:WaitForChild("ScreenPopups")

local round = require(ServerScriptService:WaitForChild("GameSystems").RoundServer.Round)

local tool = script.Parent

local BeepSound = tool.Handle.Beep
local LightPart = tool.Light
local target = nil

local looping = false
local inBackpack = true

local function LightPing()
	TweenService:Create(
		LightPart,
		TweenInfo.new(0.3, Enum.EasingStyle.Linear),
		{ Color = Color3.fromRGB(255, 0, 0) }
	):Play()
	
	task.wait(0.5)
	
	TweenService:Create(
		LightPart,
		TweenInfo.new(1, Enum.EasingStyle.Linear),
		{ Color = Color3.fromRGB(25, 25, 25) }
	):Play()
end

local function HandleAll()
	repeat
		BeepSound:Play()
		ScreenPopup:FireClient(Players:GetPlayerFromCharacter(tool.Parent), "EntityLocation", target)
		LightPing()

		task.wait(0.0025 / (0.25 / (tool.Handle.Position - target.Position).Magnitude))
	until looping == false or inBackpack == true
end

local function Handle()
	local entity = round.Entity
	
	if entity then
		target = entity.Character.PrimaryPart
		
		if not inBackpack then
			HandleAll()
		end
	else
		target = game.Workspace.Entity
		
		if not inBackpack then
			HandleAll()
		end
	end
end

tool.Equipped:Connect(function()
	looping = true
	inBackpack = false
	Handle()
end)

tool.Unequipped:Connect(function()
	looping = false
	inBackpack = true
end)

Also sorry if you lost braincells by reading the post title :skull_and_crossbones:

First, check, try to wrap some code into a new thread like so:

local function HandleAll()
	repeat
		task.spawn(function()
			BeepSound:Play()
			ScreenPopup:FireClient(Players:GetPlayerFromCharacter(tool.Parent), "EntityLocation", target)
			LightPing()
		end)
		task.wait(0.0025 / (0.25 / (tool.Handle.Position - target.Position).Magnitude))
	until looping == false or inBackpack == true
end

If that doesnt work, tell me, I dont have access to studio, and I’ll try more.

The delay works better now, since there isn’t a task.wait(0.5) in the main thread, but the sound still plays more often when you unequip and quickly equip afterwards.

Hm, I’ll get thinking a bit more about it.

I don’t think I can find a solution currently. Sorry.

It’s due to the fact that when you unequip and equip while the task.wait() is yielding, you call HandleAll() again before it even finishes. This creates another repeat loop but the condition for the existing repeat loop is still met by the time it finishes.

You can scrap that completely and add this at the bottom of your script:

while true do
	if target ~= nil then
		BeepSound:Play()
		ScreenPopup:FireClient(Players:GetPlayerFromCharacter(tool.Parent), "EntityLocation", target)
		LightPing()
			
		task.wait(0.0025 / (0.25 / (tool.Handle.Position - target.Position).Magnitude))
	else
		task.wait()
	end
end

Or if you prefer a smaller footprint method:

local toolThread: thread? = nil

local function toggleTool(toggle: boolean): ()
	if toggle == true and toolThread == nil then
		toolThread = task.spawn(function()
			while true do
				if target ~= nil then
					BeepSound:Play()
					ScreenPopup:FireClient(Players:GetPlayerFromCharacter(tool.Parent), "EntityLocation", target)
					LightPing()

					task.wait(0.0025 / (0.25 / (tool.Handle.Position - target.Position).Magnitude))
				else
					task.wait()
				end
			end
		end)
	elseif toggle == false and toolThread ~= nil then
		task.cancel(toolThread)
		toolThread = nil
	end
end

tool.Equipped:Connect(function(): ()
	toggleTool(true)
end)

tool.Unequipped:Connect(function(): ()
	toggleTool(false)
end)
2 Likes