nickcool9999

PI Placement System

Nov 14th, 2017
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.61 KB | None | 0 0
  1. Download Example: https://mega.nz/#!8g5XlSqb!lbRigilYpDbdOupfc80AwavoQ9n-F0faCjC3MjmK5wE
  2.  
  3. local run_service = game:GetService("RunService")
  4. local anchor_name = workspace.Anchor_Part -- Anchor Part's name
  5. local tile_folder = workspace.Tiles -- where will the tiles be placed inside?
  6. local scan_distance = 500 -- how many studs away will the placement system scan?
  7. local x_lim,z_lim = 512,512 -- how far away from the anchor will you let the player place?
  8. local Mouse_Offset = Vector3.new(-2,0,-2) -- offset vector3 of mouse placement
  9. local smooth_placement = true -- PI's smooth placement system? true for yes, false for no
  10. local rotation = 0 -- edit this value in your input script to change rotation
  11.  
  12. -- safely return player
  13. function getLocalPlayer()
  14.     if not game.Players.LocalPlayer then
  15.         repeat wait() until game.Players.LocalPlayer -- halt until player found
  16.     end
  17.     return game.Players.LocalPlayer
  18. end
  19.  
  20. -- safely return character
  21. function getLocalCharacter()
  22.     local pl = getLocalPlayer()
  23.     if not pl.Character then
  24.         repeat wait() until pl.Character -- halt until character exists
  25.     end
  26.     return pl.Character
  27. end
  28.  
  29. function round(x) return math.floor(x+0.5) end
  30. function onr(r,c,v3) if r==c then return v3 end end
  31. 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)
  32. function GetOffset(Size,r)
  33.     -- rotation fix, will determine Vector3 offset for less weird rotation
  34.     local a = Vector3.new(round(Size.X),round(Size.Y),round(Size.Z))/4
  35.    
  36.     local ax=a.X%2 local az=a.Z%2
  37.     local pick
  38.     if ax == 0 and az == 0 then -- 0 0 offset
  39.         pick = onr(r,0,none) or onr(r,90,none) or onr(r,180,none) or onr(r,270,none)
  40.         return pick
  41.     elseif ax == 0 and az == 1 then -- 0 1 offset
  42.         pick = onr(r,0,none) or onr(r,90,foo) or onr(r,180,oof) or onr(r,270,none)
  43.         return pick
  44.     elseif ax == 1 and az == 0 then -- 1 0 offset
  45.         pick = onr(r,0,oof) or onr(r,90,foo) or onr(r,180,fof) or onr(r,270,fof)
  46.         return pick
  47.     else -- 1 1 offset
  48.         pick = onr(r,0,none) or onr(r,90,foo) or onr(r,180,fof) or onr(r,270,oof)
  49.         return pick
  50.     end
  51. end
  52. function modelPutty(x)
  53.     -- this will "Putty" the model, which will make it transparent
  54.     for _,c in pairs(x:GetChildren()) do
  55.         if (c:IsA("BasePart") or c:IsA("UnionOperation")) and not c:FindFirstChild("PuttyTransparency") and c.Name ~= "Upgrader" then
  56.             local v = Instance.new("NumberValue",c)
  57.             v.Name = "PuttyTransparency"
  58.             v.Value = c.Transparency
  59.             local v2 = Instance.new("BoolValue",c)
  60.             v2.Name = "PuttyCollidable"
  61.             v2.Value = c.CanCollide
  62.             c.CanCollide = false
  63.             if c.Name:find("Marker")==nil then
  64.                 c.Transparency = math.min(c.Transparency + 0.5,1)
  65.             end
  66.         end
  67.         if c.Name:find("Marker")==nil then
  68.             modelPutty(c)
  69.         end
  70.     end
  71. end
  72. function modelUnputty(x)
  73.     -- make model visible again, but wont be needed for placement
  74.     for _,c in pairs(x:GetChildren()) do
  75.         if (c:IsA("BasePart") or c:IsA("UnionOperation")) and c:FindFirstChild("PuttyTransparency") then
  76.             c.Transparency = c.PuttyTransparency.Value
  77.             c.CanCollide = c.PuttyCollidable.Value
  78.             c.PuttyTransparency:Destroy()
  79.             c.PuttyCollidable:Destroy()
  80.         end
  81.     end
  82. end
  83.  
  84. UIS = game:GetService"UserInputService"
  85. local key_map = { -- change key_map if your game needs different keys
  86.     cancel_placement = {
  87.         Keyboard={'Q'},
  88.         OnPress = function()
  89.             if selected_model then
  90.                 selected_model:Destroy()
  91.             end
  92.             selected_model = nil
  93.         end
  94.     },
  95.     rotate = {
  96.         Keyboard={'R'},
  97.         OnPress = function()
  98.             rotation = (rotation + 90) % 360 -- reset at 360
  99.         end
  100.     },
  101.     test_model = {
  102.         Keyboard={'E'},
  103.         OnPress = function()
  104.             print'select'
  105.             if selected_model then
  106.                 selected_model:Destroy()
  107.             end
  108.             selected_model = workspace.Test_Model:Clone()
  109.             modelPutty(selected_model)
  110.             selected_model.Parent = workspace.CurrentCamera
  111.         end
  112.     },
  113. }
  114. UIS.InputBegan:connect(function(Key)
  115.     local UType,Key_Code = Key.UserInputType.Name,Key.KeyCode.Name
  116.     for key_name,key_data in pairs(key_map) do
  117.         if key_data[UType] then -- cancel
  118.             for i = 1, #key_data[UType] do
  119.                 if key_data[UType][i]==Key_Code then
  120.                     key_data.OnPress(Key)
  121.                 end
  122.             end
  123.         end
  124.     end
  125. end)
  126.  
  127. while run_service.RenderStepped:wait() do
  128.  
  129.     --[[ requirements:
  130.     1) selected_model MUST have PrimaryPart
  131.     2) There MUST be an AnchorPart in workspace on which the grid will be placed
  132.     3) There MUST be a RemoteEvent / RemoteFunction hooked up for when you click
  133.         (You shouldnt use experimental mode anyways)
  134.     4) ALL PLACED TILES MUST BE PLACED IN TILE_FOLDER!!!!!
  135.         (Else your mouse will weirdly register where the model will be placed)
  136.     ]]
  137.     mouse = getLocalPlayer():GetMouse()
  138.     while selected_model and selected_model.PrimaryPart do
  139.         local ppart = selected_model.PrimaryPart
  140.         -- initial scan of mouse's ray
  141.         local Mouse_Ray = Ray.new(mouse.UnitRay.Origin, mouse.UnitRay.Direction * scan_distance)
  142.         intersect_part, Hit = workspace:FindPartOnRayWithIgnoreList(Mouse_Ray, {workspace.CurrentCamera, tile_folder, getLocalCharacter()})
  143.         Hit = Hit + Mouse_Offset
  144.         -- secondary scan of model position
  145.         local ray = Ray.new(ppart.CFrame.p, Vector3.new(0,-20,0))
  146.         local testpart = workspace:FindPartOnRayWithIgnoreList(ray, {workspace.CurrentCamera, tile_folder, getLocalCharacter()})
  147.         -- return model's offset based on rotation
  148.         local moffset = Vector3.new(0,0,0)
  149.         moffset = GetOffset(ppart.Size, rotation)
  150.         -- offset from anchor
  151.         local diff = Hit - anchor_name.Position
  152.         -- 'Valid' doesnt matter if there is no intersect_part, so include it in the checks
  153.         local XValid,ZValid=math.abs(diff.X)<=x_lim,math.abs(diff.Z)<=z_lim
  154.         local movePos
  155.         if intersect_part and XValid and ZValid then -- must be 'Valid'+'part'
  156.             -- primary part's size x and z determine its offset for placement
  157.             local psx,psz=ppart.Size.X/2,ppart.Size.Z/2
  158.             local mousePos = Vector3.new(round(Hit.X/4)*4, 0, round(Hit.Z/4)*4)
  159.             -- 1) calculate position you want the model to go
  160.             local look = CFrame.new(mousePos)
  161.                         * CFrame.Angles(0, -math.rad(rotation), 0)
  162.                         * CFrame.new(-psx%4, 0, -psz%4)
  163.                         + moffset
  164.             local cf2
  165.             -- 2) change by any offsets, plus the primarypart's Y size
  166.             cf2=look+Vector3.new(0,(ppart.Size.Y/2),0)
  167.             -- this variable is used for smooth placement
  168.             local dist = (cf2.p-selected_model.PrimaryPart.CFrame.p).magnitude
  169.             placecframe = cf2
  170.             if (dist<.2) or (dist>64) then
  171.                 -- too close or too far, teleport to goal cframe
  172.                 selected_model:SetPrimaryPartCFrame(cf2)
  173.             else
  174.                 -- smoothly move to goal cframe
  175.                 selected_model:SetPrimaryPartCFrame(ppart.CFrame:lerp(cf2,((not smooth_placement) and 1) or .6)) --.4
  176.             end
  177.         end
  178.         run_service.RenderStepped:wait()
  179.     end
  180.  
  181. end
Advertisement
Add Comment
Please, Sign In to add comment