How to point your hand toward the mouse when holding the tool

I wanted to make a flashlight tool, but I didn’t know the script that the arm points to the mouse, so I looked around, but they pointed to the mouse from start to finish, and the arm The range of motion was also unrestricted.
What kind of script should I use to point the mouse only when I have the tool and limit the range of motion of my arm? Thank you.

2 Likes

I haven’t tested this, but try calling rotateArm on RunService.Stepped and give it the RightShoulder Motor6D. If Transform isn’t updated on Stepped, the changes will be overwritten by animations. You could use Tool.Equipped to detect when the tool is equipped. Then create a Stepped connection and store the Stepped connection in a variable. Disconnect the Stepped connection when the tool is unequipped (use Tool.UnEquipped for this).

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

-- Replace the limits with your own values.
local X_MIN_DEG = -180
local X_MAX_DEG = 180

local Y_MIN_DEG = -180
local Y_MAX_DEG = 180

local Z_MIN_DEG = -180
local Z_MAX_DEG = 180

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

local radLimits = {
    math.rad(X_MIN_DEG),
    math.rad(X_MAX_DEG),
   
    math.rad(Y_MIN_DEG),
    math.rad(Y_MAX_DEG),

    math.rad(Z_MIN_DEG),
    math.rad(Z_MAX_DEG)
}

local function rotateArm(joint)
    local jointDefaultCfWorldSpace = joint.Part0.CFrame*joint.C0
    local jointTargetCfWorldSpace = CFrame.new(jointDefaultCfWorldSpace.Position, mouse.Hit.Position)
    
    -- transform angles
    local x, y, z = (jointDefaultCfWorldSpace:Inverse()*jointTargetCfWorldSpace):ToEulerAnglesXYZ()
    x = math.clamp(x, radLimits[1], radLimits[2])
    y = math.clamp(y, radLimits[3], radLimits[4])
    z = math.clamp(z, radLimits[5], radLimits[6])
    
    joint.Transform = CFrame.Angles(x, y, z)
end

Edit: You’re right, @WaterJamesPlough, I’ve fixed that now

1 Like

Just noticed a mistake in the script, y and z variables should be these instead, I believe:

y = math.clamp(y, radLimits[3], radLimits[4]
z = math.clamp(z, radLimits[5], radLimits[6]
1 Like

I got a error from this : [ToEulerAnglesXYZ is not a valid member of Vector3]
What should I do?

Edit : I fixed with using “fromEulerAnglesXYZ”.
but another error I got : [Argument 3 missing or nil]

I had forgotten to write CFrame.new() on one line. Does it now work?

I checked using RunService.RenderStepped:Connect(rotateArm(plr.Character.RightUpperArm.RightShoulder)), but I got the error “Attempt to connect failed: Passed value is not a function”.

So it means “No.”

RunService.RenderStepped:Connect(rotateArm(plr.Character.RightUpperArm.RightShoulder))

Passes the return value of rotateArm as the argument to the Connect method. It returns nothing, so that value is nil. Try this instead.

RunService.Stepped:Connect(function()
    rotateArm(plr.Character.RightUpperArm.RightShoulder)
end)

Remember to use Stepped instead of RenderStepped, it’s important when updating Transform.

What should I say … It’s strange.
Since it is difficult to say by mouth, I will attach an image.


also a video

This works better. Not properly, though. The arm rotation doesn’t work properly when mouse.Hit.Position is behind the character. I don’t know how to fix it.

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

-- Replace the limits with your own values.
local X_MIN_DEG = 15
local X_MAX_DEG = 145

local Z_MIN_DEG = -30
local Z_MAX_DEG = 30

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

local radLimits = {
	math.rad(X_MIN_DEG),
	math.rad(X_MAX_DEG),

	math.rad(Z_MIN_DEG),
	math.rad(Z_MAX_DEG)
}

local function rotateArm(char)
	local hrp = char:WaitForChild("HumanoidRootPart")
	local rShoulder = char:WaitForChild("RightUpperArm"):WaitForChild("RightShoulder")

	local mouseHit = mouse.Hit
	local mouseHitPos = mouseHit.Position
	
	local jointDefaultCfWorldSpace = rShoulder.Part0.CFrame*rShoulder.C0
	local jointTargetCfWorldSpace = CFrame.new(jointDefaultCfWorldSpace.Position, mouseHitPos)*CFrame.Angles(math.pi/2, 0, 0)

	-- transform angles
	local dir = (mouseHitPos-jointDefaultCfWorldSpace.Position).Unit
	local x = math.abs(dir.Y*math.pi/2+math.pi/2)
	local z = math.atan2(dir.Z, dir.X)-math.atan2(jointDefaultCfWorldSpace.LookVector.Z, jointDefaultCfWorldSpace.LookVector.X)
	
	x = math.clamp(x, radLimits[1], radLimits[2])
	z = math.clamp(z, radLimits[3], radLimits[4])

	rShoulder.Transform = CFrame.Angles(x, 0, z)
end
4 Likes

Thank you very much. It worked.
This is the last question, but how do I enable it when I have the tool and restore it when I don’t have the tool?
I’m sorry to ask many questions.

local steppedConn
tool.Equipped:Connect(function()
    steppedConn = RunService.Stepped:Connect(function()
        updateArm(char)
    end)
end)
tool.Unequipped:Connect(function()
    steppedConn:Disconnect()
end)
4 Likes