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")

-- Local function definitions
local c = Workspace:WaitForChild("Terrain", 86400) or Workspace:WaitForChild("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
