So I am working on a build-to-survive type of game this system utilizes a modified version of PlacementService by zblox I am having an issue where the placement is trying to place inside of the already placed down objects instead of on the face of the currently hovered object like it is supposed to do, video attached below.
The full code can be found here:
PlacementService.rbxm (25.1 KB)
2 main functions run the placement calculations
SnapCFrame
local function SnapCFrame(c : CFrame) : CFrame
local newX = round((c.X / GRID_UNIT)) * GRID_UNIT
local newZ = round((c.Z / GRID_UNIT)) * GRID_UNIT
local newCFrame = cframe(newX, 0, newZ)
return newCFrame
end
CalcItemLocation
local function CalcItemLocation(last, final)
local x: number, z: number
local cx: number, cz: number
local sizeX: number, sizeZ: number, sizeY: number
local finalC: CFrame
if currentRot then
sizeX = primary.Size.X * 0.5
sizeZ = primary.Size.Z * 0.5
else
sizeX = primary.Size.Z * 0.5
sizeZ = primary.Size.X * 0.5
end
sizeY = primary.Size.Y * 0.5
if moveByGrid then
cx = sizeX - floor((sizeX / GRID_UNIT) + 0.5) * GRID_UNIT
cz = sizeZ - floor((sizeZ / GRID_UNIT) + 0.5) * GRID_UNIT
else
cx = sizeX
cz = sizeZ
end
local cam: Camera = workspace.CurrentCamera
local camPos: Vector3 = cam.CFrame.Position
local unit: Ray
local ray: {[string]: any}
local nilRay: Vector3
if isMobile then
ray = workspace:Raycast(camPos, cam.CFrame.LookVector * maxRange, raycastParams)
nilRay = camPos + cam.CFrame.LookVector * (maxRange + plot.Size.X * 0.5 + plot.Size.Z * 0.5)
else
unit = cam:ScreenPointToRay(mouse.X, mouse.Y, 1)
ray = workspace:Raycast(unit.Origin, unit.Direction * maxRange, raycastParams)
nilRay = unit.Origin + unit.Direction * (maxRange + plot.Size.X * 0.5 + plot.Size.Z * 0.5)
end
if ray then
x = ray.Position.X - cx
z = ray.Position.Z - cz
if stackable then
target = ray.Instance
else
target = plot
end
else
x = nilRay.X - cx
z = nilRay.Z - cz
target = plot
end
y = CalcYPos(plot.Position.Y, plot.Size.Y, primary.Size.Y)
local pltCFrame = plot.CFrame
-- Changes y depending on mouse target
if stackable and target and (target:IsDescendantOf(placedObjects) or target == plot) then
if ray and ray.Normal then
if ray.Normal:Dot(Vector3.FromNormalId(Enum.NormalId.Top)) > 0 then
y = CalcYPos(target.Position.Y, target.Size.Y, primary.Size.Y)
elseif ray.Normal:Dot(Vector3.FromNormalId(Enum.NormalId.Bottom)) > 0 then
y = ray.Instance.Position.Y - (sizeY*2)
else
y = ray.Instance.Position.Y
end
if ray.Normal:Dot(Vector3.FromNormalId(Enum.NormalId.Right)) > 0 then
x += sizeX
elseif ray.Normal:Dot(Vector3.FromNormalId(Enum.NormalId.Left)) > 0 then
if x > 0 then
x -= sizeX
end
elseif ray.Normal:Dot(Vector3.FromNormalId(Enum.NormalId.Front)) > 0 then
if z > 0 then
z -= sizeZ
end
elseif ray.Normal:Dot(Vector3.FromNormalId(Enum.NormalId.Back)) > 0 then
z += sizeZ
end
end
end
-- Clamps y to a max height above the plot position
local maxHeight = initialMaxHeight
y = clamp(y, initialY, maxHeight + initialY)
if moveByGrid then
-- Calculates the correct position
local rel = pltCFrame:Inverse() * CFrame.new(x, 0, z)
local snappedRel = SnapCFrame(rel) * CFrame.new(cx, 0, cz)
if not removePlotDependencies then
snappedRel = bounds(snappedRel, sizeX, sizeZ, pltCFrame)
end
finalC = pltCFrame * snappedRel
else
finalC = pltCFrame:Inverse() * CFrame.new(x, 0, z) * CFrame.new(cx, 0, cz)
if not removePlotDependencies then
finalC = bounds(finalC, sizeX, sizeZ, pltCFrame)
end
finalC = pltCFrame * finalC
end
local maxAllowedSize = plot.Size.X / 2
if final or not interpolation then
return finalC * CFrame.new(0, y - plot.Position.Y, 0) * anglesXYZ(0, rotation * pi / 180, 0)
end
return finalC * CFrame.new(0, y - plot.Position.Y, 0) * anglesXYZ(0, rotation * pi / 180, 0) * CalcAngle(last, finalC)
end