A good place to start would be using some quick and simple trig to find the angle of the camera relative to the horizontal axis and applying that angle to the angle of the shoulder joint. To do this you could do the following
local runServ = game:GetService("RunService")
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
runServ.RenderStepped:Connect(function()
char:WaitForChild("RightUpperArm").RightShoulder.C1 = CFrame.new(char.RightUpperArm.RightShoulder.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y), 0, 0)
char:WaitForChild("LeftUpperArm").LeftShoulder.C1 = CFrame.new(char.LeftUpperArm.LeftShoulder.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y), 0, 0)
end)
The code is only partially tested and assumes you already have an animation constantly playing for the holding of the weapon.
It may look weird that only your arms are moving when you are looking up and down, so you could do the same thing I did for the left and right shoulder joints to the upper torso. You probably don’t want the upper torso to move as much as the arms do when looking around though, so you can divide the math.asin(…) by some number like 2 or 3 to make it react less to the movement of the camera.
local runServ = game:GetService("RunService")
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
runServ.RenderStepped:Connect(function()
char:WaitForChild("RightUpperArm").RightShoulder.C1 = CFrame.new(char.RightUpperArm.RightShoulder.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y), 0, 0)
char:WaitForChild("LeftUpperArm").LeftShoulder.C1 = CFrame.new(char.LeftUpperArm.LeftShoulder.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y), 0, 0)
char:WaitForChild("UpperTorso").Waist.C1 = CFrame.new(char.UpperTorso.Waist.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y)/2, 0, 0)
end)
If you do decide to do that, you would also need to change how affected the arms are by the rotation of the camera as now you have the CFrame rotation of the arms and the the CFrame rotation of the torso which effects the arms as well. This would mean that if you were to test it now without dividing the previous math.asin(…) values you found for the arms, the arms would rotate farther than they would be able to naturally, and it would look fairly weird.
Because of this, it would be wise to divide those values as well, giving us our final script:
local runServ = game:GetService("RunService")
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
runServ.RenderStepped:Connect(function()
char:WaitForChild("RightUpperArm").RightShoulder.C1 = CFrame.new(char.RightUpperArm.RightShoulder.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y)/2, 0, 0)
char:WaitForChild("LeftUpperArm").LeftShoulder.C1 = CFrame.new(char.LeftUpperArm.LeftShoulder.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y)/2, 0, 0)
char:WaitForChild("UpperTorso").Waist.C1 = CFrame.new(char.UpperTorso.Waist.C1.Position) * CFrame.Angles(math.asin(-workspace.CurrentCamera.CFrame.LookVector.Y)/2, 0, 0)
end)