When I click faster than the wait timer It doubles the loop

I am trying to make it so when I hold the mouse button down it shoots, but when I click my mouse faster than the wait timer in the loop it makes a new loop

this is what happens

here is my code

function shoot()
	if magazine > 0 then
		if firing then
			local mousePosition = mouse.Hit.Position
			fireEvent:FireServer(mousePosition)
			magazine -= 1
		end
	else
		if reloading == false then
			reloading = true
			magazine = 0
			wait(reloadtime)
			magazine = magazinesize
			reloading = false
		end
	end
end

mouse.Button1Down:Connect(function()
	if firing == false then
		firing = true
		while firing do --this is the loop that errors
			shoot()
			wait(1 / firerate)
		end
	end
end)

mouse.Button1Up:Connect(function()
	firing = false
end)

Can i have more detail

  1. What object’s script are you using for this?
  2. What exactly do you mean by clicking ‘faster than the wait timer’, do you mean clicking faster than ‘wait(X)’ or do you mean clicking faster than any timer that is in the loop? (For example, if you have a script with this loop: while true do … end
    Do you mean clicking faster than the loop?)

I have figured out the problem heres the new modified code

local Shooting = true
local magazine = 5
local reloadtime = 1
local firerate = 1
function shoot()
if magazine > 0 then
if firing then
local mousePosition = mouse.Hit.Position
fireEvent:FireServer(mousePosition)
magazine -= 1	
wait(reloadtime)	

I have fixed the loop and made it way more easier to read

The issue its not the loop specifically, its about the debounce “firing”. More than one loop is created when you click fast, not related with the wait() time in the script. Once you ButtonUP, the debounce is open again to accept inputs again, so you are triggering it many times causing multiple loops.
Then the way the while loop is using to break, while firing do, makes it to wait wait(1 / firerate), causing it wont break in the exact moment the ButtonUP happens.

If this already Client sided which is not exactly recomended to handle the magazine player has… You could use a RunService step connection calling the shoot function when ButtonDown, and disconnect it when ButtonUP, to “stop the loop” in the exact moment the ButtonUP happens.

This is specifically for your current approach, of Client sided handling magazine and stuff. Its just an edited version of your script using RunService check and splitting functions.

local Players = game:GetService("Players")
local RS = game:GetService("RunService")

local player = Players.LocalPlayer
local mouse = player:GetMouse()

-- 2 bullets per second, one each 0.5 seconds
local firerate = 0.5

-- bullets in gun
local magazine = 7
-- default size of magazine
local magazinesize = 7

-- reload debounce and time
local reloading = false
local reloadtime = 4

-- player's holding button time
local fireTime = 0

-- RunService step connection
local fireConn

-- Reload function
local function Reload()
	warn("Reloading")
	task.wait(reloadtime)
	print("Reload done")
	magazine = magazinesize
	reloading = false
end

-- Shooting function
function Shoot()
	if magazine > 0 then
		warn("shoot")
		local mousePosition = mouse.Hit.Position
		
		fireEvent:FireServer(mousePosition) -- Your server call
		
		magazine -= 1
		print("remaining mag:", magazine)
	else
		print("mag empty")
		reloading = true
		fireConn:Disconnect()
		Reload()
	end
end


mouse.Button1Down:Connect(function()
	if not reloading then
		-- THE "LOOP" connection. A RunService step
		fireConn = RS.RenderStepped:Connect(function(d)
			fireTime += d -- delta progress
			if fireTime >= (1*firerate) then -- if enough time since last shoot, shoot again
				fireTime = 0
				Shoot()	
			end
		end)
		Shoot() -- First shoot when holding button
	else
		warn("cant shoot while reloading")
	end
end)

mouse.Button1Up:Connect(function()
	fireConn:Disconnect() -- Disconnect the "loop" inmediately
end)

*It has prints and warns for you to check it in Output

this works but when it reloads and I keep holding the mouse button it stops shooting

also when I spam mouse this happens

local mouse = game.Players.LocalPlayer:GetMouse()


local mag = {
	["bullets"] = 0,
	["capacity"] = 10
}
local reloading = false
local m1down = false
local shotsPerSecond = 15
local reloadBulletsPerSecond = 1.2


mouse.Button1Down:Connect(function() reloading = false m1down = true end)
mouse.Button1Up:Connect(function() m1down = false end)



game:GetService("UserInputService").InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then return end
	if input.UserInputType == Enum.UserInputType.Keyboard then
		if input.KeyCode == Enum.KeyCode.R then
			if mag.bullets < mag.capacity then
				reloading = true
			end
		end
	end
end)


local i = 0
local lastShot = os.clock()
local lastBulletReload = os.clock()
while true do
	if reloading and (os.clock() - lastBulletReload) >= (1/reloadBulletsPerSecond) then
		if (mag.bullets < mag.capacity) then
			mag.bullets += 1
			print("reload click "..mag.bullets.."/"..mag.capacity)
			lastBulletReload = os.clock()
		else
			reloading = false
		end
	end
	if (m1down and not reloading and (os.clock() - lastShot) >= (1/shotsPerSecond)) then
		if (mag.bullets > 0) then
			mag.bullets -= 1
			print("pew "..mag.bullets.."/"..mag.capacity)
			lastShot = os.clock()
			if mag.bullets == 0 then
				reloading = true
			end
		else
			reloading = true
		end
	end
	i += 1
	if (i > 300) then wait() i = 0 end
end
1 Like

thanks, this works just as I wanted! : )

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