Odd error i cant wrap my head around (help appreciated please)

hello robloxians im having issues with this and i cant figure out what to do im at a loss

External Media

heres the script i use

-- LocalScript inside StarterPlayerScripts

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local runService = game:GetService("RunService")

-- Variables for controlling the arm in an R6 rig
local rightArm = character:WaitForChild("Right Arm")
local torso = character:WaitForChild("Torso")
local rightShoulder = torso:WaitForChild("Right Shoulder")

local originalC0 = rightShoulder.C0

-- Reference to the flashlight tool
local flashlightTool = player:WaitForChild("Backpack"):WaitForChild("Flashlight")
local light = flashlightTool:FindFirstChild("Handle"):FindFirstChildWhichIsA("PointLight") or flashlightTool:FindFirstChild("Handle"):FindFirstChildWhichIsA("SpotLight")

local lightOn = false
local connection -- Variable to store the RenderStepped connection

-- Function to clamp the angle within the specified range
local function clamp(value, min, max)
	return math.max(min, math.min(value, max))
end

-- Function to update the arm position based on cursor direction
local function updateArm()
	if lightOn and flashlightTool.Parent == character then
		local mousePosition = mouse.Hit.Position
		local direction = (mousePosition - character.Head.Position).unit

		-- Calculate the yaw needed to make the arm follow the cursor, clamped between -65 and 65 degrees
		local yaw = math.atan2(direction.X, direction.Z)
		yaw = clamp(yaw, math.rad(-65), math.rad(65))

		-- Create the target CFrame based on calculated yaw, only affecting yaw (left/right rotation)
		local newC0 = originalC0 * CFrame.Angles(0, yaw, 0)
		rightShoulder.C0 = newC0
	else
		rightShoulder.C0 = originalC0
	end
end

-- Function to toggle the light
local function toggleLight()
	lightOn = not lightOn
	light.Enabled = lightOn
end

-- Function to handle flashlight tool equipped
local function onEquipped()
	lightOn = light and light.Enabled
	connection = runService.RenderStepped:Connect(updateArm)
end

-- Function to handle flashlight tool unequipped
local function onUnequipped()
	if connection then
		connection:Disconnect()
		connection = nil
	end
	rightShoulder.C0 = originalC0
end

-- Connect the functions to the flashlight tool's events
flashlightTool.Equipped:Connect(onEquipped)
flashlightTool.Unequipped:Connect(onUnequipped)
flashlightTool.Activated:Connect(toggleLight)

it should be moving smoothly right to left but it snaps to the max angle when my mouse is infront of the character but behind the player it does it perfectly?? the game will be in first person

EDIT:

External Media

it works in some directions so im not quite sure

EDIT 2:
fixed a little of it up it does it in all directions smoothely but still only when the players mouse is behind the player… :confused:

-- LocalScript inside StarterPlayerScripts

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local runService = game:GetService("RunService")

-- Variables for controlling the arm in an R6 rig
local rightArm = character:WaitForChild("Right Arm")
local torso = character:WaitForChild("Torso")
local rightShoulder = torso:WaitForChild("Right Shoulder")

local originalC0 = rightShoulder.C0

-- Reference to the flashlight tool
local flashlightTool = player:WaitForChild("Backpack"):WaitForChild("Flashlight")
local light = flashlightTool:FindFirstChild("Handle"):FindFirstChildWhichIsA("PointLight") or flashlightTool:FindFirstChild("Handle"):FindFirstChildWhichIsA("SpotLight")

local lightOn = false
local connection -- Variable to store the RenderStepped connection

-- Function to clamp the angle within the specified range
local function clamp(value, min, max)
	return math.max(min, math.min(value, max))
end

-- Function to update the arm position based on cursor direction
local function updateArm()
	if lightOn and flashlightTool.Parent == character then
		local mousePosition = mouse.Hit.Position
		local headPosition = character.Head.Position
		local torsoCFrame = torso.CFrame

		-- Calculate the direction from the character's head to the mouse position
		local direction = (mousePosition - headPosition).unit

		-- Convert the direction to the local space of the torso
		local relativeDirection = torsoCFrame:VectorToObjectSpace(direction)

		-- Calculate the yaw needed to make the arm follow the cursor, clamped between -65 and 65 degrees
		local yaw = math.atan2(relativeDirection.X, relativeDirection.Z)
		yaw = clamp(yaw, math.rad(-65), math.rad(65))

		-- Create the target CFrame based on calculated yaw, only affecting yaw (left/right rotation)
		local newC0 = originalC0 * CFrame.Angles(0, yaw, 0)
		rightShoulder.C0 = newC0
	else
		rightShoulder.C0 = originalC0
	end
end

-- Function to toggle the light
local function toggleLight()
	lightOn = not lightOn
	light.Enabled = lightOn
end

-- Function to handle flashlight tool equipped
local function onEquipped()
	lightOn = light and light.Enabled
	connection = runService.RenderStepped:Connect(updateArm)
end

-- Function to handle flashlight tool unequipped
local function onUnequipped()
	if connection then
		connection:Disconnect()
		connection = nil
	end
	rightShoulder.C0 = originalC0
end

-- Connect the functions to the flashlight tool's events
flashlightTool.Equipped:Connect(onEquipped)
flashlightTool.Unequipped:Connect(onUnequipped)
flashlightTool.Activated:Connect(toggleLight)

try testing it in first person, also it seems like its inverted? not sure but test it in first person because third person results are kind of useless if the game wont be in 3rd person or at least have that option

1 Like
External Media

heres a first person pov

this code works alot better but its still inverted when i move the cursor behind the player its very annoying i dont under stand

-- LocalScript inside StarterPlayerScripts

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local runService = game:GetService("RunService")

-- Variables for controlling the arm in an R6 rig
local rightArm = character:WaitForChild("Right Arm")
local torso = character:WaitForChild("Torso")
local rightShoulder = torso:WaitForChild("Right Shoulder")

local originalC0 = rightShoulder.C0

-- Reference to the flashlight tool
local flashlightTool = player:WaitForChild("Backpack"):WaitForChild("Flashlight")
local light = flashlightTool:FindFirstChild("Handle"):FindFirstChildWhichIsA("PointLight") or flashlightTool:FindFirstChild("Handle"):FindFirstChildWhichIsA("SpotLight")

local lightOn = false
local connection -- Variable to store the RenderStepped connection

-- Function to clamp the angle within the specified range
local function clamp(value, min, max)
	return math.max(min, math.min(value, max))
end

-- Function to update the arm position based on cursor direction
local function updateArm()
	if lightOn and flashlightTool.Parent == character then
		local mousePosition = mouse.Hit.Position
		local headPosition = character.Head.Position
		local torsoCFrame = torso.CFrame

		-- Calculate the direction from the character's head to the mouse position
		local direction = (mousePosition - headPosition).unit

		-- Convert the direction to the local space of the torso
		local relativeDirection = torsoCFrame:VectorToObjectSpace(direction)

		-- Check if the cursor is in front of the character
		if relativeDirection.Z > 0 then
			-- Calculate the yaw needed to make the arm follow the cursor, clamped between -65 and 65 degrees
			local yaw = math.atan2(relativeDirection.X, relativeDirection.Z)
			yaw = clamp(yaw, math.rad(-65), math.rad(65))

			-- Create the target CFrame based on calculated yaw, only affecting yaw (left/right rotation)
			local newC0 = originalC0 * CFrame.Angles(0, yaw, 0)
			rightShoulder.C0 = newC0
		else
			rightShoulder.C0 = originalC0
		end
	else
		rightShoulder.C0 = originalC0
	end
end

-- Function to toggle the light
local function toggleLight()
	lightOn = not lightOn
	light.Enabled = lightOn
end

-- Function to handle flashlight tool equipped
local function onEquipped()
	lightOn = light and light.Enabled
	connection = runService.RenderStepped:Connect(updateArm)
end

-- Function to handle flashlight tool unequipped
local function onUnequipped()
	if connection then
		connection:Disconnect()
		connection = nil
	end
	rightShoulder.C0 = originalC0
end

-- Connect the functions to the flashlight tool's events
flashlightTool.Equipped:Connect(onEquipped)
flashlightTool.Unequipped:Connect(onUnequipped)
flashlightTool.Activated:Connect(toggleLight)