Guest User

Placement Module Script

a guest
Sep 8th, 2019
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.08 KB | None | 0 0
  1. local INTERPOLATION = true -- whether placement smoothing is enabled
  2. local INTERPOLATION_DAMP = .21 -- how fast smoothing is, make it a value (0, 1]
  3. local ROTATION_SPEED = .2 -- rotation tween speed in seconds
  4.  
  5. local COLLISION_COLOR3 = Color3.fromRGB(255,0,0)--BrickColor.Red().Color -- color of the hitbox when object collides
  6. local COLLISION_TRANSPARENCY = .6 -- transparency of the hitbox when object collides
  7.  
  8. local NORMAL_COLOR3 = BrickColor.new().Color -- color of the hitbox
  9. local NORMAL_TRANSPARENCY = .6 -- transparency of the hitbox
  10.  
  11. local LOAD_COLOR3 = Color3.fromRGB(226, 155, 64) -- color of the hitbox when loading
  12. local LOAD_TRANSPARENCY = .6 -- transparency of the hitbox when loading
  13.  
  14. local GRID_TEXTURE = "rbxassetid://13786085" -- texture of the grid space, set to nil if you don't want a visible grid
  15.  
  16. local OVERRIDE_CONTROLS = false -- whether click to place and r to rotate are enabled
  17. local INPUT_PRIORITY = 9 -- input priority of default controls
  18. local TOUCH_RANGE = 30 -- range of mobile placement
  19.  
  20. local PLACEMENT_COOLDOWN = .45 -- how quickly the user can place
  21.  
  22.  
  23. --[[
  24.     DO NOT EDIT PAST THESE LINES UNLESS YOU KNOW WHAT YOU'RE DOING 
  25. --]]
  26.  
  27. local module = {}
  28.  
  29. local player = game.Players.LocalPlayer
  30. local mouse = player:GetMouse()
  31. local runService = game:GetService("RunService")
  32. local touch = game:GetService("UserInputService").TouchEnabled
  33.  
  34. local currentPlane
  35. local currentBase
  36.  
  37. local renderConnection = nil
  38.  
  39. local cx, cy, cz, cr = 0, 0, 0, 0
  40. local currentObjects = {}
  41. local currentEvent
  42. local currentTexture
  43. local currentPosition = Vector3.new(0, 0, 0)
  44. local ax, az
  45.  
  46. local currentExtentsX
  47. local currentExtentsZ
  48. local currentYAxis
  49. local currentXAxis
  50. local currentZAxis
  51. local currentAxis
  52.  
  53. local ox, oy, oz -- do
  54. local dxx, dxy, dxz
  55. local dzx, dzy, dzz
  56.  
  57. local min = math.min
  58. local max = math.max
  59. local abs = math.abs
  60.  
  61. local springVelocity = Vector3.new(0, 0, 0)
  62. local springPosition = Vector3.new(0, 0, 0)
  63. local tweenGoalRotation = 0 -- springs arent worth effort for rotation
  64. local tweenStartRotation = 0
  65. local tweenCurrentRotation = 0
  66. local tweenAlpha = 1
  67.  
  68. local lastRenderCycle = tick()
  69. local lastPlacement = tick()
  70.  
  71. local function round(n, to)
  72.     return n % to ~= 0 and (n % to) > to/2 and (n + to - (n % to)) or (n - (n % to))   
  73. end
  74.  
  75. local function project(px, py, pz)
  76.     px, py, pz = px - ox, py - oy, pz - oz
  77.    
  78.     return px * dxx + py * dxy + pz * dxz, px * dzx + py * dzy + pz * dzz
  79. end
  80.  
  81. local function translate(px, pz, r)
  82.     if (r == 0) then
  83.         return px, pz
  84.     elseif (r == 1) then
  85.         return -pz, px
  86.     elseif (r == 2) then
  87.         return -px, -pz
  88.     elseif (r == 3) then
  89.         return pz, -px
  90.     end
  91.    
  92. --  or for all angles
  93. --  r = r * math.pi/2
  94. --  return math.cos(r) * px - math.sin(r) * pz,  math.sin(r) * px + math.cos(r) * pz   
  95. end
  96.  
  97. local function angleLerp(a, b, d) -- to avoid angle jump
  98.     local x1, y1 = math.cos(a), math.sin(a)
  99.     local x2, y2 = math.cos(b), math.sin(b)
  100.    
  101.     return math.atan2(y1 + (y2 - y1) * d, x1 + (x2 - x1) * d)
  102. end
  103.  
  104. local function calculateExtents(part, cf)
  105.     local cf = cf or part.CFrame
  106.    
  107.     local edgeA = cf * CFrame.new(-part.Size.X/2, 0, 0)
  108.     local edgeB = cf * CFrame.new(part.Size.X/2, 0, 0)
  109.     local edgeC = cf * CFrame.new(0, 0, part.Size.Z/2)
  110.     local edgeD = cf * CFrame.new(0, 0, -part.Size.Z/2)
  111.    
  112.     local edgeAx, edgeAz = project(edgeA.X, edgeA.Y, edgeA.Z)
  113.     local edgeBx, edgeBz = project(edgeB.X, edgeB.Y, edgeB.Z)
  114.     local edgeCx, edgeCz = project(edgeC.X, edgeC.Y, edgeC.Z)
  115.     local edgeDx, edgeDz = project(edgeD.X, edgeD.Y, edgeD.Z)
  116.    
  117.     local extentsX = max(edgeAx, edgeBx, edgeCx, edgeDx) - min(edgeAx, edgeBx, edgeCx, edgeDx)
  118.     local extentsZ = max(edgeAz, edgeBz, edgeCz, edgeDz) - min(edgeAz, edgeBz, edgeCz, edgeDz)
  119.    
  120.     return round(extentsX, currentPlane.grid), round(extentsZ, currentPlane.grid)
  121. end
  122.  
  123. local states = {
  124.     neutral = 1;
  125.     collision = 2;
  126.     loading = 3;
  127. }
  128.  
  129. module.states = states
  130.  
  131. local function setState(object, state, downward)
  132.     if (object.state and (object.state == state or (object.state > state and not downward))) then
  133.         return
  134.     end
  135.    
  136.     object.state = state
  137.    
  138.     if (state == 1) then
  139.         if (NORMAL_COLOR3) then
  140.             object.model.PrimaryPart.Color = NORMAL_COLOR3
  141.         end
  142.         if (NORMAL_TRANSPARENCY) then
  143.             object.model.PrimaryPart.Transparency = NORMAL_TRANSPARENCY
  144.         end
  145.     elseif (state == 2) then
  146.         if (COLLISION_COLOR3) then
  147.             object.model.PrimaryPart.Color = COLLISION_COLOR3
  148.         end
  149.         if (COLLISION_TRANSPARENCY) then
  150.             object.model.PrimaryPart.Transparency = COLLISION_TRANSPARENCY
  151.         end
  152.     elseif (state == 3) then
  153.         if (LOAD_COLOR3) then
  154.             object.model.PrimaryPart.Color = LOAD_COLOR3
  155.         end
  156.         if (LOAD_TRANSPARENCY) then
  157.             object.model.PrimaryPart.Transparency = LOAD_TRANSPARENCY
  158.         end
  159.     end
  160.    
  161.     currentPlane.stateEvent:Fire(object.model, state)
  162. end
  163.  
  164. --[[
  165.     status
  166.     model
  167.     px, pz, r
  168.     sx, sz
  169. --]]
  170.  
  171. local function floatEqual(a, b)
  172.     return (math.abs(a - b) < .01)
  173. end
  174.  
  175. local function floatGreater(a, b)
  176.     return (a - b) > .01
  177. end
  178.  
  179. local function floatLesser(a, b)
  180.     return (b - a) > .01
  181. end
  182.  
  183. local function obstacleCollision()
  184.     local px, pz = cx, cz
  185.    
  186.     local collision = false
  187.    
  188.     for _, model in pairs(currentPlane.obstacles:GetChildren()) do
  189.         if (model.PrimaryPart) then
  190.            
  191.             local extentsX1, extentsZ1 = calculateExtents(model.PrimaryPart)
  192.             local x1, z1 = project(model.PrimaryPart.Position.X, model.PrimaryPart.Position.Y, model.PrimaryPart.Position.Z)           
  193.                        
  194.             for i = 1, #currentObjects do
  195.                 local object = currentObjects[i]
  196.                
  197.                 if (not object.collision) then
  198.                     local r = (object.r + cr) % 4          
  199.                    
  200.                     local x0, z0 = translate(object.px, -object.pz, cr)
  201.                     x0 = x0 + px
  202.                     z0 = z0 + pz
  203.                    
  204.                     local extentsX0, extentsZ0             
  205.                                
  206.                     if (r == 1 or r == 3) then
  207.                         extentsX0, extentsZ0 = object.sz, object.sx
  208.                     else
  209.                         extentsX0, extentsZ0 = object.sx, object.sz
  210.                     end    
  211.                    
  212.                     if (floatLesser(x0 - extentsX0/2, x1 + extentsX1/2) and floatGreater(x0 + extentsX0/2, x1 - extentsX1/2) and floatLesser(z0 - extentsZ0/2, z1 + extentsZ1/2) and floatGreater(z0 + extentsZ0/2, z1 - extentsZ1/2)) then
  213.                         collision = true
  214.                         object.collision = true
  215.                         setState(object, states.collision)
  216.                     end
  217.                 end
  218.             end
  219.         end
  220.     end
  221.    
  222.     for i = 1, #currentObjects do
  223.         local object = currentObjects[i]
  224.        
  225.         if (not object.collision and object.state == states.collision) then
  226.             setState(object, states.neutral, true)
  227.         else
  228.             object.collision = nil
  229.         end
  230.     end
  231.    
  232.     return not collision
  233. end
  234.  
  235. local function inputCapture() -- converts user inputs to 3d position, built in mobile compatibility
  236.     local position
  237.    
  238.     if (touch) then
  239.         local camera = workspace.CurrentCamera
  240.         local range = TOUCH_RANGE * (camera.Focus.p - camera.CFrame.p).magnitude/5 
  241.        
  242.         position = camera.Focus.p + camera.CFrame.lookVector * (camera.CoordinateFrame.lookVector.Y/2 + .5) * range
  243.     else
  244.         local hit, p = workspace:FindPartOnRayWithWhitelist(Ray.new(mouse.UnitRay.Origin, mouse.UnitRay.Direction * 999), {currentPlane.base})
  245.        
  246.         if (hit) then
  247.             position = p
  248.         end
  249.     end
  250.    
  251.     return position, cr
  252. end
  253.  
  254. local resting = false
  255.  
  256. local function calc(position, rotation, force)
  257.     if (not currentPlane or currentPlane.loading) then
  258.         return
  259.     end
  260.    
  261.     force = force == true
  262.    
  263.     local ux, uz
  264.    
  265.     if (position) then
  266.         ux, uz = project(position.X, position.Y, position.Z)
  267.     else
  268.         ux, uz = ax or 0, az or 0
  269.     end
  270.          
  271.     local nr = rotation or cr
  272.        
  273.     local nx = round(ux, currentPlane.grid)
  274.     local nz = round(uz, currentPlane.grid)
  275.    
  276.     local extentsX, extentsZ = translate(currentExtentsX, currentExtentsZ, nr)
  277.     extentsX = abs(extentsX)
  278.     extentsZ = abs(extentsZ)
  279.    
  280.     if (floatEqual(extentsX/2 % currentPlane.grid, 0)) then
  281.         nx = nx + currentPlane.grid/2
  282.     end
  283.    
  284.     if (floatEqual(extentsZ/2 % currentPlane.grid, 0)) then
  285.         nz = nz + currentPlane.grid/2
  286.     end
  287.    
  288.     nx = nx + currentPlane.offsetX
  289.     nz = nz + currentPlane.offsetZ
  290.    
  291.     local borderX = currentPlane.size.X/2
  292.     local borderZ = currentPlane.size.Z/2
  293.    
  294.     ax = ux
  295.     az = uz
  296.    
  297.     if (nx + extentsX/2 > borderX) then
  298.         nx = nx - (nx + extentsX/2 - borderX)
  299.     elseif (nx - extentsX/2 < -borderX) then
  300.         nx = nx - (nx - extentsX/2 + borderX)
  301.     end
  302.    
  303.     if (nz + extentsZ/2 > borderZ) then
  304.         nz = nz - (nz + extentsZ/2 - borderZ)
  305.     elseif (nz - extentsZ/2 < -borderZ) then
  306.         nz = nz - (nz - extentsZ/2 + borderZ)
  307.     end
  308.    
  309.     if (force or nx ~= cx or nz ~= cz or cr ~= nr) then
  310.         cx, cz, cr = nx, nz, nr
  311.         resting = false
  312.         currentPosition = (Vector3.new(ox, oy, oz) + currentXAxis * nx + currentZAxis * nz)
  313.         obstacleCollision()
  314.     end
  315. end
  316.  
  317. local function render()
  318.     if (resting) then
  319.         return
  320.     end
  321.    
  322.     if (INTERPOLATION) then
  323.         local delta = 1/60
  324.        
  325.         springVelocity = (springVelocity + (currentPosition - springPosition)) * INTERPOLATION_DAMP * 60 * delta
  326.         springPosition = springPosition + springVelocity
  327.        
  328.         local extentsX, extentsZ = translate(currentExtentsX, currentExtentsZ, cr)
  329.        
  330.         local vx, vz = 9 * springVelocity:Dot(currentXAxis)/abs(extentsX), 9 * springVelocity:Dot(currentZAxis)/abs(extentsZ)
  331.         local r
  332.        
  333.         if (not floatEqual(tweenGoalRotation, cr * math.pi/2)) then
  334.             tweenStartRotation = tweenCurrentRotation
  335.             tweenGoalRotation = cr * math.pi/2
  336.             tweenAlpha = 0
  337.         end
  338.                
  339.         if (tweenAlpha < 1) then
  340.             tweenAlpha = min(1, tweenAlpha + delta/ROTATION_SPEED)
  341.             tweenCurrentRotation = angleLerp(tweenStartRotation, tweenGoalRotation, 1 - (1 - tweenAlpha)^2)
  342.             r = tweenCurrentRotation
  343.         else
  344.             r = cr * math.pi/2
  345.         end
  346.        
  347.        
  348.         local effectAngle = CFrame.Angles(math.sqrt(math.abs(vz/100)) * math.sign(vz), 0, math.sqrt(math.abs(vx/100)) * math.sign(vx))
  349.        
  350.         local rotationCFrame = currentAxis * effectAngle * CFrame.Angles(0, r, 0)
  351.         local centerCFrame = rotationCFrame + springPosition
  352.        
  353.         for i = 1, #currentObjects do
  354.             local object = currentObjects[i]
  355.                        
  356.             local x, z = object.px, object.pz          
  357.            
  358.             object.model:SetPrimaryPartCFrame(centerCFrame * CFrame.Angles(0, object.r * math.pi/2, 0) + rotationCFrame * Vector3.new(x, object.sy/2, z))
  359.         end    
  360.        
  361.         if (springVelocity.magnitude < .01 and tweenAlpha >= 1) then
  362.             resting = true
  363.         end
  364.     else
  365.         local rotationCFrame = currentAxis * CFrame.Angles(0, cr * math.pi/2, 0)       
  366.        
  367.         for i = 1, #currentObjects do
  368.             local object = currentObjects[i]
  369.             local x, z = object.px, object.pz
  370.            
  371.             object.model:SetPrimaryPartCFrame(rotationCFrame * CFrame.Angles(0, object.r * math.pi/2, 0) + rotationCFrame * Vector3.new(x, object.sy/2, z) + currentPosition)
  372.         end
  373.        
  374.         resting = true
  375.     end
  376. end
  377.  
  378. local function run(display)
  379.     local position, rotation = inputCapture()
  380.    
  381.     if (position or rotation) then
  382.         calc(position, rotation)
  383.         if (display) then
  384.             render()
  385.         end
  386.     end
  387. end
  388.  
  389. local function place()
  390.     if (currentPlane and (obstacleCollision()) and (tick() - lastPlacement) >= PLACEMENT_COOLDOWN and not currentPlane.loading) then
  391.         lastPlacement = tick()
  392.                
  393.         local modelCFrames = {}
  394.        
  395.         for i = 1, #currentObjects do
  396.             local object = currentObjects[i]
  397.             modelCFrames[i] = currentAxis * CFrame.Angles(0, (object.r + cr) * math.pi/2, 0) +  (currentAxis * CFrame.Angles(0, cr * math.pi/2, 0)) * Vector3.new(object.px, object.sy/2, object.pz) + currentPosition
  398.         end
  399.        
  400.         currentEvent:Fire(modelCFrames)    
  401.     end
  402. end
  403.  
  404. local function rotate()
  405.     calc(nil, (cr + 1) % 4)
  406.     render()
  407. end
  408.  
  409. local function inputRotate(_, userInputState, inputObject)
  410.     if (currentPlane and userInputState == Enum.UserInputState.End) then
  411.         rotate()
  412.     end
  413. end
  414.  
  415. local function inputPlace(_, userInputState, inputObject)
  416.     if (currentPlane and userInputState == Enum.UserInputState.End) then
  417.         place()
  418.     end
  419. end
  420.  
  421. local function bindInputs()
  422.     if (not OVERRIDE_CONTROLS) then
  423.         game:GetService("ContextActionService"):BindActionAtPriority("PlacementModule_Rotate", inputRotate, false, INPUT_PRIORITY, Enum.KeyCode.R)
  424.         game:GetService("ContextActionService"):BindActionAtPriority("PlacementModule_Place", inputPlace, false, INPUT_PRIORITY, Enum.UserInputType.MouseButton1)
  425.     end
  426. end
  427.  
  428. local function unbindInputs()
  429.     if (not OVERRIDE_CONTROLS) then
  430.         game:GetService("ContextActionService"):UnbindAction("PlacementModule_Rotate")
  431.         game:GetService("ContextActionService"):UnbindAction("PlacementModule_Place")
  432.     end
  433. end
  434.  
  435. local function enablePlacement(plane, models, prealigned)
  436.     if (plane == currentPlane) then
  437.         return
  438.     elseif (currentPlane) then
  439.         currentPlane:disable()
  440.     end
  441.    
  442.     if (type(models) ~= "table") then
  443.         models = {models}
  444.     end
  445.    
  446.     lastRenderCycle = tick()
  447.    
  448.     currentPlane = plane
  449.     currentBase = plane.base
  450.  
  451.     local planePosition = currentBase.CFrame * Vector3.new(0, currentBase.Size.Y/2, 0) 
  452.    
  453.     resting = false
  454.     ox, oy, oz = planePosition.X, planePosition.Y, planePosition.Z
  455.     currentXAxis = currentBase.CFrame.rightVector
  456.     currentYAxis = currentBase.CFrame.upVector
  457.     currentZAxis = currentBase.CFrame.lookVector
  458.     currentAxis = CFrame.new(0, 0, 0, currentXAxis.X, currentYAxis.X, -currentZAxis.X, currentXAxis.Y, currentYAxis.Y, -currentZAxis.Y, currentXAxis.Z, currentYAxis.Z, -currentZAxis.Z)
  459.     currentObjects = {}
  460.     dxx, dxy, dxz = currentXAxis.X, currentXAxis.Y, currentXAxis.Z
  461.     dzx, dzy, dzz = currentZAxis.X, currentZAxis.Y, currentZAxis.Z
  462.     cx, cy, cz, cr = 0, 0, 0, 0
  463.    
  464.     springVelocity = Vector3.new(0, 0, 0)
  465.     springPosition = Vector3.new(0, 0, 0)
  466.    
  467.     tweenAlpha = 0
  468.     tweenCurrentRotation = 0
  469.     tweenGoalRotation = 0
  470.     tweenStartRotation = 0
  471.    
  472.     local position, _ = inputCapture()
  473.    
  474.     if (not position) then
  475.         position = planePosition
  476.     end
  477.    
  478.     springPosition = position
  479.    
  480.     do
  481.         local extentsXMin, extentsXMax = 10e10, -10e10
  482.         local extentsZMin, extentsZMax = 10e10, -10e10
  483.        
  484.         for i = 1, #models do
  485.             local model = models[i]
  486.             local object = {}
  487.             object.model = model
  488.            
  489.             local lookVector = object.model.PrimaryPart.CFrame.lookVector  
  490.             local theta
  491.             local px, pz
  492.            
  493.             if (prealigned) then
  494.                 local position = object.model.PrimaryPart.CFrame * Vector3.new(0, -object.model.PrimaryPart.Size.Y/2 , 0)      
  495.                 px, pz = project(position.X, position.Y, position.Z)
  496.  
  497.                 theta = math.acos(math.clamp(lookVector:Dot(currentZAxis), -1, 1))
  498.                 local cross = lookVector:Cross(currentZAxis)
  499.                
  500.                 if (cross:Dot(currentYAxis) > 0) then
  501.                     theta = -theta
  502.                 end
  503.                
  504.             else
  505.                 px, pz = object.model.PrimaryPart.Position.X, object.model.PrimaryPart.Position.Z
  506.                 theta = math.atan2(lookVector.X, lookVector.Z)     
  507.             end
  508.            
  509.             local x, z = model.PrimaryPart.Size.X, model.PrimaryPart.Size.Z
  510.            
  511.             object.r = round((theta % (2 * math.pi))/(math.pi/2), 1)
  512.            
  513.             if (object.r == 1 or object.r == 3) then
  514.                 x, z = z, x
  515.             end
  516.            
  517.             local x1, x2 = px + x/2, px - x/2
  518.             local z1, z2 = pz + z/2, pz - z/2  
  519.            
  520.             if (x2 < extentsXMin) then
  521.                 extentsXMin = x2
  522.             end
  523.             if (x1 > extentsXMax) then
  524.                 extentsXMax = x1
  525.             end
  526.            
  527.             if (z2 < extentsZMin) then
  528.                 extentsZMin = z2
  529.             end
  530.             if (z1 > extentsZMax) then
  531.                 extentsZMax = z1
  532.             end
  533.                        
  534.            
  535.             model.PrimaryPart.Transparency = .5
  536.             model.PrimaryPart.Anchored = true
  537.             model.PrimaryPart.CanCollide = false
  538.            
  539.             setState(object, plane.loading and states.loading or states.neutral)
  540.            
  541.             currentObjects[i] = object
  542.         end
  543.        
  544.         currentExtentsX, currentExtentsZ = round(extentsXMax - extentsXMin, currentPlane.grid), round(extentsZMax - extentsZMin, currentPlane.grid)
  545.                
  546.         for i = 1, #currentObjects do
  547.             local object = currentObjects[i]
  548.             local px, pz
  549.            
  550.             if (prealigned) then
  551.                 local position = object.model.PrimaryPart.CFrame * Vector3.new(0, -object.model.PrimaryPart.Size.Y/2, 0)       
  552.                 px, pz = project(position.X, position.Y, position.Z)
  553.             else
  554.                 px, pz = object.model.PrimaryPart.Position.X, object.model.PrimaryPart.Position.Z
  555.             end
  556.            
  557.             object.px = px - (extentsXMin + extentsXMax)/2
  558.             object.pz = (pz - (extentsZMin + extentsZMax)/2) * (prealigned and -1 or 1)
  559.                                    
  560.             object.sx, object.sy, object.sz = object.model.PrimaryPart.Size.X, object.model.PrimaryPart.Size.Y, object.model.PrimaryPart.Size.Z
  561.         end
  562.     end
  563.    
  564.     renderConnection = runService.RenderStepped:connect(run)
  565.     module.currentPlane = currentPlane
  566.     currentEvent = Instance.new("BindableEvent")
  567.    
  568.     if (GRID_TEXTURE) then
  569.         currentTexture = Instance.new("Texture", currentPlane.base)
  570.         currentTexture.Texture = GRID_TEXTURE
  571.         currentTexture.Face = Enum.NormalId.Top
  572.         currentTexture.StudsPerTileU = currentPlane.grid
  573.         currentTexture.StudsPerTileV = currentPlane.grid
  574.     end
  575.        
  576.     bindInputs()
  577.    
  578.     run(true)
  579.        
  580.     return currentEvent.Event
  581. end
  582.  
  583. local function disablePlacement(plane)
  584.     if (currentPlane) then
  585.         renderConnection:disconnect()
  586.         renderConnection = nil
  587.         currentPlane = nil
  588.         module.currentPlane = nil
  589.         currentEvent:Destroy()
  590.         currentEvent = nil 
  591.        
  592.         if (currentTexture) then
  593.             currentTexture:Destroy()
  594.             currentTexture = nil
  595.         end
  596.        
  597.         for i = 1, #currentObjects do
  598.             local object = currentObjects[i]
  599.             object.model = nil
  600.             currentObjects[i] = nil
  601.         end
  602.        
  603.         unbindInputs()
  604.     end
  605. end
  606.  
  607. local function setLoading(plane, isLoading)
  608.     if (plane.loading == isLoading) then
  609.         return
  610.     end
  611.    
  612.     plane.loading = isLoading
  613.    
  614.     if (plane == currentPlane) then
  615.         if (isLoading) then
  616.             for i = 1, #currentObjects do
  617.                 setState(currentObjects[i], states.loading)
  618.             end
  619.         else
  620.             for i = 1, #currentObjects do
  621.                 setState(currentObjects[i], states.neutral, true)
  622.             end
  623.            
  624.             obstacleCollision()
  625.         end
  626.     end
  627. end
  628.  
  629. module.new = function(base, obstacles, grid)
  630.     local plane = {}
  631.     plane.base = base
  632.     plane.obstacles = obstacles
  633.     plane.position = base.Position
  634.     plane.size = base.Size
  635.    
  636.     if (math.floor(.5 + plane.size.X/grid) % 2 == 0) then
  637.         plane.offsetX = -grid/2
  638.     else
  639.         plane.offsetX = 0
  640.     end
  641.    
  642.     if (math.floor(.5 + plane.size.Z/grid) % 2 == 0) then
  643.         plane.offsetZ = -grid/2
  644.     else
  645.         plane.offsetZ = 0
  646.     end
  647.    
  648.    
  649.     plane.stateEvent = Instance.new("BindableEvent")
  650.     plane.stateChanged = plane.stateEvent.Event
  651.    
  652.     plane.grid = grid
  653.     plane.enable = enablePlacement
  654.     plane.disable = disablePlacement
  655.     plane.rotate = rotate
  656.     plane.place = place
  657.     plane.setLoading = setLoading
  658.    
  659.     return plane
  660. end
  661.  
  662. module.setLoading = setLoading
  663. module.currentPlane = false
  664.  
  665. return module
Advertisement
Add Comment
Please, Sign In to add comment