forked from aya/aya
292 lines
7.7 KiB
Lua
292 lines
7.7 KiB
Lua
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
|