Looping script where it should only run while "mined"

So I want to make a rock mining script, and right now its functioning fine, though the respawning script keeps looping a few times whilst the pickaxe is touching the rock, meaning that due to the randomness of the respawn, once it does respawn, if you come back to it to mine, it can keep on “respawning.”

"Focused" part of the script
		--Hiding the ores on the rock
		ore.Parent.OreVisibility.Transparency = 1
		Mined = true
		label.Active = false
		--Dropping the ore
		if script.Parent.OreDropped.Value == false then
			local Ores = ReplicatedStorage.Ores:FindFirstChild('Iron')
			local randomRaw = Ores:Clone()--[math.random(1, #Ores)]:Clone()
			randomRaw.Parent = game.Workspace
			randomRaw.Position = stonePos.Position
			local collectScript = ServerStorage:FindFirstChild('Collect'):Clone()
			collectScript.Parent = randomRaw
			script.Parent.OreDropped.Value = true
		end
		print('Ore Dropped')
		--Allowing the ore to be mined again
		wait(math.random(30, 60))
		ore.Parent.OreVisibility.Transparency = 0
		Mined = false
		script.Parent.OreDropped.Value = false
		swingsMax = math.random(5,15)
		swingsLeft = swingsMax
		label.Green.Size = UDim2.new(swingsLeft/swingsMax, 0, 1, 0)
		label.Active = true
		print('Respawned')```
Entire Script
--- Variables/References
--References
local ore = script.Parent.Stone
local stonePos = ore.Pos --Ore Drop Positioning

local label = ore.Health --Healthbar

local collider = ore.Collider --Custom hitbox
--Health Var
local swingsMax = 10
local swingsLeft = swingsMax
if swingsLeft == swingsMax then
	label.Green.Visible = false
	label.Bar.Visible = false
end --Hiding the healthbar on spawn (Hiding if no one else is already mining the rock)

local Mined = false

local ServerStorage = game:GetService('ServerStorage')
local ReplicatedStorage = game:GetService('ReplicatedStorage') --Literally just getting the server storage and replicated storage


--- Functionality
local function onTouch(otherPart)
	print('Collision detected')
	local tool = otherPart.Parent --When touching another part, it sets it to the tool value, then checks to make sure it is a tool
	if tool:IsA('Tool') and tool.Mining.Value == true and Mined == false then --If the tool is a pickaxe, and it has the mining value, and it is true, along with the ore not being
		print('Mining')
		local Strikes = script:GetChildren() --mined, it will start to mine.
		local RandomIndex = math.random(1, #Strikes) --SFX
		local RandomStrike = Strikes[RandomIndex]
		RandomStrike:Play()
		print('SFX Played')
		label.Bar.Visible = true --making sure the bar is visible
		label.Green.Visible = true
		swingsLeft -= tool.MineStrength.Value --Subtracting health based on a pickaxe's strength value
		label.Green.Size = UDim2.new(swingsLeft/swingsMax, 0, 1, 0)
		print('Health Subtracted')
		tool.Mining.Value = false
		wait(0.6)
	end
	if swingsLeft <= 0 then
		print('Broken')
		--Hiding the ores on the rock
		ore.Parent.OreVisibility.Transparency = 1
		Mined = true
		label.Active = false
		--Dropping the ore
		if script.Parent.OreDropped.Value == false then
			local Ores = ReplicatedStorage.Ores:FindFirstChild('Iron')
			local randomRaw = Ores:Clone()--[math.random(1, #Ores)]:Clone()
			randomRaw.Parent = game.Workspace
			randomRaw.Position = stonePos.Position
			local collectScript = ServerStorage:FindFirstChild('Collect'):Clone()
			collectScript.Parent = randomRaw
			script.Parent.OreDropped.Value = true
			print('Ore Dropped')
		end
		--Allowing the ore to be mined again
		wait(math.random(30, 60))
		ore.Parent.OreVisibility.Transparency = 0
		Mined = false
		script.Parent.OreDropped.Value = false
		swingsMax = math.random(5,15)
		swingsLeft = swingsMax
		label.Green.Size = UDim2.new(swingsLeft/swingsMax, 0, 1, 0)
		label.Active = true
		print('Respawned')
	end
end

--Finding touches
collider.Touched:Connect(onTouch)

--testprint("Hello world!")

Right now, my only idea for a solution to this is to add another variable titled “respawning,” and have this part of the script

"uberfocused part of script ig"
        wait(math.random(30, 60))
		ore.Parent.OreVisibility.Transparency = 0
		Mined = false
		script.Parent.OreDropped.Value = false
		swingsMax = math.random(5,15)
		swingsLeft = swingsMax
		label.Green.Size = UDim2.new(swingsLeft/swingsMax, 0, 1, 0)
		label.Active = true
		print('Respawned')

be changed to this

possible solution
local respawning = false

if respawning == false then
        respawning = true
        wait(math.random(30, 60))
		ore.Parent.OreVisibility.Transparency = 0
		Mined = false
		script.Parent.OreDropped.Value = false
		swingsMax = math.random(5,15)
		swingsLeft = swingsMax
		label.Green.Size = UDim2.new(swingsLeft/swingsMax, 0, 1, 0)
		label.Active = true
		print('Respawned')
        respawning = false

unless anybody has any simpler ideas?

For example, this is what happened after I left it to run and walked away for a moment
image
from one ore.

Maybe move your “swingsLeft” if statement into your tool if statement:
if tool:IsA('Tool') and tool.Mining.Value == true and Mined == false then
At the end before the wait. Not really sure how you’ve got everything set up but this seems like it would work.

Sorry, I’m not entirely sure I understand what you mean by this. Do you mean to have a

if tool:IsA('Tool') and tool.Mining.Value == true and Mined == false and swingsLeft >= 1

before running the script?

Sorry, I didn’t really explain that very well. Inside your onTouch function, you have an if statement that checks if the object is a tool and mining and if the rock hasn’t been mined completely yet.

Inside this if statement check, you would want to run your check to see if the “swingsLeft” on the rock has reached zero AFTER you have changed its value.

Something like:

local function onTouch(otherPart)
	local tool = otherPart.Parent
	if tool:IsA('Tool') and tool.Mining.Value == true and Mined == false then
		-- all your code and stuff
		swingsLeft -= tool.MineStrength.Value
		if swingsLeft <= 0 then
			-- Rock breaking code
		end
end

So you’re checking if the swingsLeft has reached 0 right after you’ve changed its value. This may or may not fix it.
Edit: Fixed some typos and grammar