forked from aya/aya
Initial commit
This commit is contained in:
291
client/studio/resources/BuiltInPlugins/terrain/08 - roads.lua
Normal file
291
client/studio/resources/BuiltInPlugins/terrain/08 - roads.lua
Normal file
@@ -0,0 +1,291 @@
|
||||
while game == nil do
|
||||
wait(1/30)
|
||||
end
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
local loaded = false
|
||||
local on = false
|
||||
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("Roads", "Roads", "roads.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
game:WaitForChild("Workspace")
|
||||
game.Workspace:WaitForChild("Terrain")
|
||||
|
||||
-- Local function definitions
|
||||
local c = game.Workspace.Terrain
|
||||
local SetCell = c.SetCell
|
||||
local GetCell = c.GetCell
|
||||
local WorldToCellPreferSolid = c.WorldToCellPreferSolid
|
||||
local WorldToCellPreferEmpty = c.WorldToCellPreferEmpty
|
||||
local SetCells = c.SetCells
|
||||
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
local x1 = 200
|
||||
local y1 = 200
|
||||
local x2 = 300
|
||||
local y2 = 300
|
||||
local h = 20
|
||||
local mode = 0
|
||||
|
||||
local DefaultTerrainMaterial = 1
|
||||
|
||||
local roadDragBar, roadFrame,roadFrame, roadCloseEvent = nil
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--makes a column of blocks from 0 up to height at location (x,z) in cluster c
|
||||
function coordHeight(x, z, height)
|
||||
SetCells(c, Region3int16.new(Vector3int16.new(x, 1, z), Vector3int16.new(x, height, z)), DefaultTerrainMaterial, 0, 0)
|
||||
end
|
||||
|
||||
function coordCheck(x, z, height)
|
||||
for h = height, 0, -1 do
|
||||
material, wedge, rotation = GetCell(c, x, h, z)
|
||||
if material.Value > 0 then
|
||||
return true
|
||||
elseif height == 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function dist(x1, y1, x2, y2)
|
||||
return math.sqrt(math.pow(x2-x1, 2) + math.pow(y2-y1, 2))
|
||||
end
|
||||
|
||||
function dist3d(x1, y1, z1, x2, y2, z2)
|
||||
return math.sqrt(math.pow(dist(x1, y1, x2, y2), 2) + math.pow(z2-z1, 2))
|
||||
end
|
||||
|
||||
--create a path between coordinates (x1,z1) and (x2,z2) at height h in cluster c
|
||||
--a path is a road with height of 3 instead of 1, and it builds a bridge if there is no existing land under it
|
||||
--if you want path to come from x direction, make it start at the place
|
||||
--if you want it to come from z direction, make it end at the place
|
||||
--if p is true, turns on pillars, otherwise pillars are off
|
||||
function makePath(x1, z1, x2, z2, h, p)
|
||||
if x2 < x1 then
|
||||
incx = -1
|
||||
n = 1
|
||||
else
|
||||
incx = 1
|
||||
n = -1
|
||||
end
|
||||
for x = x1, x2+n, incx do
|
||||
SetCells(c, Region3int16.new(Vector3int16.new(x, h+1, z1-1), Vector3int16.new(x, h+3, z1+1)), 0, 0, 0)
|
||||
SetCells(c, Region3int16.new(Vector3int16.new(x, h, z1-1), Vector3int16.new(x, h, z1+1)), DefaultTerrainMaterial, 0, 0)
|
||||
end
|
||||
if p then
|
||||
for x = x1, x2+n, 16*incx do
|
||||
if coordCheck(x, z1, h-1) then
|
||||
coordHeight(x, z1, h-1)
|
||||
end
|
||||
if coordCheck(x, z1-1, h-1) then
|
||||
coordHeight(x, z1-1, h-1)
|
||||
end
|
||||
if coordCheck(x, z1+1, h-1) then
|
||||
coordHeight(x, z1+1, h-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
if z2 < z1 then
|
||||
incz = -1
|
||||
m = 1
|
||||
n = 2
|
||||
else
|
||||
incz = 1
|
||||
m = -1
|
||||
n = -2
|
||||
end
|
||||
for z = z1+m, z2+n, incz do
|
||||
SetCells(c, Region3int16.new(Vector3int16.new(x2-1, h+1, z), Vector3int16.new(x2+1, h+3, z)), 0, 0, 0)
|
||||
SetCells(c, Region3int16.new(Vector3int16.new(x2-1, h, z), Vector3int16.new(x2+1, h, z)), DefaultTerrainMaterial, 0, 0)
|
||||
end
|
||||
if p then
|
||||
for z = z1+m, z2+n, 16*incz do
|
||||
if coordCheck(x2, z, h-1) then
|
||||
coordHeight(x2, z, h-1)
|
||||
end
|
||||
if coordCheck(x2-1, z, h-1) then
|
||||
coordHeight(x2-1, z, h-1)
|
||||
end
|
||||
if coordCheck(x2+1, z, h-1) then
|
||||
coordHeight(x2+1, z, h-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
game:GetService("ChangeHistoryService"): SetWaypoint("Roads")
|
||||
end
|
||||
|
||||
-- Do a line/plane intersection. The line starts at the camera. The plane is at y == 0, normal(0, 1, 0)
|
||||
--
|
||||
-- vectorPos - End point of the line.
|
||||
--
|
||||
-- Return:
|
||||
-- success - Value is true if there was a plane intersection, false if not.
|
||||
-- cellPos - Value is the terrain cell intersection point if there is one, vectorPos if there isn't.
|
||||
function PlaneIntersection(vectorPos)
|
||||
local currCamera = game.Workspace.CurrentCamera
|
||||
local startPos = Vector3.new(currCamera.CoordinateFrame.p.X, currCamera.CoordinateFrame.p.Y, currCamera.CoordinateFrame.p.Z)
|
||||
local endPos = Vector3.new(vectorPos.X, vectorPos.Y, vectorPos.Z)
|
||||
local normal = Vector3.new(0, 1, 0)
|
||||
local p3 = Vector3.new(0, 0, 0)
|
||||
local startEndDot = normal:Dot(endPos - startPos)
|
||||
local cellPos = vectorPos
|
||||
local success = false
|
||||
|
||||
if startEndDot ~= 0 then
|
||||
local t = normal:Dot(p3 - startPos) / startEndDot
|
||||
if(t >=0 and t <=1) then
|
||||
local intersection = ((endPos - startPos) * t) + startPos
|
||||
cellPos = c:WorldToCell(intersection)
|
||||
success = true
|
||||
end
|
||||
end
|
||||
|
||||
return success, cellPos
|
||||
end
|
||||
|
||||
function onClicked (mouse)
|
||||
if on then
|
||||
|
||||
local cellPos = WorldToCellPreferEmpty(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local solidCell = WorldToCellPreferSolid(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local success = false
|
||||
|
||||
-- If nothing was hit, do the plane intersection.
|
||||
if 0 == GetCell(c, solidCell.X, solidCell.Y, solidCell.Z).Value then
|
||||
--print('Plane Intersection happens')
|
||||
success, cellPos = PlaneIntersection(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
if not success then
|
||||
cellPos = solidCell
|
||||
end
|
||||
end
|
||||
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
if mode == 0 then
|
||||
x1 = x
|
||||
y1 = z
|
||||
h = y
|
||||
mode = 1
|
||||
|
||||
-- first click determines default material
|
||||
local celMat = GetCell(c, x, y, z)
|
||||
if celMat.Value > 0 then
|
||||
DefaultTerrainMaterial = celMat.Value
|
||||
else
|
||||
if 0 == DefaultTerrainMaterial then
|
||||
DefaultTerrainMaterial = 1
|
||||
end
|
||||
end
|
||||
elseif mode == 1 then
|
||||
x2 = x
|
||||
y2 = z
|
||||
makePath(x1, y1, x2, y2, h, true, c)
|
||||
mode = 0
|
||||
else
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
if not c then
|
||||
return
|
||||
end
|
||||
if self then
|
||||
self:Activate(true)
|
||||
end
|
||||
if toolbarbutton then
|
||||
toolbarbutton:SetActive(true)
|
||||
end
|
||||
if roadDragBar then
|
||||
roadDragBar.Visible = true
|
||||
end
|
||||
|
||||
mode = 0
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
if toolbarbutton then
|
||||
toolbarbutton:SetActive(false)
|
||||
end
|
||||
if roadDragBar then
|
||||
roadDragBar.Visible = false
|
||||
end
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
local g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
g.Name = "RoadGui"
|
||||
|
||||
roadDragBar, roadFrame, roadHelpFrame, roadCloseEvent = RbxGui.CreatePluginFrame("Roads",UDim2.new(0,141,0,80),UDim2.new(0,0,0,0),false,g)
|
||||
roadDragBar.Visible = false
|
||||
roadCloseEvent.Event:connect(function ( )
|
||||
Off()
|
||||
end)
|
||||
|
||||
local roadTextHelper = Instance.new("TextLabel",roadFrame)
|
||||
roadTextHelper.Text = "Click once to set the starting point and again to set the endpoint of the road."
|
||||
roadTextHelper.Font = Enum.Font.ArialBold
|
||||
roadTextHelper.FontSize = Enum.FontSize.Size14
|
||||
roadTextHelper.TextColor3 = Color3.new(1,1,1)
|
||||
roadTextHelper.BackgroundTransparency = 1
|
||||
roadTextHelper.Size = UDim2.new(1,-8,1,-8)
|
||||
roadTextHelper.Position = UDim2.new(0,4,0,4)
|
||||
roadTextHelper.TextXAlignment = Enum.TextXAlignment.Left
|
||||
roadTextHelper.TextYAlignment = Enum.TextYAlignment.Top
|
||||
roadTextHelper.TextWrap = true
|
||||
|
||||
roadHelpFrame.Size = UDim2.new(0,200,0,150)
|
||||
local helpText = Instance.new("TextLabel",roadHelpFrame)
|
||||
helpText.Font = Enum.Font.ArialBold
|
||||
helpText.FontSize = Enum.FontSize.Size12
|
||||
helpText.TextColor3 = Color3.new(1,1,1)
|
||||
helpText.BackgroundTransparency = 1
|
||||
helpText.TextWrap = true
|
||||
helpText.Size = UDim2.new(1,-10,1,-10)
|
||||
helpText.Position = UDim2.new(0,5,0,5)
|
||||
helpText.TextXAlignment = Enum.TextXAlignment.Left
|
||||
helpText.Text =
|
||||
[[Creates roads in existing terrain. Roads are created by setting a beginning point (first click on terrain) and an ending point (second click on terrain). The material of terrain is determined by the first click point. After the second click the tool resets and will create a new segment of road, not neccessarily connected to the first road segment created.]]
|
||||
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
Reference in New Issue
Block a user