How would I cancel a function?

With my gun, I have the player’s walkspeed change upon aiming down on a player. However, if the player unequips the tool the gun still fires, plus their walkspeed doesn’t go back to normal. How would I cancel a function, as well as detect if its cancelled?

local gun = script.Parent
local RS = game:GetService("RunService")
local firing = false--bool value to make sure you cant fire twice while you are firing
local aimTime = 4
local aimSound = gun.Handle.Aim
local shotSound = gun.Handle.Fire
local aimWalkSpeed = 0
local range = 100--max range
local maxuses = 5
local uses = 5

function aimStarted()
	local character = gun.Parent or gun.Parent.Parent.Character
	firing = true
	aimSound:Play()
	character.Humanoid.WalkSpeed = aimWalkSpeed
end

function aimEnded()
	local character = gun.Parent or gun.Parent.Parent.Character
	character.Humanoid.WalkSpeed = 13.5
	firing = false
end

local function FireWeapon(player, target)
	local text = require(player.PlayerGui.TextSystem.TextModule)
	local gunCast = gun.Handle
	local RootPart = target.Parent.HumanoidRootPart
	local parameters = RaycastParams.new()
	parameters.FilterType = Enum.RaycastFilterType.Blacklist
	parameters.FilterDescendantsInstances = {player.Character, gun, target.Parent}
	local GunRay = workspace:Raycast(gunCast.Position, RootPart.Position - gunCast.Position)
	if GunRay.Instance.Name ~= RootPart.Name and uses > 0 then
		uses -= 1
		if uses < 1 then
			uses = 0
		end
		gun.ToolTip = uses.."/"..maxuses.." shots left."
		text.CreateNewLabel("Shot missed.", Color3.fromRGB(255, 162, 153))
		shotSound:Play()
	elseif GunRay.Instance.Name == RootPart.Name and uses > 0 then
		uses -= 1
		if uses < 1 then
			uses = 0
		end
		gun.ToolTip = uses.."/"..maxuses.." shots left."
		text.CreateNewLabel("Shot hit "..target.Parent.Name..".", Color3.fromRGB(200, 26, 26))
		shotSound:Play()
		target.Parent.Humanoid:TakeDamage(100)
	elseif uses <= 0 then
		uses = 0
		text.CreateNewLabel("Out of ammunition.", Color3.fromRGB(255, 0, 4))
		gun.Handle.NoAmmo:Play()
	end
end

script.Parent.MouseEvent.OnServerEvent:Connect(function(player, target)--if player clicks on target
	local text = require(player.PlayerGui.TextSystem.TextModule)
	local magnitude = (target.Parent.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).Magnitude
	if firing == false and magnitude < range then
		text.CreateNewLabel("You aim in..", Color3.fromRGB(123, 163, 255))
		aimStarted()
		task.wait(aimTime)
		FireWeapon(player, target)
		task.wait(0.5)
		FireWeapon(player, target)--each fire function is 1 shot, i want it so that if you unequip the tool, the function doesn't continue.
		task.wait(0.5)
		FireWeapon(player, target)
		task.wait(0.2)
		aimEnded()
	elseif magnitude > range then
		text.CreateNewLabel("Out of range.", Color3.fromRGB(234, 234, 234))
    end
end)

Does anyone know?

You can return it or use

:Disconnect()

:Disconnect() makes it so the function can’t be used again, not cancel it, and with return, I’m not sure when/how to use it.

You can use return like this let me know how it works out for you and if you have questions [quote=“HearTheThing, post:1, topic:2182099”]

function aimStarted()
	local character = gun.Parent or gun.Parent.Parent.Character
	firing = true
	aimSound:Play()
	character.Humanoid.WalkSpeed = aimWalkSpeed
return
end

function aimEnded()
	local character = gun.Parent or gun.Parent.Parent.Character
	character.Humanoid.WalkSpeed = 13.5
	firing = false
return
end

[/quote]

I did this, and it made the script fire only once

Yeah you have to call the function again if you want it to run again. You said you are trying to cancel the function?

Cancel like this:
Player clicks on target > aimStart activated > walkspeed changes to 0 > FireWeapon(player, target) > FireWeapon(player, target) > FireWeapon(player, target) > FireWeapon(player, target) > aimEnded()

So if anytime inbetween the chain the player, for example dies or unequips the tool, it goes straight to aimEnded() instead of firing the gun.

Player clicks on target > aimStart activated > walkspeed changes to 0 > FireWeapon(player, target) > FireWeapon(player, target) > player dies > aimEnded()

You can make a function checking if it met your specific condition then return it once it meets that condition like dying, etc

1 Like

Something like this?

function checkForCancel(player, target)
	if player.Health < 1 then
		player.Character.Humanoid.WalkSpeed = 13.5
		firing = false
	   return
	end
end

1 Like

Yes if that is what you are trying to achieve then that should work for you.

return returns Data and ends a function early, if you want to completely cancel something, try coroutines or task if you want it to not yield and end the function where its at

local co = coroutine.wrap(function()
    -- code here
end)()

if Condition then
    if coroutine.status(co) ~= "dead" then
        coroutine.close(co) -- closes thread
    end
end
thread = task.spawn(function()
    -- code
end)

task.cancel(thread) -- cancels thread by stopping it

I’ve tried with cororutine.close() before, it cancels it but it makes it so the function can never be used again. Does task.cancel() do the same thing?

Something like

function aimStarted()
	local character = gun.Parent or gun.Parent.Parent.Character
	firing = true
	aimSound:Play()
	character.Humanoid.WalkSpeed = aimWalkSpeed
    if not firing then return end 
end

function aimEnded()
	local character = gun.Parent or gun.Parent.Parent.Character
	character.Humanoid.WalkSpeed = 13.5
	firing = false
end
1 Like

This doesn’t do anything as aimStarted() only runs once.

To fix the firing issue you can use if statements

local function FireWeapon(player, target)
if firing then
--stuff
end

Yes thanks, your solution helped me find an answer to my problem.

I can’t even tell if this is sarcasm, if it is then I’ll look deep into a solution for you

No, it actually did, i’m putting if not equipped then return end in the middle of each fire event, it stops the function.

1 Like

However, one more thing. Would it be possible to put more functions inside of the return end, for example:

if not equipped then

do stuff
return

Would that give the same result, or a different one?

I’m not too sure what you mean. Once return has been called, the function ends, it does not “continue” beyond that point