I have a awfully buggy placement system right now, and currently it only supports perfect cubes such as a 4x4x4 side and a 1x1x1 size. It also currently doesn’t support rotation.
game:GetService("RunService").Heartbeat:Connect(function()
local target = mouse.Hit
if value.Value == true and select == false then
if game.Workspace.Client:FindFirstChild("PreviewBlock") then
game.Workspace.Client:FindFirstChild("PreviewBlock"):Destroy()
end
if connection then
connection:Disconnect()
end
if connection3 then
connection3:Disconnect()
end
if connection4 then
connection4:Disconnect()
end
if connection5 then
connection5:Disconnect()
end
if not highlight or highlight.Parent == nil then
highlight = Instance.new("Highlight")
highlight.FillTransparency = 1
highlight.OutlineColor = Color3.new(0.337255, 0.796078, 0.0352941)
else
highlight.OutlineColor = Color3.new(0.337255, 0.796078, 0.0352941)
end
if mouse.Target then
highlight.Parent = mouse.Target
connection5 = mouse.Button1Down:Connect(function()
game.ReplicatedStorage.Files.Events["GKey[C]"]:FireServer("5NeJ01ZUe0cD5MWjFYzbngtJdiQbZ4Lvrwrd59id")
local cmdevent = game.ReplicatedStorage.Files.Events.LocalCommandEvent
local data = {
playerInstanceFinder = game.Players.LocalPlayer.Name,
commandText = script.Parent.Properties.DoNotApply.Command.Value
}
cmdevent:FireServer(data)
end)
end
end
if script.Parent.Properties.DoNotApply.Mode.Value == 0 and target and value.Value == false then
if connection5 then
connection5:Disconnect()
end
if not highlight or highlight.Parent == nil then
highlight = Instance.new("Highlight")
highlight.FillTransparency = 1
highlight.OutlineColor = Color3.new(0,0,0)
end
if connection then
connection:Disconnect()
end
if connection3 then
connection3:Disconnect()
end
for _, obj in pairs(game.Workspace.Client:GetChildren()) do
if obj.Name == "PreviewBlock" then
highlight.Parent = nil
obj:Destroy()
end
end
if script.Parent.Properties.DoNotApply.Painting.Value == true then
if mouse.Target and mouse.Target.Parent == game.Workspace.Blocks then
local target = mouse.Target
highlight.Parent = target
highlight.OutlineColor = Color3.new(1, 0.454902, 0.992157)
connection3 = mouse.Button1Down:Connect(function()
script.Parent.Properties.DoNotApply.Button1Down.Value = true
connection4 = mouse.Button1Up:Connect(function()
script.Parent.Properties.DoNotApply.Button1Down.Value = false
connection3:Disconnect()
connection4:Disconnect()
end)
while true do
if script.Parent.Properties.DoNotApply.Button1Down.Value == true then
print("e")
wait(0.1)
else
break
end
end
end)
end
else
if not mouse.Target or mouse.Target.Parent ~= game.Workspace.Blocks then return end
if GetBlockSideNoPrompt() == nil then return end
local block = game.ReplicatedStorage.Files.BlockTypes:FindFirstChild(script.Parent.Properties.Shape.Value):Clone()
block.Size = script.Parent.Properties.Size.Value
block.Anchored = true
block.CanCollide = false
block.Color = script.Parent.Properties.Color.Value
block.Material = Enum.Material[script.Parent.Properties.Material.Value]
block.Transparency = script.Parent.Properties.Transparency.Value
block.Reflectance = script.Parent.Properties.Reflectance.Value
block.Name = "PreviewBlock"
block.Orientation = script.Parent.Properties.Orientation.Value
highlight.Parent = block
highlight.OutlineColor = Color3.new(0,1,1)
if script.Parent.Properties.Light.Brightness.Value ~= 0 and script.Parent.Properties.Light.Radius.Value ~= 0 then
local light = Instance.new("PointLight")
light.Parent = block
light.Color = script.Parent.Properties.Light.Color.Value
light.Range = script.Parent.Properties.Light.Radius.Value
light.Brightness = script.Parent.Properties.Light.Brightness.Value
end
local gridSize
--[[if block.Size == Vector3.new(4,4,4) or block.Size == Vector3.new(2,2,2) or block.Size == Vector3.new(1,1,1) then
gridSize = block.Size
else
if script.Parent.Sizing.Fade.ShapeText.Text == "PillarX" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "PillarY" then
gridSize = Vector3.new(4, 2, 2)
elseif script.Parent.Sizing.Fade.ShapeText.Text == "PillarZ" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "SlabX" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "SlabY" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "SlabZ" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "ChunkX" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "ChunkY" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "ChunkZ" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "PlateX" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "PlateY" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "PlateZ" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "Full" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "Small" then
elseif script.Parent.Sizing.Fade.ShapeText.Text == "Tiny" then
end
end]]
gridSize = block.Size
local raycastparams = RaycastParams.new()
raycastparams.FilterDescendantsInstances = {game.Players.LocalPlayer.Character, block}
raycastparams.FilterType = Enum.RaycastFilterType.Exclude
local result = workspace:Raycast(
workspace.CurrentCamera.CFrame.Position,
(mouse.Hit.Position - workspace.CurrentCamera.CFrame.Position).Unit * 100000000,
raycastparams
)
local finalpos
if result then
local hitpos = result.Position
local surfacenormal = result.Normal
finalpos = Vector3.new(
math.floor(hitpos.X / gridSize.X) * gridSize.X + gridSize.X / 2,
math.floor(hitpos.Y / gridSize.Y) * gridSize.Y + gridSize.Y / 2,
math.floor(hitpos.Z / gridSize.Z) * gridSize.Z + gridSize.Z / 2
)
if math.abs(surfacenormal.X) == 1 then
if surfacenormal.X == -1 then
finalpos = finalpos - Vector3.new(gridSize.X - (script.Parent.Properties.Size.Value.X / script.Parent.Properties.Size.Value.X - 1), 0, 0)
else
finalpos = finalpos - Vector3.new(gridSize.X - (script.Parent.Properties.Size.Value.X / script.Parent.Properties.Size.Value.X + (script.Parent.Properties.Size.Value.X - 1)), 0, 0)
end
elseif math.abs(surfacenormal.Y) == 1 then
if surfacenormal.Y == -1 then
finalpos = finalpos - Vector3.new(0, gridSize.Y - (script.Parent.Properties.Size.Value.Y / script.Parent.Properties.Size.Value.Y - 1), 0)
end
elseif math.abs(surfacenormal.Z) == 1 then
if surfacenormal.Z == 1 then
finalpos = finalpos - Vector3.new(0, 0, gridSize.Z - (script.Parent.Properties.Size.Value.Z / script.Parent.Properties.Size.Value.Z + script.Parent.Properties.Size.Value.Z - 1))
else
finalpos = finalpos + Vector3.new(0, 0, (surfacenormal.Z * gridSize.Z))
end
end
else
finalpos = Vector3.new(
math.floor(target.Position.X / gridSize.X) * gridSize.X + gridSize.X / 2,
math.floor(target.Position.Y / gridSize.Y) * gridSize.Y + gridSize.Y / 2,
math.floor(target.Position.Z / gridSize.Z) * gridSize.Z + gridSize.Z / 2
)
end
--[[local function snapToGrid(position, blockSize, blockCFrame)
-- Extract the rotation component of the block's CFrame
local rotation = blockCFrame - blockCFrame.Position
-- Transform the world position to the block's local space
local localPosition = rotation:Inverse() * (position - blockCFrame.Position)
-- Calculate from the corner by adding half the size
localPosition = localPosition + (blockSize / 2)
-- Snap the local position to the grid based on block size
local snappedLocalPosition = Vector3.new(
math.floor(localPosition.X / blockSize.X) * blockSize.X,
math.floor(localPosition.Y / blockSize.Y) * blockSize.Y,
math.floor(localPosition.Z / blockSize.Z) * blockSize.Z
)
-- Adjust back from corner to center
snappedLocalPosition = snappedLocalPosition - (blockSize / 2)
-- Transform back to world space
local snappedWorldPosition = rotation * snappedLocalPosition + blockCFrame.Position
return snappedWorldPosition
end
-- Example usage:
local mouse = game.Players.LocalPlayer:GetMouse()
local hitPosition = mouse.Hit.Position
-- Use the block's current CFrame for accurate rotation
local snappedPosition = snapToGrid(hitPosition, block.Size, block.CFrame)
-- Update the block's position and maintain its rotation]]
block.Position = finalpos -- CFrame.new(snappedPosition) * (block.CFrame - block.CFrame.Position)
block.Parent = game.Workspace.Client
connection = mouse.Button1Down:Connect(function()
local tables = {
Transparency = script.Parent.Properties.Transparency.Value,
Reflectance = script.Parent.Properties.Reflectance.Value,
Collision = script.Parent.Properties.Collision.Value,
LightRadius = script.Parent.Properties.Light.Radius.Value,
LightBrightness = script.Parent.Properties.Light.Brightness.Value,
LightColor = script.Parent.Properties.Light.Color.Value,
Shape = script.Parent.Properties.Shape.Value,
Color = script.Parent.Properties.Color.Value,
Material = script.Parent.Properties.Material.Value,
Size = script.Parent.Properties.Size.Value,
Position = block.CFrame
}
local event = game.ReplicatedStorage.Files.Events.NonNative.Place
event:FireServer(tables)
local clonedBlock = block:Clone()
clonedBlock.Parent = game.Workspace.Client
clonedBlock.Size = Vector3.new(0, 0, 0)
clonedBlock.Name = "Anim"
clonedBlock.Highlight:Destroy()
local tweenInfo = TweenInfo.new(0.25, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
local tweenProperties = {Size = block.Size}
local tween = TweenService:Create(clonedBlock, tweenInfo, tweenProperties)
tween:Play()
tween.Completed:Connect(function()
clonedBlock:Destroy()
end)
end)
end
elseif script.Parent.Properties.DoNotApply.Mode.Value == 1 and value.Value == false and select == false then
if mouse.Target and mouse.Target.Parent == game.Workspace.Blocks then
local blockpos = mouse.Hit.Position
if not highlight or highlight.Parent == nil then
highlight = Instance.new("Highlight")
highlight.FillTransparency = 1
highlight.OutlineColor = Color3.new(0,0,0)
end
highlight.Parent = mouse.Target
highlight.OutlineColor = Color3.new(1, 0, 0)
if connection then
connection:Disconnect()
end
if connection2 then
connection2:Disconnect()
end
connection2 = mouse.Button1Down:Connect(function()
local target = mouse.Target
if target and target.Parent == game.Workspace.Blocks and script.Parent.Properties.DoNotApply.Mode.Value == 1 and value.Value == false then
local event = game.ReplicatedStorage.Files.Events.NonNative.Delete
event:FireServer(target)
highlight.Parent = nil
local clonedBlock = target:Clone()
clonedBlock.Parent = game.Workspace.Client
clonedBlock.Size = target.Size
clonedBlock.Name = "Anim"
local tweenInfo = TweenInfo.new(0.25, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
local tweenProperties = {Size = Vector3.new(0,0,0)}
local tween = TweenService:Create(clonedBlock, tweenInfo, tweenProperties)
tween:Play()
tween.Completed:Connect(function()
clonedBlock:Destroy()
end)
end
end)
end
end
end)
Commented out parts are my attempts [using AI] trying to get it to work.
How do I do this? I’ve been trying for a MONTH.
Also, here’s an example of if I try rotate something without the proper sizing.