As mentioned above, a CFrame pointing from position A to position B can be found with CFrame.lookAt(origin, target, upVector)
But this does not give you a useful result, either! This would be good if the turret were free-standing in the air and not mounted on a spaceship, or if the turret’s CFrame were `CFrame.new(). This is because it does not account for the orientation of the spaceship it’s mounted on.
The way to fix this is to work in the coordinate space of the turret, to make the turret the center of the world, not the origin point (0,0,0)
Relative to the turret, the player is located at turret.CFrame:PointToObjectSpace(targetVector3)
This will return a Vector3 that’s in the turret’s space, as if the turret were the center of the world.
If the player is exactly 20 studs in front of the turret, then this will be something like (0, 0, 20) regardless of where in the world the turret or player are.
You may then use CFrame.lookAt(Vector3.new(), target.Position) to get a CFrame that’s ready to be put into C0 or C1 (not sure which).
Edit: The code above works just as well as the code below does, because (0, 1, 0) is already “up” in turret space
(None of this has been tested, please tell me when something isn’t as I expected when writing this)
You might notice that the turret faces the right way, but it’s twisted in some random direction.
This is because CFrame.lookAt is missing some information it would like to have when constructing the orientation; namely, which way is up.
To fix this, you will need the direction that’s considered “up” for the turret’s base. If the turret is mounted flat on the ground, then (0, 1, 0) will do and is already the default. But for a spaceship that can turn and tumble, you will probably need the upVector of the spaceship’s body. Or you may add an Attachment that faces some direction that’s considered up, and use its lookVector or upVector.
When you have the up vector, you use CFrame.lookAt(origin, target, upVector) to get the CFrame that points from the turret to the player.
But wait, that’s what you had earlier! It points in some weird, but correlated direction!
That’s because it’s in world space. To get the real CFrame, you put it into the space of the turret:
turret.CFrame:ToObjectSpace(CFrame.lookAt(origin, target, upVector))
(or should turret.CFrame and the other CFrame be switched?)