Hello, i’m making an orbitter script that works by slicing a circle by any amounts (like number of parts), then orbiting it by offsetting the starting point on the circle, it works perfectly

but when it comes to make the orbit fixed to the base’s orientation, it works but the orbit’s center position would be offsetted from the base pos

Here are the screen recordings

As you can see, the orientationing works, but it offsets the base

Here’s my code

```
local module = {}
local RUN = game:GetService("RunService")
export type OrbitConfigs = {
PosCount:number?;
Base:CFrame;
Parts:{BasePart}?;
Radius:number?;
Offset:number?;
Speed:number?;
PositionSine:boolean?;
SineAmp:number?;
SineDuration:number?;
SineAxis:Vector3?;
AutoSineOffset:boolean?;
}
function getSineOffset(t, Amp, Mag, Axis)
return Axis * Amp * math.sin(t * math.pi / Mag)
end
-- offset is from 0 - 1, or degrees, not required
function module:MakeCircle(num:number, base:Vector3?, radius:number?, offset:number?): {Vector3 | CFrame}
offset = offset or 0
local toReturn = {}
local absolutePositions = {}
for i = 1, num do
local angle = (i + offset) * 2 * (math.pi / num)
local absoluteCirclePos = Vector3.new(math.sin(angle), 0, math.cos(angle))
local positionOnCircle = absoluteCirclePos * radius
table.insert(toReturn, (base or Vector3.zero) + positionOnCircle)
table.insert(absolutePositions, absoluteCirclePos)
end
return toReturn, absolutePositions
end
function module:Orbit(configs:OrbitConfigs)
local offset = configs.Offset or 0
local currentOffset = offset
local CFrames = nil
local startTime = os.clock() -- for sining pos
local loop = task.spawn(function()
while true do
local currentTime = os.clock() - startTime
local parts = configs.Parts
local speed = configs.Speed or 1
local count = configs.PosCount or #parts or 1
local radius = configs.Radius or 5
local baseCF = configs.Base or CFrame.new()
if typeof(baseCF) == "Instance" and baseCF:IsA("BasePart") then
baseCF = baseCF.CFrame
end
currentOffset += speed / 60 -- updates the positions, makes it orbit
local positions = module:MakeCircle(count, baseCF, radius, currentOffset) -- returns CFrames because i didn't use baseCF.Position
if parts then -- if a table of parts are provided updates their position, otherwise positions are still accessible
for i, pos in ipairs(positions) do
local part = parts[i]
if configs.PositionSine then
local t = currentTime
local axis = configs.SineAxis or Vector3.new(0, 1, 0)
if configs.AutoSineOffset then
if i % 2 == 0 then
t = -t
end
end
local sinePos = getSineOffset(t, configs.SineAmp or 3, configs.SineDuration or 2, axis)
pos += sinePos -- apply sine
end
local CF = baseCF * pos -- this is where i stumble on my problem
part.CFrame = CF
positions[i] = CF
end
end
CFrames = positions
task.wait()
end
end)
return {
UpdateLoop = loop;
Configs = configs;
GetCFrames = function()
return CFrames
end,
}
end
return module
```

I’ve been trying to get this correct but my knowledge is sort of limited (especially math), any help would be appreciated!

Here’s the testing place file:

orbitTest.rbxl (50.4 KB)