I cannot figure out how to limit the CFrame angles for my turret.

I have spent hours reading and looking on the forum. I found bunch of post and tried to make use of them but cannot figure it out.

Here is the Client Script (sends Mouse Position):

local MouseLock = script.Parent:WaitForChild("RF_MouseLock")
local Mouse = game.Players.LocalPlayer:GetMouse()
function MouseLock.OnClientInvoke()
return Mouse.Hit.Position
end

Here is the Server Script (that rotates the turret):

local seat = script.Parent:WaitForChild("Seat")
local housing = script.Parent:WaitForChild("Housing")
local occupied = false
seat:GetPropertyChangedSignal("Occupant"):Connect(function()
if seat.Occupant then
occupied = true
while task.wait() do
if occupied then
-- find player and mouse postion
local character = seat.Occupant.Parent
local player = game.Players:WaitForChild(character.Name)
local MouseLock = character:WaitForChild("RF_MouseLock")
local MouseHitPosition = MouseLock:InvokeClient(player)
-- rotate toward mouse
if (MouseHitPosition-housing.Position).magnitude>3 then
housing.CFrame = CFrame.new(housing.Position, MouseHitPosition)
end
end
end
else
occupied = false
return
end
end)

The workspace contains only the two parts:

a seat

a part named “housing” that is welded to the seat.

First I will assume you know how parts have an orientation property and that you can modify each angle in order to limit them in each axis using a function such as math.clamp.

local orientation = part.Orientation
local newYOrientation = math.clamp(orientation.Y, -45, 45) --Clamp y rotation between -45 to 45
local newOrientation = Vector3.new(orientation.X, newYOrientation, orientation.Z)

You can apply the same technique given a CFrame using the to orientation function. Orientation is used as it’s easier to visualize and the angles are applied

local x, y, z = part.CFrame:ToOrientation()
local newYAngle = math.clamp(y, math.rad(-45), math,rad(45)) --The function angles are given in radians so math.rad is needed to convert degrees into radians

In your case the CFrame you achieved is through CFrame.lookAt() or CFrame.new(pos1, pos2) so all you need to do is to limit it.

local rotationCFrame = CFrame.new(housing.Position, MouseHitPosition)
local x, y, z = rotationCFrame:ToOrientation()
--limit angles
local newYAngle = math.clamp(y, math.rad(-45), math,rad(45)) --The function angles are given in radians so math.rad is needed to convert degrees into radians
local newRotationCFrame = CFrame.fromOrientation(x, newYAngle, z)

Thank you. I managed to get it to work with your help!

All but one thing, it moves the Housing to 0,0,0 when I use `housing.CFrame = newRotationCFrame.

I have been trying to figure out how to fix it, but cannot. I looked up a bunch of posts about rotating CFrames and keeping the original position but cannot figure it out.

I tried different things like housing.CFrame = housing.CFrame * newRotationCFrame but that just makes it spin like a top.

I don’t know why CFrames are so difficult for me to understand.

Current Code:

seat:GetPropertyChangedSignal("Occupant"):Connect(function()
if seat.Occupant then
occupied = true
while task.wait() do
if occupied then
-- find player and mouse postion
local character = seat.Occupant.Parent
local player = game.Players:WaitForChild(character.Name)
local MouseLock = character:WaitForChild("RF_MouseLock")
local MouseHitPosition = MouseLock:InvokeClient(player)
-- rotate toward mouse
if (MouseHitPosition-housing.Position).magnitude > 3 then
local rotationCFrame = CFrame.new(housing.Position, MouseHitPosition)
local x, y, z = rotationCFrame:ToOrientation()
local newYAngle = math.clamp(y, math.rad(-90), math.rad(90)) --limit left/right
local newXAngle = math.clamp(x, math.rad(-45), math.rad(45)) --limit up/down
local newRotationCFrame = CFrame.fromOrientation(newXAngle, newYAngle, z)
housing.CFrame = housing.CFrame * newRotationCFrame -- this line is not working
end
end
end
else
occupied = false
return
end
end)