Rust like Building System help

Im trying to make a rust like building system mixed with fallout like how you can free place.
Here’s a clip of the System


Here is the Script, it’s a local to make sure the preview snaps to the attachments shown in the video.

--Property of @notrebel_1776
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local replicatedStorage = game:GetService("ReplicatedStorage")
local userInput = game:GetService("UserInputService")
local runService = game:GetService("RunService")
local placementFolder = workspace


local currentPrefab = replicatedStorage.GameMechanics.Prefab.Wall
local snappingEnabled = true  
local buildingEnabled = false 
local placementObject

local function createPlacementGhost()
	placementObject = currentPrefab:Clone()
	placementObject.Parent = workspace
	placementObject.PrimaryPart = placementObject:FindFirstChild("PlacementPart")

	for _, part in ipairs(placementObject:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Transparency = 0.5
			part.CanCollide = false
		end
	end
end

local function getPlacementPart(model)
	if model and model:IsA("Model") then
		return model:FindFirstChild("PlacementPart")
	end
	return nil
end

local function findNearestAttachment(position, parentModel)
	local closestAttachment = nil
	local closestDistance = math.huge

	local placementPart = getPlacementPart(parentModel)
	if not placementPart then return nil end

	for _, attachment in pairs(placementPart:GetChildren()) do
		if attachment:IsA("Attachment") then
			local distance = (position - attachment.WorldPosition).Magnitude
			closestDistance = math.clamp(distance, 0, math.huge)
			if distance < closestDistance then
				closestDistance = distance
				closestAttachment = attachment
			end
		end
	end

	return closestAttachment
end

local function snapToNearestAttachment(targetPosition)
	local nearestAttachment = nil
	local closestDistance = math.huge

	for _, placedPrefab in pairs(placementFolder:GetChildren()) do
		local candidateAttachment = findNearestAttachment(targetPosition, placedPrefab)
		if candidateAttachment then
			local distance = (targetPosition - candidateAttachment.WorldPosition).Magnitude
			closestDistance = math.clamp(distance, 0, math.huge)
			if distance < closestDistance then
				closestDistance = distance
				nearestAttachment = candidateAttachment
			end
		end
	end

	local ghostAttachment = findNearestAttachment(targetPosition, placementObject)

	if nearestAttachment and ghostAttachment then
		local offset = ghostAttachment.CFrame:Inverse() * placementObject.PrimaryPart.CFrame
		local newCFrame = nearestAttachment.WorldCFrame * offset
		placementObject:SetPrimaryPartCFrame(newCFrame)
		print("Snapped to attachment: " .. nearestAttachment.Name)
		return true
	end
	return false
end

local function updatePlacement()
	if not placementObject or not buildingEnabled then return end

	local mouseRay = workspace.CurrentCamera:ScreenPointToRay(mouse.X, mouse.Y)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {placementObject} -- Ignore ghost object
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	local rayResult = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 100, raycastParams)

	if rayResult then
		local HitPart = rayResult.Instance
		if HitPart:IsA("Model") then
			for i, child in pairs(HitPart:GetChildren()) do
				if child.Name == "PlacementPart" then
					print("Found PlacementPart inside:", HitPart.Name)
				end
			end
		end
	end



	local targetPosition = rayResult and rayResult.Position or mouse.Hit.Position
	local detectedPrefab = rayResult and rayResult.Instance and rayResult.Instance.Parent

	if detectedPrefab and getPlacementPart(detectedPrefab) then
		local nearestAttachment = findNearestAttachment(targetPosition, detectedPrefab)
		if nearestAttachment then
			snapToNearestAttachment(nearestAttachment.WorldPosition)
			return
		end
	end

	if snappingEnabled and snapToNearestAttachment(targetPosition) then
		return
	end

	placementObject:SetPrimaryPartCFrame(CFrame.new(targetPosition))
end

local function placeObject()
	if placementObject and buildingEnabled then
		local newObj = currentPrefab:Clone()
		newObj:SetPrimaryPartCFrame(placementObject.PrimaryPart.CFrame)
		newObj.Parent = placementFolder

		placementObject:Destroy()
		placementObject = nil
		createPlacementGhost()
	end
end



local tweenService = game:GetService("TweenService")
local playerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")

local notificationTemplate = replicatedStorage.GameMechanics.GUI:WaitForChild("Notification")
local maxNotifications = 5 

local activeNotifications = {}

local function showNotification(text)
	local Cloned = notificationTemplate:Clone()
	Cloned.Parent = playerGui
	Cloned.Enabled = true
	Cloned.Frame.Frame.TextLabel.Text = text

	local baseYPosition = 0.3
	local spacing = 0.07 
	local limit = maxNotifications * spacing 

	if #activeNotifications >= maxNotifications then
		local oldest = table.remove(activeNotifications, 1)
		oldest:Destroy()
	end

	local offset = #activeNotifications * spacing
	if offset > limit then offset = limit end

	Cloned.Frame.Position = UDim2.new(1, 50, baseYPosition + offset, 0)

	local tweenIn = tweenService:Create(Cloned.Frame, TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
		Position = UDim2.new(0.8, 0, baseYPosition + offset, 0)
	})

	tweenIn:Play()
	table.insert(activeNotifications, Cloned)

	task.delay(3, function()
		local tweenOut = tweenService:Create(Cloned.Frame, TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
			Position = UDim2.new(1, 50, baseYPosition + offset, 0)
		})
		tweenOut:Play()
		tweenOut.Completed:Wait()
		Cloned:Destroy()
	end)
end

local function toggleSnapping()
	snappingEnabled = not snappingEnabled
	showNotification("Snapping " .. (snappingEnabled and "Enabled" or "Disabled"))
end

local istoggle = false
local toggled = false

local function toggleBuildMode()
	buildingEnabled = not buildingEnabled

	if buildingEnabled then
		if placementObject then
			placementObject:Destroy()
		end
		createPlacementGhost()
		istoggle = true
	else
		if placementObject then
			placementObject:Destroy()
			placementObject = nil
		end
		istoggle = false	
	end
end

userInput.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.B then
		if toggled == false then
			toggled = true
			toggleBuildMode()
		else
			toggled = false
			toggleBuildMode()
		end
	end
end)

userInput.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.T then
		if buildingEnabled then
			toggleSnapping()
		else
			showNotification("Can't toggle snapping outside of build mode.")
		end
	end
end)

runService.RenderStepped:Connect(updatePlacement)
mouse.Button1Down:Connect(placeObject)

Also the place file.
BuildingSystem.rbxl (68.4 KB)