Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Download Example: https://mega.nz/#!8g5XlSqb!lbRigilYpDbdOupfc80AwavoQ9n-F0faCjC3MjmK5wE
- local run_service = game:GetService("RunService")
- local anchor_name = workspace.Anchor_Part -- Anchor Part's name
- local tile_folder = workspace.Tiles -- where will the tiles be placed inside?
- local scan_distance = 500 -- how many studs away will the placement system scan?
- local x_lim,z_lim = 512,512 -- how far away from the anchor will you let the player place?
- local Mouse_Offset = Vector3.new(-2,0,-2) -- offset vector3 of mouse placement
- local smooth_placement = true -- PI's smooth placement system? true for yes, false for no
- local rotation = 0 -- edit this value in your input script to change rotation
- -- safely return player
- function getLocalPlayer()
- if not game.Players.LocalPlayer then
- repeat wait() until game.Players.LocalPlayer -- halt until player found
- end
- return game.Players.LocalPlayer
- end
- -- safely return character
- function getLocalCharacter()
- local pl = getLocalPlayer()
- if not pl.Character then
- repeat wait() until pl.Character -- halt until character exists
- end
- return pl.Character
- end
- function round(x) return math.floor(x+0.5) end
- function onr(r,c,v3) if r==c then return v3 end end
- local foo, fof, oof, none = Vector3.new(4,0,0), Vector3.new(4,0,4), Vector3.new(0,0,4), Vector3.new(0,0,0)
- function GetOffset(Size,r)
- -- rotation fix, will determine Vector3 offset for less weird rotation
- local a = Vector3.new(round(Size.X),round(Size.Y),round(Size.Z))/4
- local ax=a.X%2 local az=a.Z%2
- local pick
- if ax == 0 and az == 0 then -- 0 0 offset
- pick = onr(r,0,none) or onr(r,90,none) or onr(r,180,none) or onr(r,270,none)
- return pick
- elseif ax == 0 and az == 1 then -- 0 1 offset
- pick = onr(r,0,none) or onr(r,90,foo) or onr(r,180,oof) or onr(r,270,none)
- return pick
- elseif ax == 1 and az == 0 then -- 1 0 offset
- pick = onr(r,0,oof) or onr(r,90,foo) or onr(r,180,fof) or onr(r,270,fof)
- return pick
- else -- 1 1 offset
- pick = onr(r,0,none) or onr(r,90,foo) or onr(r,180,fof) or onr(r,270,oof)
- return pick
- end
- end
- function modelPutty(x)
- -- this will "Putty" the model, which will make it transparent
- for _,c in pairs(x:GetChildren()) do
- if (c:IsA("BasePart") or c:IsA("UnionOperation")) and not c:FindFirstChild("PuttyTransparency") and c.Name ~= "Upgrader" then
- local v = Instance.new("NumberValue",c)
- v.Name = "PuttyTransparency"
- v.Value = c.Transparency
- local v2 = Instance.new("BoolValue",c)
- v2.Name = "PuttyCollidable"
- v2.Value = c.CanCollide
- c.CanCollide = false
- if c.Name:find("Marker")==nil then
- c.Transparency = math.min(c.Transparency + 0.5,1)
- end
- end
- if c.Name:find("Marker")==nil then
- modelPutty(c)
- end
- end
- end
- function modelUnputty(x)
- -- make model visible again, but wont be needed for placement
- for _,c in pairs(x:GetChildren()) do
- if (c:IsA("BasePart") or c:IsA("UnionOperation")) and c:FindFirstChild("PuttyTransparency") then
- c.Transparency = c.PuttyTransparency.Value
- c.CanCollide = c.PuttyCollidable.Value
- c.PuttyTransparency:Destroy()
- c.PuttyCollidable:Destroy()
- end
- end
- end
- UIS = game:GetService"UserInputService"
- local key_map = { -- change key_map if your game needs different keys
- cancel_placement = {
- Keyboard={'Q'},
- OnPress = function()
- if selected_model then
- selected_model:Destroy()
- end
- selected_model = nil
- end
- },
- rotate = {
- Keyboard={'R'},
- OnPress = function()
- rotation = (rotation + 90) % 360 -- reset at 360
- end
- },
- test_model = {
- Keyboard={'E'},
- OnPress = function()
- print'select'
- if selected_model then
- selected_model:Destroy()
- end
- selected_model = workspace.Test_Model:Clone()
- modelPutty(selected_model)
- selected_model.Parent = workspace.CurrentCamera
- end
- },
- }
- UIS.InputBegan:connect(function(Key)
- local UType,Key_Code = Key.UserInputType.Name,Key.KeyCode.Name
- for key_name,key_data in pairs(key_map) do
- if key_data[UType] then -- cancel
- for i = 1, #key_data[UType] do
- if key_data[UType][i]==Key_Code then
- key_data.OnPress(Key)
- end
- end
- end
- end
- end)
- while run_service.RenderStepped:wait() do
- --[[ requirements:
- 1) selected_model MUST have PrimaryPart
- 2) There MUST be an AnchorPart in workspace on which the grid will be placed
- 3) There MUST be a RemoteEvent / RemoteFunction hooked up for when you click
- (You shouldnt use experimental mode anyways)
- 4) ALL PLACED TILES MUST BE PLACED IN TILE_FOLDER!!!!!
- (Else your mouse will weirdly register where the model will be placed)
- ]]
- mouse = getLocalPlayer():GetMouse()
- while selected_model and selected_model.PrimaryPart do
- local ppart = selected_model.PrimaryPart
- -- initial scan of mouse's ray
- local Mouse_Ray = Ray.new(mouse.UnitRay.Origin, mouse.UnitRay.Direction * scan_distance)
- intersect_part, Hit = workspace:FindPartOnRayWithIgnoreList(Mouse_Ray, {workspace.CurrentCamera, tile_folder, getLocalCharacter()})
- Hit = Hit + Mouse_Offset
- -- secondary scan of model position
- local ray = Ray.new(ppart.CFrame.p, Vector3.new(0,-20,0))
- local testpart = workspace:FindPartOnRayWithIgnoreList(ray, {workspace.CurrentCamera, tile_folder, getLocalCharacter()})
- -- return model's offset based on rotation
- local moffset = Vector3.new(0,0,0)
- moffset = GetOffset(ppart.Size, rotation)
- -- offset from anchor
- local diff = Hit - anchor_name.Position
- -- 'Valid' doesnt matter if there is no intersect_part, so include it in the checks
- local XValid,ZValid=math.abs(diff.X)<=x_lim,math.abs(diff.Z)<=z_lim
- local movePos
- if intersect_part and XValid and ZValid then -- must be 'Valid'+'part'
- -- primary part's size x and z determine its offset for placement
- local psx,psz=ppart.Size.X/2,ppart.Size.Z/2
- local mousePos = Vector3.new(round(Hit.X/4)*4, 0, round(Hit.Z/4)*4)
- -- 1) calculate position you want the model to go
- local look = CFrame.new(mousePos)
- * CFrame.Angles(0, -math.rad(rotation), 0)
- * CFrame.new(-psx%4, 0, -psz%4)
- + moffset
- local cf2
- -- 2) change by any offsets, plus the primarypart's Y size
- cf2=look+Vector3.new(0,(ppart.Size.Y/2),0)
- -- this variable is used for smooth placement
- local dist = (cf2.p-selected_model.PrimaryPart.CFrame.p).magnitude
- placecframe = cf2
- if (dist<.2) or (dist>64) then
- -- too close or too far, teleport to goal cframe
- selected_model:SetPrimaryPartCFrame(cf2)
- else
- -- smoothly move to goal cframe
- selected_model:SetPrimaryPartCFrame(ppart.CFrame:lerp(cf2,((not smooth_placement) and 1) or .6)) --.4
- end
- end
- run_service.RenderStepped:wait()
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment