So basically this is my current math for snapping my objects to my first ever placement system grid and it works great clamping everything to the base plot, however I’m not sure how I could go about adding land expansions using this method unless I just expand the plot itself?
I know some variables aren’t defined here and it’s not pretty but that wasn’t really the goal with this post, it was more so to ask how I should approach this or if I should just do it differently entirely.
function PlacementAPI:Snap(Position)
-- Check if the base plot part exists
if not BasePlotPart then
return Position
end
local ObjectSize = Vector3.new(
math.abs(CurrentObjName.PrimaryPart.Size.X),
math.abs(ObjectHeight),
math.abs(CurrentObjName.PrimaryPart.Size.Z)
)
-- Calculate the bounding box of the rotated object
local rotatedCFrame = CFrame.new(Position) * CFrame.Angles(0, math.rad(Rotation), 0)
local objectBoundingBox = CurrentObjName:GetExtentsSize(rotatedCFrame)
-- Round the position to the nearest grid cell within the bounding box
local snappedPosition = Vector3.new(
math.floor((rotatedCFrame.X - BasePlotTopLeft.X) / PlacementAPI.ClientChecks.GridCellSize + 0.5) * PlacementAPI.ClientChecks.GridCellSize + BasePlotTopLeft.X,
BasePlotHeight,
math.floor((rotatedCFrame.Z - BasePlotTopLeft.Z) / PlacementAPI.ClientChecks.GridCellSize + 0.5) * PlacementAPI.ClientChecks.GridCellSize + BasePlotTopLeft.Z
)
-- Clamp the snapped position to the boundaries of the bounding box
if Rotation == 0 then
snappedPosition = Vector3.new(
math.clamp(snappedPosition.X, BasePlotTopLeft.X + objectBoundingBox.X/2, BasePlotBottomRight.X - objectBoundingBox.X/2),
0,
math.clamp(snappedPosition.Z, BasePlotTopLeft.Z + objectBoundingBox.Z/2, BasePlotBottomRight.Z - objectBoundingBox.Z/2)
)
elseif Rotation == 90 then
snappedPosition = Vector3.new(
math.clamp(snappedPosition.X, BasePlotTopLeft.X + objectBoundingBox.Z/2, BasePlotBottomRight.X - objectBoundingBox.Z/2),
0,
math.clamp(snappedPosition.Z, BasePlotTopLeft.Z + objectBoundingBox.X/2, BasePlotBottomRight.Z - objectBoundingBox.X/2)
)
end
-- Convert snappedPosition to a CFrame before undoing the rotation
local snappedCFrame = CFrame.new(snappedPosition)
-- Undo object rotation from the snapped position
local unrotatedCFrame = snappedCFrame * CFrame.Angles(0, math.rad(Rotation), 0)
-- Convert the position of the object's bottom surface back to its center position
finalPosition = Vector3.new(unrotatedCFrame.X, BasePlotHeight + ObjectHeight/2, unrotatedCFrame.Z)
return finalPosition
end