You’d need to get the dot product between the player’s LookVector (so we get a nice 90 degree up-straight rotation when idle) and the player-to-rope’s end direction and then just apply a rotation on the player’s RootJoint (since the RootJoint’s C0 and stuff is only purely visual, and doesn’t affect the player’s collisions and the sort)
local RootJoint = HumanoidRootPart:WaitForChild("RootJoint")
RunService:BindToRenderStep("MakePlayerRotateBasedOnRopeAngle", 301, function()
local Direction = (a1.WorldPosition - a0.WorldPosition).Unit
-- The dot product isn't really the "angle", but it doesn't really matter as using
-- the angle from the dot product just forces us to add some offset values for the same thing anyway
local Angle = Direction:Dot(HumanoidRootPart.CFrame.LookVector) --
-- This weird combination is the RootJoint's C0 default CFrame
local A = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, -0) * CFrame.Angles(Angle, 0, 0)
RootJoint.C0 = A
end)
EDIT: Oops, forgot that you might also want the roll angle.
It’s the same thing but you have to use the RightVector
local Pitch = Direction:Dot(HumanoidRootPart.CFrame.LookVector)
local Roll = Direction:Dot(HumanoidRootPart.CFrame.RightVector)
local A = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, -0) * CFrame.Angles(Pitch, -Roll, 0)