How do I bind MouseHold to ContextActionService?

Let’s say whenever the mousebutton1 is down, i’ll fire a function, when it’s up, it will stop firing.

CAS:BindAction("ShootWeapon", EnableShoot, false, Enum.UserInputType.MouseButton1)

What should I change the fourth argument to such that it will detect mouse button hold? I want to pair up ContextActionService with IsMouseButtonPressed but how?

Just use RunService heartbeat to run the code while the button is down?

Bind the button being down and up to functions which change a variable and then use runservice to do something IF the variable is true, or if you’re feeling extra spicy, write a while loop with heartbeat straight into your function

You can do delays by using Heartbeat’s return which is how long it took since the last heartbeat

1 Like

Your code already does that. All context action binds fire twice: once when the input starts and once when the input ends. There are other cases where other states will fire as well though. All you need to do is check for the current InputState and change a value based off of that.

local mouseHeld = false

local function mouseDetermineDown(actionName, inputState, inputObject)
    mouseHeld = (inputState == Enum.UserInputState.Begin)
end

ContextActionService:BindAction("MouseHold", mouseDetermineDown, false, Enum.UserInputType.MouseButton1)
2 Likes

I just added those three arguments to check whether the InputState is begin or not, it still won’t fire when I hold down the mouse button.

What does your code currently look like? An explicit mouse held input state doesn’t exist: what you’re intended to do is check when the mouse is pressed down and then when it’s next released, then anything in that time period is counted as the mouse being held.

I’m testing this in Studio and my barebones code works fine. I have a strong feeling that it has to do with your current implementation and how something is blocking it from running.

Maybe you get me wrong: whenever the mouse is holding down, I want it to keep firing the function until MouseUp.

But I think I’m not going to use ContextActionService for this anymore… When I bind Right Mouse Down to a function, it overlays and I can’t rotate my camera. I’ll probably stick with mouse.KeyDown or UserInputService…

Is there any better solution? I’d like to utilize ContextActionService for cleaner code and moblie/console controls for future development.

I don’t get you wrong. The state of a mouse being held down refers to the time between when you press the mouse down and when you next click up. Therefore, when you press the mouse button down, your function runs until the button is released. I said that.

Like I said: there is most likely something you aren’t doing right that is blocking the code from running. To know this, I actually need to see your implementation to understand where specifically in your case, you went wrong and prevented this code from running.

If you have difficulty doing this with ContextActionService, you aren’t necessarily going to have an easier time with UserInputService or KeyDown (which is deprecated and should not be used). The process is still relatively the same, just with more steps involved.

The better solution is to fix your current code instead of relying on workarounds that may not even solve your issue, or may lead you into other kinds of problems to have to resolve.

So what if I want it to repeatedly fire it until MouseButton is up?
Here’s a function that I wrote for firing a weapon, it will first check is the weapon fireable such as Ammo Count, is it equipped etc. Then it will fire the gun.

function EnableShoot(actionName, inputState, inputObj)
	if inputState == Enum.UserInputState.Begin then
        -- Check for Gun State
        -- If pass then shoot

Bind Action:
CAS:BindAction("ShootWeapon", EnableShoot, false, Enum.UserInputType.MouseButton1)

To do this you can use a while loop when the input begins with a variable that is set to true. Once the input has ended you can set the variable to false which will stop the loop. It will end up looking something similar to what Colbert suggested.

local mouseHeld = false

local function mouseDetermineDown(actionName, inputState, inputObject)
    if inputState == Enum.UserInputState.Begin then
        mouseHeld = true
        while mouseHeld and ammo > 0 do 
            -- shoot
        end
    elseif inputState == Enum.UserInputState.End then
        mouseHeld = false
    end
end

ContextActionService:BindAction("MouseHold", mouseDetermineDown, false, Enum.UserInputType.MouseButton1)

Alternatively, you could use the UserInputService which is what I personally prefer. On InputBegan you would set a variable to true, in this example I name it “firing”. You would then create a while loop that runs under the conditions that firing is true and the ammo count is above 0. Then on InputEnded we would simply change firing to false which will stop the loop running.

local firing = false

UserInputService.InputBegan:Connect(function(inputObject, gameProcessed)
    if gameProcessed then return end
    if inputObject.UserInputType == Enum.UserInputType.MouseButton1 then
		firing = true
		while firing and ammo > 0 do
			-- shoot
		end
	end
end)

UserInputService.InputEnded:Connect(function(inputObject)
    if inputObject.UserInputType == Enum.UserInputType.MouseButton1 then
		firing = false
	end
end)
6 Likes