Hello! I am currently working on adding a feature to allow “stackable” objects on all axis for my placement module. What I mean by that is similar to Minecraft’s placement system where you can place objects in the air horizontally without the object being within/too far from the other object. This allows for bridging, roof building and just easier placement overall.

What I want:

What I get:

Currently my system only allows for vertical stacking (y) and that is calculated in the following function:

```
-- tp = to position, ts = to size, o = model size
local function calculateYPos(tp, ts, o)
return (tp + ts*0.5) + o*0.5
end
```

I tried using the same function to calculate the offset just on another axis but it didn’t end up working as I want.

```
-- Calculates the stacked positions and returns them
local function calcStack(r)
local px, py, pz = 0, 0, 0
local t = mouse.Target
if mouse.TargetSurface == Enum.NormalId.Top then -- vertical
px = 0
py = calculateYPos(t.Position.Y, t.Size.Y, primary.Size.Y)
pz = 0
elseif mouse.TargetSurface == Enum.NormalId.Front then -- non vertical
py = t.Position.Y + (t.Size.Y*0.5 - primary.Size.Y*0.5) -- sets the object on the same y
pz = calculateYPos(t.Position.Z, t.Size.Z, primary.Size.Z) -- should calc the z
end
return px, py, pz
end
```

## If you're interested, my main calculate function looks like this:

```
local function calculateItemLocation() : CFrame
-- Changes y depending on mouse target
if stackable and mouse.Target then
if mouse.Target:IsDescendantOf(placedObjects) or mouse.Target == plot then
sx, y, sz = calcStack()
end
end
if currentRot then
cx = primary.Size.X*0.5
cz = primary.Size.Z*0.5
else
cx = primary.Size.Z*0.5
cz = primary.Size.X*0.5
end
x, z = mouse.Hit.X - cx - sx, mouse.Hit.Z - cz - sz
if moveByGrid then
-- Calculates the correct position
local pltCFrame = cframe(plot.CFrame.X, plot.CFrame.Y, plot.CFrame.Z)
pos = cframe(x, 0, z)
pos = snapCFrame(pltCFrame:Inverse()*pos)
finalC = pos*pltCFrame*cframe(cx, 0, cz)
else
finalC = cframe(x, y, z)*cframe(cx, 0, cz)
end
finalC = bounds(finalC)
-- Clamps y to a max height above the plot position (assuming removePlotDep = false)
y = clamp(y, initialY, maxHeight + initialY)
return finalC*anglesXYZ(0, rot*pi/180, 0)
end
```

The reason why this doesn’t work is that I am using NormalId’s which should work except that models can be rotated. When a model is rotated, it wont work. Is there anyway I can make this work regardless of rotation? I am out of ideas so all help is greatly appreciated!