How to create a grid placement system that only works within the player's own plot?

Hi guys! I’m still currently making a grid placement system and it has been going well. I followed a template made by another user and customized parts of it. I also have a plot placement system inside my game and I’m not quite sure how to connect that to my grid placement system. Basically what I want to do is make it so that the player is unable to place items outside of their assigned plot. I’ve tried for the past 2 hours and nothing worked :frowning:

1 Like

I guess it depends on how your current grid placement system is. Can you please provide a sample of the code? Depending on how it is implemented, the solution will vary slightly

Are the plots rotated at all? Are they squares? Are the dimensions constant?

theyre not rotated, size is 26, 1, 26 yes square

In that case, you should be able to modify the SnapToGrid function like this:

local plot = ...
local function SnapToGrid(position, hitPart)
	position = Vector3.new(
		math.clamp(position.X, plot.Position.X - Plot.Size.X, plot.Position + plot.Size.X),
		position.Y,
		math.clamp(position.Z, plot.Position.Z - Plot.Size.Z, plot.Position + plot.Size.Z),
	)

	return Vector3.new(
		math.floor(position.X / gridSize + 0.5) * gridSize,
		hitPart.Position.Y + (ObjectClone.Size.Y / 2) + (hitPart.Size.Y / 2), -- Prevents underground placement
		math.floor(position.Z / gridSize + 0.5) * gridSize
	)
end

I also have a spawns folder set up like this:

do i add my code inside the 3 dots? and would this setup affect my code in any way?

You should set the plot variable at some point, probably just using a loop to go through all the plots and checking if the local player is the one who owns the plot

Replace the 3 dots with the player’s plot .

on the server, create a tag for the plot with the player’s name (or user ID if you want to be truly safe), in your RenderStepped just check if the Hit includes the tag of the player’s name.

I’m also making a plot system rn, and the code I use for keeping a part inside the plot is like this:

It might not be good though, but it works for me

function module.bounds(c: CFrame, primaryRotation: Vector3, Size: Vector3, plot:BasePart): CFrame
	-- Calculate plot bounds in local space
	local plotCFrame:CFrame = plot.CFrame
	local plotSize = plot.Size

	-- Transform the input point to the plot's local space
	local relativePos = plotCFrame:PointToObjectSpace(c.Position)

	-- Account for primary part rotation
	local primaryRotCFrame = CFrame.Angles(
		math.rad(primaryRotation.X),
		math.rad(primaryRotation.Y),
		math.rad(primaryRotation.Z)
	)

	-- Calculate the rotated size
	local primarySize = Size
	local rotatedSize = Vector3.new(
		math.abs(primarySize.X * primaryRotCFrame.RightVector.X) +
			math.abs(primarySize.Y * primaryRotCFrame.UpVector.X) +
			math.abs(primarySize.Z * primaryRotCFrame.LookVector.X),

		math.abs(primarySize.X * primaryRotCFrame.RightVector.Y) +
			math.abs(primarySize.Y * primaryRotCFrame.UpVector.Y) +
			math.abs(primarySize.Z * primaryRotCFrame.LookVector.Y),

		math.abs(primarySize.X * primaryRotCFrame.RightVector.Z) +
			math.abs(primarySize.Y * primaryRotCFrame.UpVector.Z) +
			math.abs(primarySize.Z * primaryRotCFrame.LookVector.Z)
	)
	-- Update bounds based on rotated size
	local lowerX = -plotSize.X / 2 + rotatedSize.X / 2
	local upperX = plotSize.X / 2 - rotatedSize.X / 2
	local lowerY = plotSize.Y/2 + rotatedSize.Y/2
	local upperY = Placement:GetAttribute("MaxHeight" ) - rotatedSize.Y / 2
	local lowerZ = -plotSize.Z / 2 + rotatedSize.Z / 2
	local upperZ = plotSize.Z / 2 - rotatedSize.Z / 2

	-- Clamp the position in local space
	local clampedX = math.clamp(relativePos.X, math.min(lowerX, upperX), math.max(lowerX, upperX))
	local clampedY = math.clamp(relativePos.Y, math.min(lowerY, upperY), math.max(lowerY, upperY))
	local clampedZ = math.clamp(relativePos.Z, math.min(lowerZ, upperZ), math.max(lowerZ, upperZ))

	-- Transform the clamped position back to world space
	local clampedWorldPos = plotCFrame:PointToWorldSpace(Vector3.new(clampedX, clampedY, clampedZ))
	local clampedVector = CFrame.new(clampedWorldPos.X, clampedWorldPos.Y, clampedWorldPos.Z)
	
	--if rotatedSize.X >= MaxScale.X then
	--	primarySize = Vector3.new(MaxScale.X, primarySize.Y, primarySize.Z)
	--end
	--if rotatedSize.Y >= MaxScale.Y then
	--	primarySize = Vector3.new(primarySize.X, MaxScale.Y, primarySize.Z)
	--end
	--if rotatedSize.Z >= MaxScale.X then
	--	primarySize = Vector3.new(primarySize.X, primarySize.Y, MaxScale.Z)
	--end
	
	if primarySize.X >= plot.Size.X then
		primarySize = Vector3.new(plot.Size.X, primarySize.Y, primarySize.Z)
		clampedVector = CFrame.new(plot.Position.X, clampedVector.Y, clampedVector.Z)
	end
	if primarySize.Y >= Placement:GetAttribute("MaxHeight" ) then
		primarySize = Vector3.new(primarySize.X, Placement:GetAttribute("MaxHeight"), primarySize.Z)
	end
	if primarySize.Z >= plot.Size.Z then
		primarySize = Vector3.new(primarySize.X, primarySize.Y, plot.Size.Z)
		clampedVector = CFrame.new(clampedVector.X, clampedVector.Y, plot.Position.Z)
	end
	
	-- Combine the clamped position with the rotation from the original CFrame
	print(clampedVector * c - c.Position)
	return clampedVector * c - c.Position, primarySize
end

what is a tag? sorry I’m new to this and also what do you mean with the player’s name?

is this the whole script? what is maxheight?

oh max height is just a vector, you can set it to what ever you want, and also this the whole script

ok so i’ve edited this script a bit but it works!!!

         local plot = findPlot(player)  -- Now using the player's plot
				local function SnapToGrid(position, hitPart)
					-- Get the half-width and half-length of the object
					local halfWidth = ObjectClone.Size.X / 2
					local halfLength = ObjectClone.Size.Z / 2

					-- Calculate plot boundaries
					local plotHalfX = plot.Size.X / 2
					local plotHalfZ = plot.Size.Z / 2

					-- Clamp the object's position so it doesn't exceed the plot's boundaries
					local clampedX = math.clamp(position.X, plot.Position.X - plotHalfX + halfWidth, plot.Position.X + plotHalfX - halfWidth)
					local clampedZ = math.clamp(position.Z, plot.Position.Z - plotHalfZ + halfLength, plot.Position.Z + plotHalfZ - halfLength)

					-- Set the new position with the clamped values
					position = Vector3.new(clampedX, position.Y, clampedZ)

					-- Return the snapped position, also adjusting the Y to prevent underground placement
					return Vector3.new(
						math.floor(position.X / gridSize + 0.5) * gridSize,
						hitPart.Position.Y + (ObjectClone.Size.Y / 2) + (hitPart.Size.Y / 2), -- Prevents underground placement
						math.floor(position.Z / gridSize + 0.5) * gridSize
					)
				end

so the only problem is that the length and width of the object has to be divisible by 2 or otherwise it won’t perfectly snap to the grid lol

the original script you gave didn’t work and i could only rotate/move the object once according to where my character face but i fixed it!

also some other problem: the object tends to snap to the baseplate if i try to move it out any further. will fix that later

thank you sir

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.