GEEKING
@@ -0,0 +1,570 @@
|
||||
-- Local function definitions
|
||||
local c = game.Workspace.Terrain
|
||||
local SetCell = c.SetCell
|
||||
local GetCell = c.GetCell
|
||||
local SetCells = c.SetCells
|
||||
local AutoWedge = c.AutowedgeCells
|
||||
|
||||
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
xpos = 0
|
||||
zpos = 0
|
||||
width = 512
|
||||
length = 512
|
||||
a = 30
|
||||
f = 8
|
||||
on = false
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Terrain Generator", "terrain.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--makes a column of blocks from 1 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)), 1, 0, 0)
|
||||
end
|
||||
|
||||
--makes a heightmap for a layer of mountains (width x depth)
|
||||
--with a width frequency wf and depthfrequency df (width should be divisible by wf, depth should be divisible by df) (for unsquished results, width/wf = depth/df)
|
||||
--with a range of amplitudes between 0 and a
|
||||
function mountLayer(width, depth, wf, df, a)
|
||||
local heightmap = {}
|
||||
for i = 0, width-1 do
|
||||
heightmap[i] = {}
|
||||
for k = 0, depth-1 do
|
||||
heightmap[i][k] = 0
|
||||
end
|
||||
end
|
||||
math.randomseed(tick())
|
||||
local corners = {}
|
||||
for i = 0,wf do
|
||||
corners[i] = {}
|
||||
for k = 0, df do
|
||||
corners[i][k] = a*math.random()
|
||||
end
|
||||
end
|
||||
for i = 0, wf do
|
||||
corners[i][0] = 0
|
||||
corners[i][math.floor(df)] = 0
|
||||
end
|
||||
for k = 0, df do
|
||||
corners[0][k]=0
|
||||
corners[math.floor(wf)][k]=0
|
||||
end
|
||||
|
||||
for i = 0, width-(width/wf), width/wf do
|
||||
for k = 0, depth-(depth/df), depth/df do
|
||||
local c1 = corners[i/(width/wf)][k/(depth/df)]
|
||||
local c2 = corners[i/(width/wf)][(k+depth/df)/(depth/df)]
|
||||
local c3 = corners[(i+width/wf)/(width/wf)][k/(depth/df)]
|
||||
local c4 = corners[(i+width/wf)/(width/wf)][(k+depth/df)/(depth/df)]
|
||||
for x = i, i+(width/wf)-1 do
|
||||
for z = k, k+(depth/df)-1 do
|
||||
local avgc1c3 = (math.abs(x-i)*c3 + math.abs(x-(i+width/wf))*c1)/(width/wf)
|
||||
local avgc2c4 = (math.abs(x-i)*c4 + math.abs(x-(i+width/wf))*c2)/(width/wf)
|
||||
local avg = math.floor((math.abs(z-k)*avgc2c4 + math.abs(z-(k+depth/df))*avgc1c3)/(depth/df))
|
||||
if (avg > 100) then
|
||||
print(avg)
|
||||
avg = 1
|
||||
end
|
||||
heightmap[x][z]= avg
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return heightmap
|
||||
end
|
||||
|
||||
--makes a shell around block at coordinate x, z using heightmap
|
||||
function makeShell(x, z, heightmap, shellheightmap)
|
||||
local originalheight = heightmap[x][z]
|
||||
for i = x - 1, x + 1 do
|
||||
for k = z - 1, z + 1 do
|
||||
if shellheightmap[i][k] < originalheight then
|
||||
for h = originalheight, shellheightmap[i][k] - 2, -1 do
|
||||
if h > 0 then
|
||||
SetCell(c, i, h, k, 1, 0, 0)
|
||||
end
|
||||
end
|
||||
shellheightmap[i][k] = originalheight
|
||||
end
|
||||
end
|
||||
end
|
||||
return shellheightmap
|
||||
end
|
||||
|
||||
function setCamera()
|
||||
local currCamera = game.Workspace.CurrentCamera
|
||||
currCamera.CoordinateFrame = CFrame.new(0, 400, 1600)
|
||||
currCamera.Focus = CFrame.new(0, 255, 0)
|
||||
end
|
||||
|
||||
|
||||
function onGenerate()
|
||||
generate.BorderColor3 = Color3.new(0, 0, 0)
|
||||
generate.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
generate.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
if g:FindFirstChild("gload") == nil then
|
||||
gload = Instance.new("Frame", g)
|
||||
gload.Name = "gload"
|
||||
gload.Position = UDim2.new(0.4, 0, 0.025, 0)
|
||||
gload.Size = UDim2.new(0.2, 0, 0.05, 0)
|
||||
gload.BackgroundTransparency = 0.5
|
||||
gfill = Instance.new("Frame", gload)
|
||||
gfill.Name = "gfill"
|
||||
gfill.Position = UDim2.new(0, 0, 0, 0)
|
||||
gfill.Size = UDim2.new(0, 0, 1, 0)
|
||||
gfill.BackgroundColor3 = Color3.new(1, 0.25, 0)
|
||||
gfill.BackgroundTransparency = 0.5
|
||||
gloadstatus = Instance.new("TextLabel", gload)
|
||||
gloadstatus.Position = UDim2.new(0.4, 0, 0.4, 0)
|
||||
gloadstatus.Size = UDim2.new(0.2, 0, 0.2, 0)
|
||||
gloadstatus.Text = ""
|
||||
gloadstatus.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
gloadstatus.TextColor3 = Color3.new(1, 1, 1)
|
||||
gloadstatus.Font = Enum.Font.ArialBold
|
||||
gloadstatus.FontSize = Enum.FontSize.Size14
|
||||
gloadstatus.BorderColor3 = Color3.new(0, 0, 0)
|
||||
gloadstatus.BackgroundTransparency = 1
|
||||
else
|
||||
gload = g:FindFirstChild("gload")
|
||||
gfill = gload:FindFirstChild("gfill")
|
||||
gload.Visible = 1
|
||||
gfill.Visible = 1
|
||||
gfill.Size = UDim2.new(0, 0, 1, 0)
|
||||
gloadstatus.Text = ""
|
||||
end
|
||||
|
||||
--Generate Terrain
|
||||
-- offset terrain additionally by whatever the smallest cell is
|
||||
--xpos2 = xpos + game.Workspace.Terrain.MaxExtents.Min.X
|
||||
--zpos2 = zpos + game.Workspace.Terrain.MaxExtents.Min.Z
|
||||
xpos2 = xpos - width/2
|
||||
zpos2 = zpos - length/2
|
||||
|
||||
-- make sure we can see all the terrain
|
||||
if game.Workspace.CurrentCamera.CoordinateFrame.p.Y < 255 then
|
||||
setCamera()
|
||||
end
|
||||
|
||||
--make 3 layers of mountains (you can change the frequency and amplitude of each layer and add or remove layers as you see fit (but don't forget to add the new layers to the loop below)
|
||||
a1 = mountLayer(width, length, f*width/512, f*length/512, 3/5*a)
|
||||
a2 = mountLayer(width, length, 2*f*width/512, 2*f*length/512, 2/5*a)
|
||||
heightmap = {}
|
||||
for x = 0, width - 1 do
|
||||
heightmap[x + xpos2] = {}
|
||||
for z = 0, length - 1 do
|
||||
heightmap[x + xpos2][z + zpos2] = a1[x][z] + a2[x][z]
|
||||
end
|
||||
end
|
||||
shellheightmap = {}
|
||||
for x = 0, width - 1 do
|
||||
shellheightmap[x + xpos2] = {}
|
||||
for z = 0, length - 1 do
|
||||
shellheightmap[x + xpos2][z + zpos2] = heightmap[x + xpos2][z + zpos2]
|
||||
end
|
||||
end
|
||||
gprogress = 0
|
||||
gloadstatus.Text = "Generating Terrain Shape..."
|
||||
k = 1 + zpos2
|
||||
|
||||
local waitCount = 0
|
||||
|
||||
while k < length - 1 + zpos2 do
|
||||
for x = 1 + xpos2, width - 2 + xpos2 do
|
||||
coordHeight(x, k, heightmap[x][k])
|
||||
shellheightmap = makeShell(x, k, heightmap, shellheightmap)
|
||||
end
|
||||
k = k + 1
|
||||
gprogress = gprogress + 2/(length * 3)
|
||||
gfill.Size = UDim2.new(gprogress, 0, 1, 0)
|
||||
if waitCount > 5 then waitCount = 0 wait(0.01) else waitCount = waitCount + 1 end
|
||||
end
|
||||
gloadstatus.Text = "Smoothing Terrain..."
|
||||
k = 1 + zpos2
|
||||
waitCount = 0
|
||||
local maxHeight = -1
|
||||
local oldK = k
|
||||
while k < length - 1 + zpos2 do
|
||||
for x = 1 + xpos2, width - 2 + xpos2 do
|
||||
height = shellheightmap[x][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
if height > maxHeight then
|
||||
maxHeight = height
|
||||
end
|
||||
end
|
||||
k = k + 1
|
||||
gprogress = gprogress + 1/(length * 3)
|
||||
gfill.Size = UDim2.new(gprogress, 0, 1, 0)
|
||||
if waitCount > 10 then
|
||||
waitCount = 0
|
||||
AutoWedge(c, Region3int16.new(Vector3int16.new(1 + xpos2, 0, oldK), Vector3int16.new(width - 2 + xpos2, maxHeight, k)))
|
||||
oldK = k+1
|
||||
maxHeight = -1
|
||||
wait()
|
||||
else waitCount = waitCount + 1 end
|
||||
if k == length - 2 + zpos2 then
|
||||
AutoWedge(c, Region3int16.new(Vector3int16.new(1 + xpos2, 0, oldK), Vector3int16.new(width - 2 + xpos2, maxHeight, k)))
|
||||
|
||||
gfill.Parent.Visible = false
|
||||
gfill.Visible = false
|
||||
end
|
||||
end
|
||||
|
||||
--Generate Terrain End
|
||||
end
|
||||
|
||||
function onReset()
|
||||
reset.BorderColor3 = Color3.new(0, 0, 0)
|
||||
reset.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
reset.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
|
||||
if g:FindFirstChild("rload") == nil then
|
||||
rload = Instance.new("Frame", g)
|
||||
rload.Name = "rload"
|
||||
rload.Position = UDim2.new(0.4, 0, 0.025, 0)
|
||||
rload.Size = UDim2.new(0.2, 0, 0.05, 0)
|
||||
rload.BackgroundTransparency = 0.5
|
||||
rfill = Instance.new("Frame", rload)
|
||||
rfill.Name = "rfill"
|
||||
rfill.Position = UDim2.new(0, 0, 0, 0)
|
||||
rfill.Size = UDim2.new(0, 0, 1, 0)
|
||||
rfill.BackgroundColor3 = Color3.new(1, 0.25, 0)
|
||||
rfill.BackgroundTransparency = 0.5
|
||||
else
|
||||
rload = g:FindFirstChild("rload")
|
||||
rfill = rload:FindFirstChild("rfill")
|
||||
rload.Visible = 1
|
||||
rfill.Visible = 1
|
||||
rfill.Size = UDim2.new(0, 0, 1, 0)
|
||||
end
|
||||
--Erase Terrain
|
||||
|
||||
local xMax = c.MaxExtents.Max.X
|
||||
local yMax = c.MaxExtents.Max.Y
|
||||
local zMax = c.MaxExtents.Max.Z
|
||||
|
||||
local xMin = c.MaxExtents.Min.X
|
||||
local yMin = c.MaxExtents.Min.Y
|
||||
local zMin = c.MaxExtents.Min.Z
|
||||
|
||||
|
||||
rprogress = 0
|
||||
|
||||
local waitCount = 0
|
||||
|
||||
z = zMax
|
||||
while z >= zMin do
|
||||
SetCells(c, Region3int16.new(Vector3int16.new(xMin, yMin, z), Vector3int16.new(xMax, yMax, z)), 0, 0, 0)
|
||||
z = z - 1
|
||||
|
||||
rprogress = rprogress + 1/(zMax - zMin + 1)
|
||||
rfill.Size = UDim2.new(rprogress, 0, 1, 0)
|
||||
if z == zMin then
|
||||
reset.BorderColor3 = Color3.new(0, 0, 0)
|
||||
rfill.Parent.Visible = false
|
||||
rfill.Visible = false
|
||||
end
|
||||
if waitCount > 5 then waitCount = 0 wait(0.001) else waitCount = waitCount + 1 end
|
||||
end
|
||||
|
||||
--Erase Terrain End
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
frame.Visible = true
|
||||
for w = 0, 0.6, 0.1 do
|
||||
frame.Size = UDim2.new(w, 0, w + 0.2, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
title.Text = "Terrain Generation"
|
||||
xposl.Text = "X-Offset: "..xpos
|
||||
zposl.Text = "Z-Offset: "..zpos
|
||||
widthl.Text = "Width: "..width
|
||||
lengthl.Text = "Length: "..length
|
||||
ampl.Text = "Amplitude: "..a
|
||||
freql.Text = "Frequency: "..f
|
||||
generate.Text = "Generate"
|
||||
reset.Text = "Reset"
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
title.Text = ""
|
||||
xposl.Text = ""
|
||||
zposl.Text = ""
|
||||
widthl.Text = ""
|
||||
lengthl.Text = ""
|
||||
ampl.Text = ""
|
||||
freql.Text = ""
|
||||
generate.Text = ""
|
||||
reset.Text = ""
|
||||
for w = 0.6, 0, -0.1 do
|
||||
frame.Size = UDim2.new(w, 0, w + 0.2, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
frame.Visible = false
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Size = UDim2.new(0.6, 0, 0.8, 0)
|
||||
frame.Position = UDim2.new(0.2, 0, 0.1, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
|
||||
--title
|
||||
title = Instance.new("TextLabel", frame)
|
||||
title.Position = UDim2.new(0.4, 0, 0.05, 0)
|
||||
title.Size = UDim2.new(0.2, 0, 0.05, 0)
|
||||
title.Text = ""
|
||||
title.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
title.TextColor3 = Color3.new(1, 1, 1)
|
||||
title.Font = Enum.Font.ArialBold
|
||||
title.FontSize = Enum.FontSize.Size24
|
||||
title.BorderColor3 = Color3.new(0, 0, 0)
|
||||
title.BackgroundTransparency = 1
|
||||
|
||||
--current xoffset display label
|
||||
xposl = Instance.new("TextLabel", frame)
|
||||
xposl.Position = UDim2.new(0.05, 0, 0.2, 0)
|
||||
xposl.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
xposl.Text = ""
|
||||
xposl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
xposl.TextColor3 = Color3.new(1, 1, 1)
|
||||
xposl.Font = Enum.Font.ArialBold
|
||||
xposl.FontSize = Enum.FontSize.Size14
|
||||
xposl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
xposl.BackgroundTransparency = 1
|
||||
|
||||
--xoffset slider
|
||||
xposSliderGui, xposSliderPosition = RbxGui.CreateSlider(128, 0, UDim2.new(0.2, 0, 0.22, 0))
|
||||
xposSliderGui.Parent = frame
|
||||
xposBar = xposSliderGui:FindFirstChild("Bar")
|
||||
xposBar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
xposSliderPosition.Value = (xpos+252)/4 + 1
|
||||
xposSliderPosition.Changed:connect(function()
|
||||
xpos = (xposSliderPosition.Value - 1) * 4 - 252
|
||||
xposl.Text = "X-Offset: "..xpos
|
||||
end)
|
||||
|
||||
--current zoffset display label
|
||||
zposl = Instance.new("TextLabel", frame)
|
||||
zposl.Position = UDim2.new(0.05, 0, 0.3, 0)
|
||||
zposl.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
zposl.Text = ""
|
||||
zposl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
zposl.TextColor3 = Color3.new(1, 1, 1)
|
||||
zposl.Font = Enum.Font.ArialBold
|
||||
zposl.FontSize = Enum.FontSize.Size14
|
||||
zposl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
zposl.BackgroundTransparency = 1
|
||||
|
||||
--zoffset slider
|
||||
zposSliderGui, zposSliderPosition = RbxGui.CreateSlider(128, 0, UDim2.new(0.2, 0, 0.32, 0))
|
||||
zposSliderGui.Parent = frame
|
||||
zposBar = zposSliderGui:FindFirstChild("Bar")
|
||||
zposBar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
zposSliderPosition.Value = (zpos+252)/4 + 1
|
||||
zposSliderPosition.Changed:connect(function()
|
||||
zpos = (zposSliderPosition.Value - 1) * 4 - 252
|
||||
zposl.Text = "Z-Offset: "..zpos
|
||||
end)
|
||||
|
||||
--current width display label
|
||||
widthl = Instance.new("TextLabel", frame)
|
||||
widthl.Position = UDim2.new(0.05, 0, 0.4, 0)
|
||||
widthl.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
widthl.Text = ""
|
||||
widthl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
widthl.TextColor3 = Color3.new(1, 1, 1)
|
||||
widthl.Font = Enum.Font.ArialBold
|
||||
widthl.FontSize = Enum.FontSize.Size14
|
||||
widthl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
widthl.BackgroundTransparency = 1
|
||||
|
||||
--width slider
|
||||
widthSliderGui, widthSliderPosition = RbxGui.CreateSlider(4, 0, UDim2.new(0.2, 0, 0.42, 0))
|
||||
widthSliderGui.Parent = frame
|
||||
widthbar = widthSliderGui:FindFirstChild("Bar")
|
||||
widthbar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
widthSliderPosition.Value = 4
|
||||
widthSliderPosition.Changed:connect(function()
|
||||
width = math.pow(2, widthSliderPosition.Value + 5)
|
||||
widthl.Text = "Width: "..width
|
||||
end)
|
||||
|
||||
--current length display label
|
||||
lengthl = Instance.new("TextLabel", frame)
|
||||
lengthl.Position = UDim2.new(0.05, 0, 0.5, 0)
|
||||
lengthl.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
lengthl.Text = ""
|
||||
lengthl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
lengthl.TextColor3 = Color3.new(1, 1, 1)
|
||||
lengthl.Font = Enum.Font.ArialBold
|
||||
lengthl.FontSize = Enum.FontSize.Size14
|
||||
lengthl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
lengthl.BackgroundTransparency = 1
|
||||
|
||||
--length slider
|
||||
lengthSliderGui, lengthSliderPosition = RbxGui.CreateSlider(4, 0, UDim2.new(0.2, 0, 0.52, 0))
|
||||
lengthSliderGui.Parent = frame
|
||||
lengthbar = lengthSliderGui:FindFirstChild("Bar")
|
||||
lengthbar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
lengthSliderPosition.Value = 4
|
||||
lengthSliderPosition.Changed:connect(function()
|
||||
length = math.pow(2, lengthSliderPosition.Value + 5)
|
||||
lengthl.Text = "Length: "..length
|
||||
end)
|
||||
|
||||
--current amplitude display label
|
||||
ampl = Instance.new("TextLabel", frame)
|
||||
ampl.Position = UDim2.new(0.05, 0, 0.6, 0)
|
||||
ampl.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
ampl.Text = ""
|
||||
ampl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
ampl.TextColor3 = Color3.new(1, 1, 1)
|
||||
ampl.Font = Enum.Font.ArialBold
|
||||
ampl.FontSize = Enum.FontSize.Size14
|
||||
ampl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
ampl.BackgroundTransparency = 1
|
||||
|
||||
--amplitude slider
|
||||
ampSliderGui, ampSliderPosition = RbxGui.CreateSlider(62, 0, UDim2.new(0.2, 0, 0.62, 0))
|
||||
ampSliderGui.Parent = frame
|
||||
ampbar = ampSliderGui:FindFirstChild("Bar")
|
||||
ampbar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
ampSliderPosition.Value = a + 1
|
||||
ampSliderPosition.Changed:connect(function()
|
||||
a = ampSliderPosition.Value + 1
|
||||
ampl.Text = "Amplitude: "..a
|
||||
end)
|
||||
|
||||
--current frequency display label
|
||||
freql = Instance.new("TextLabel", frame)
|
||||
freql.Position = UDim2.new(0.05, 0, 0.7, 0)
|
||||
freql.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
freql.Text = ""
|
||||
freql.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
freql.TextColor3 = Color3.new(1, 1, 1)
|
||||
freql.Font = Enum.Font.ArialBold
|
||||
freql.FontSize = Enum.FontSize.Size14
|
||||
freql.BorderColor3 = Color3.new(0, 0, 0)
|
||||
freql.BackgroundTransparency = 1
|
||||
|
||||
--frequency slider
|
||||
freqSliderGui, freqSliderPosition = RbxGui.CreateSlider(8, 0, UDim2.new(0.2, 0, 0.72, 0))
|
||||
freqSliderGui.Parent = frame
|
||||
freqbar = freqSliderGui:FindFirstChild("Bar")
|
||||
freqbar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
freqSliderPosition.Value = 4
|
||||
freqSliderPosition.Changed:connect(function()
|
||||
f = math.pow(2, freqSliderPosition.Value - 1)
|
||||
freql.Text = "Frequency: "..f
|
||||
end)
|
||||
|
||||
--generate button
|
||||
generate = Instance.new("TextButton", frame)
|
||||
generate.Position = UDim2.new(0.275, 0, 0.85, 0)
|
||||
generate.Size = UDim2.new(0.2, 0, 0.1, 0)
|
||||
generate.Text = ""
|
||||
generate.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
generate.TextColor3 = Color3.new(1, 1, 1)
|
||||
generate.Font = Enum.Font.ArialBold
|
||||
generate.FontSize = Enum.FontSize.Size14
|
||||
generate.BorderColor3 = Color3.new(0, 0, 0)
|
||||
generate.BackgroundTransparency = 0.5
|
||||
generate.MouseEnter:connect(function()
|
||||
generate.BorderColor3 = Color3.new(1, 1, 1)
|
||||
generate.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
generate.BackgroundTransparency = 0.2
|
||||
end)
|
||||
generate.MouseButton1Click:connect(onGenerate)
|
||||
generate.MouseLeave:connect(function()
|
||||
generate.BorderColor3 = Color3.new(0, 0, 0)
|
||||
generate.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
generate.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
--reset button
|
||||
reset = Instance.new("TextButton", frame)
|
||||
reset.Position = UDim2.new(0.525, 0, 0.85, 0)
|
||||
reset.Size = UDim2.new(0.2, 0, 0.1, 0)
|
||||
reset.Text = ""
|
||||
reset.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
reset.TextColor3 = Color3.new(1, 1, 1)
|
||||
reset.Font = Enum.Font.ArialBold
|
||||
reset.FontSize = Enum.FontSize.Size14
|
||||
reset.BorderColor3 = Color3.new(0, 0, 0)
|
||||
reset.BackgroundTransparency = 0.5
|
||||
reset.MouseEnter:connect(function()
|
||||
reset.BorderColor3 = Color3.new(1, 1, 1)
|
||||
reset.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
reset.BackgroundTransparency = 0.2
|
||||
end)
|
||||
reset.MouseButton1Click:connect(onReset)
|
||||
reset.MouseLeave:connect(function()
|
||||
reset.BorderColor3 = Color3.new(0, 0, 0)
|
||||
reset.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
reset.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Terrain Plugin Loaded")
|
||||
@@ -0,0 +1,240 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Builder", "builder.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
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
|
||||
|
||||
--converts the coordinate coord into a cluster coordinate where clusterlength is the length of the cluster in the same dimension as coord
|
||||
function clusterCoord(coord, clusterlength)
|
||||
return math.floor((coord + clusterlength/2)/4)
|
||||
end
|
||||
|
||||
--makes a wedge at location x, y, z
|
||||
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
|
||||
--returns true if made a wedge, false if the cell remains a block
|
||||
function MakeWedge(x, y, z, defaultmaterial)
|
||||
local c = game.Workspace.Terrain
|
||||
--gather info about all the cells around x, y, z
|
||||
surroundings = {} --surroundings is a 3 x 3 x 3 array of the material of the cells adjacent to x, y, z
|
||||
for i = x - 1, x + 1 do
|
||||
surroundings[i] = {}
|
||||
for j = y - 1, y + 1 do
|
||||
surroundings[i][j] = {}
|
||||
for k = z - 1, z + 1 do
|
||||
local material, wedge, rotation = c:GetCell(i, j, k)
|
||||
surroundings[i][j][k] = material.Value
|
||||
end
|
||||
end
|
||||
end
|
||||
--make some useful arrays and counters
|
||||
local sides = {} --sides is an array of the material of the 4 adjacent sides
|
||||
sides[0] = surroundings[x - 1][y][z]
|
||||
sides[1] = surroundings[x][y][z + 1]
|
||||
sides[2] = surroundings[x + 1][y][z]
|
||||
sides[3] = surroundings[x][y][z - 1]
|
||||
local adjacentSides = 0
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
adjacentSides = adjacentSides + 1
|
||||
end
|
||||
end
|
||||
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
|
||||
sidesAbove[0] = surroundings[x - 1][y + 1][z]
|
||||
sidesAbove[1] = surroundings[x][y + 1][z + 1]
|
||||
sidesAbove[2] = surroundings[x + 1][y + 1][z]
|
||||
sidesAbove[3] = surroundings[x][y + 1][z - 1]
|
||||
local adjacentSidesAbove = 0
|
||||
for n = 0, 3 do
|
||||
if sidesAbove[n] > 0 then
|
||||
adjacentSidesAbove = adjacentSidesAbove + 1
|
||||
end
|
||||
end
|
||||
local corners = {} --corners is an array of the material of the 4 adjacent corners
|
||||
corners[0] = surroundings[x - 1][y][z - 1]
|
||||
corners[1] = surroundings[x - 1][y][z + 1]
|
||||
corners[2] = surroundings[x + 1][y][z + 1]
|
||||
corners[3] = surroundings[x + 1][y][z - 1]
|
||||
local adjacentCorners = 0
|
||||
for n = 0, 3 do
|
||||
if corners[n] > 0 then
|
||||
adjacentCorners = adjacentCorners + 1
|
||||
end
|
||||
end
|
||||
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
|
||||
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
|
||||
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
|
||||
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
|
||||
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
|
||||
local adjacentCornersAbove = 0
|
||||
for n = 0, 3 do
|
||||
if cornersAbove[n] > 0 then
|
||||
adjacentCornersAbove = adjacentCornersAbove + 1
|
||||
end
|
||||
end
|
||||
--determine what type of wedge to make
|
||||
local material = nil
|
||||
local wedge = nil
|
||||
local rotation = nil
|
||||
if defaultmaterial then
|
||||
material = defaultmaterial
|
||||
else
|
||||
material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
|
||||
end
|
||||
wedge = 0 --default wedge is a block
|
||||
rotation = 0 --default rotation is 0
|
||||
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
if adjacentSides == 1 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 1) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 3 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
|
||||
wedge = 2
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
|
||||
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
|
||||
if adjacentCorners > 1 then
|
||||
for n = 0, 3 do
|
||||
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 4 and adjacentCorners == 3 then
|
||||
for n = 0, 3 do
|
||||
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
|
||||
if adjacentSides == 2 and adjacentCorners < 4 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
|
||||
wedge = 4
|
||||
rotation = n
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function onClicked(mouse)
|
||||
if on then
|
||||
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
local cellPos = c:WorldToCellPreferEmpty(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
c:SetCell(x, y, z, 1, 0, 0)
|
||||
for i = x - 1, x + 1 do
|
||||
for j = y - 1, y + 1 do
|
||||
for k = z - 1, z + 1 do
|
||||
MakeWedge(i, j, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
print("Block built at: "..x..", "..y..", "..z)
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Builder Plugin Loaded")
|
||||
@@ -0,0 +1,234 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Remover", "remover.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
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
|
||||
|
||||
--makes a wedge at location x, y, z
|
||||
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
|
||||
--returns true if made a wedge, false if the cell remains a block
|
||||
function MakeWedge(x, y, z, defaultmaterial)
|
||||
local c = game.Workspace.Terrain
|
||||
--gather info about all the cells around x, y, z
|
||||
surroundings = {} --surroundings is a 3 x 3 x 3 array of the material of the cells adjacent to x, y, z
|
||||
for i = x - 1, x + 1 do
|
||||
surroundings[i] = {}
|
||||
for j = y - 1, y + 1 do
|
||||
surroundings[i][j] = {}
|
||||
for k = z - 1, z + 1 do
|
||||
local material, wedge, rotation = c:GetCell(i, j, k)
|
||||
surroundings[i][j][k] = material.Value
|
||||
end
|
||||
end
|
||||
end
|
||||
--make some useful arrays and counters
|
||||
local sides = {} --sides is an array of the material of the 4 adjacent sides
|
||||
sides[0] = surroundings[x - 1][y][z]
|
||||
sides[1] = surroundings[x][y][z + 1]
|
||||
sides[2] = surroundings[x + 1][y][z]
|
||||
sides[3] = surroundings[x][y][z - 1]
|
||||
local adjacentSides = 0
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
adjacentSides = adjacentSides + 1
|
||||
end
|
||||
end
|
||||
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
|
||||
sidesAbove[0] = surroundings[x - 1][y + 1][z]
|
||||
sidesAbove[1] = surroundings[x][y + 1][z + 1]
|
||||
sidesAbove[2] = surroundings[x + 1][y + 1][z]
|
||||
sidesAbove[3] = surroundings[x][y + 1][z - 1]
|
||||
local adjacentSidesAbove = 0
|
||||
for n = 0, 3 do
|
||||
if sidesAbove[n] > 0 then
|
||||
adjacentSidesAbove = adjacentSidesAbove + 1
|
||||
end
|
||||
end
|
||||
local corners = {} --corners is an array of the material of the 4 adjacent corners
|
||||
corners[0] = surroundings[x - 1][y][z - 1]
|
||||
corners[1] = surroundings[x - 1][y][z + 1]
|
||||
corners[2] = surroundings[x + 1][y][z + 1]
|
||||
corners[3] = surroundings[x + 1][y][z - 1]
|
||||
local adjacentCorners = 0
|
||||
for n = 0, 3 do
|
||||
if corners[n] > 0 then
|
||||
adjacentCorners = adjacentCorners + 1
|
||||
end
|
||||
end
|
||||
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
|
||||
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
|
||||
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
|
||||
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
|
||||
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
|
||||
local adjacentCornersAbove = 0
|
||||
for n = 0, 3 do
|
||||
if cornersAbove[n] > 0 then
|
||||
adjacentCornersAbove = adjacentCornersAbove + 1
|
||||
end
|
||||
end
|
||||
--determine what type of wedge to make
|
||||
local material = nil
|
||||
local wedge = nil
|
||||
local rotation = nil
|
||||
if defaultmaterial then
|
||||
material = defaultmaterial
|
||||
else
|
||||
material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
|
||||
end
|
||||
wedge = 0 --default wedge is a block
|
||||
rotation = 0 --default rotation is 0
|
||||
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
if adjacentSides == 1 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 1) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 3 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
|
||||
wedge = 2
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
|
||||
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
|
||||
if adjacentCorners > 1 then
|
||||
for n = 0, 3 do
|
||||
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 4 and adjacentCorners == 3 then
|
||||
for n = 0, 3 do
|
||||
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
|
||||
if adjacentSides == 2 and adjacentCorners < 4 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
|
||||
wedge = 4
|
||||
rotation = n
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return false
|
||||
end
|
||||
|
||||
function onClicked(mouse)
|
||||
if on then
|
||||
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
c:SetCell(x, y, z, 0, 0, 0)
|
||||
for i = x - 1, x + 1 do
|
||||
for j = y - 1, y + 1 do
|
||||
for k = z - 1, z + 1 do
|
||||
MakeWedge(i, j, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
print("Block destroyed at: "..x..", "..y..", "..z)
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Remover Plugin Loaded")
|
||||
@@ -0,0 +1,459 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
mousedown = false
|
||||
r = 0
|
||||
s = 1
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Elevation Adjuster", "elevation.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function()
|
||||
onClicked(mouse)
|
||||
end)
|
||||
mouse.Button1Up:connect(function() mousedown = false end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--find height at coordinate x, z
|
||||
function findHeight(x, z)
|
||||
c = game.Workspace.Terrain
|
||||
h = 0
|
||||
material, wedge, rotation = c:GetCell(x, h + 1, z)
|
||||
while material.Value > 0 do
|
||||
h = h + 1
|
||||
material, wedge, rotation = c:GetCell(x, h + 1, z)
|
||||
end
|
||||
return h
|
||||
end
|
||||
|
||||
|
||||
--makes a shell around block at coordinate x, z using heightmap
|
||||
function makeShell(x, z, heightmap, shellheightmap)
|
||||
local c = game.Workspace.Terrain
|
||||
local originalheight = heightmap[x][z]
|
||||
for i = x - 1, x + 1 do
|
||||
for k = z - 1, z + 1 do
|
||||
if shellheightmap[i][k] < originalheight then
|
||||
for h = originalheight, shellheightmap[i][k] - 2, -1 do
|
||||
if h > 0 then
|
||||
c:SetCell(i, h, k, 1, 0, 0)
|
||||
end
|
||||
end
|
||||
shellheightmap[i][k] = originalheight
|
||||
end
|
||||
end
|
||||
end
|
||||
return shellheightmap
|
||||
end
|
||||
|
||||
|
||||
--makes a wedge at location x, y, z using info from heightmap instead of GetCell
|
||||
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
|
||||
--returns true if made a wedge, false if the cell remains a block
|
||||
function MakeWedge(x, y, z, heightmap, defaultmaterial)
|
||||
local c = game.Workspace.Terrain
|
||||
--gather info about all the cells around x, y, z
|
||||
local surroundings = {} --surroundings is a 3 x 3 x 3 array of the cells adjacent to x, y, z (1 if a cell is there, 0 if not)
|
||||
for i = x - 1, x + 1 do
|
||||
surroundings[i] = {}
|
||||
for j = y - 1, y + 1 do
|
||||
surroundings[i][j] = {}
|
||||
for k = z - 1, z + 1 do
|
||||
heightmapi = heightmap[i]
|
||||
height = nil
|
||||
if heightmapi then
|
||||
height = heightmapi[k]
|
||||
end
|
||||
if height and height >= j then
|
||||
surroundings[i][j][k] = 1
|
||||
else
|
||||
surroundings[i][j][k] = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--make some useful arrays and counters
|
||||
local sides = {} --sides is an array of the material of the 4 adjacent sides
|
||||
sides[0] = surroundings[x - 1][y][z]
|
||||
sides[1] = surroundings[x][y][z + 1]
|
||||
sides[2] = surroundings[x + 1][y][z]
|
||||
sides[3] = surroundings[x][y][z - 1]
|
||||
local adjacentSides = 0
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
adjacentSides = adjacentSides + 1
|
||||
end
|
||||
end
|
||||
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
|
||||
sidesAbove[0] = surroundings[x - 1][y + 1][z]
|
||||
sidesAbove[1] = surroundings[x][y + 1][z + 1]
|
||||
sidesAbove[2] = surroundings[x + 1][y + 1][z]
|
||||
sidesAbove[3] = surroundings[x][y + 1][z - 1]
|
||||
local adjacentSidesAbove = 0
|
||||
for n = 0, 3 do
|
||||
if sidesAbove[n] > 0 then
|
||||
adjacentSidesAbove = adjacentSidesAbove + 1
|
||||
end
|
||||
end
|
||||
local corners = {} --corners is an array of the material of the 4 adjacent corners
|
||||
corners[0] = surroundings[x - 1][y][z - 1]
|
||||
corners[1] = surroundings[x - 1][y][z + 1]
|
||||
corners[2] = surroundings[x + 1][y][z + 1]
|
||||
corners[3] = surroundings[x + 1][y][z - 1]
|
||||
local adjacentCorners = 0
|
||||
for n = 0, 3 do
|
||||
if corners[n] > 0 then
|
||||
adjacentCorners = adjacentCorners + 1
|
||||
end
|
||||
end
|
||||
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
|
||||
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
|
||||
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
|
||||
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
|
||||
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
|
||||
local adjacentCornersAbove = 0
|
||||
for n = 0, 3 do
|
||||
if cornersAbove[n] > 0 then
|
||||
adjacentCornersAbove = adjacentCornersAbove + 1
|
||||
end
|
||||
end
|
||||
--determine what type of wedge to make
|
||||
local material = nil
|
||||
local wedge = nil
|
||||
local rotation = nil
|
||||
if defaultmaterial then
|
||||
material = defaultmaterial
|
||||
else
|
||||
material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
|
||||
end
|
||||
wedge = 0 --default wedge is a block
|
||||
rotation = 0 --default rotation is 0
|
||||
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
if adjacentSides == 1 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 1) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 3 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
|
||||
wedge = 2
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
|
||||
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
|
||||
if adjacentCorners > 1 then
|
||||
for n = 0, 3 do
|
||||
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 4 and adjacentCorners == 3 then
|
||||
for n = 0, 3 do
|
||||
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
|
||||
if adjacentSides == 2 and adjacentCorners < 4 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
|
||||
wedge = 4
|
||||
rotation = n
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--elevates terrain at point (x, y, z) in cluster c
|
||||
--within radius r1 from x, z the elevation should become y + d
|
||||
--from radius r1 to r2 the elevation should be a gradient
|
||||
function elevate(x, y, z, r1, r2, d, range)
|
||||
local c = game.Workspace.Terrain
|
||||
|
||||
for i = x - (range + 2), x + (range + 2) do
|
||||
if oldheightmap[i] == nil then
|
||||
oldheightmap[i] = {}
|
||||
end
|
||||
for k = z - (range + 2), z + (range + 2) do
|
||||
if oldheightmap[i][k] == nil then
|
||||
oldheightmap[i][k] = findHeight(i, k)
|
||||
end
|
||||
|
||||
|
||||
--figure out the height to make coordinate (i, k)
|
||||
local distance = dist(i, k, x, z)
|
||||
if distance < r1 then
|
||||
height = y + d
|
||||
elseif distance < r2 then
|
||||
height = math.floor((y + d) * (1 - (distance - r1)/(r2 - r1)) + oldheightmap[i][k] * (distance - r1)/(r2 - r1))
|
||||
else
|
||||
height = oldheightmap[i][k]
|
||||
end
|
||||
if height == 0 then
|
||||
height = -1
|
||||
end
|
||||
|
||||
--heightmap[i][k] should be the current height of coordinate (i, k)
|
||||
if heightmap[i] == nil then
|
||||
heightmap[i] = {}
|
||||
end
|
||||
if heightmap[i][k] == nil then
|
||||
heightmap[i][k] = oldheightmap[i][k]
|
||||
end
|
||||
|
||||
--the height is either greater than or less than the current height
|
||||
if height > heightmap[i][k] then
|
||||
for h = heightmap[i][k] - 2, height do
|
||||
c:SetCell(i, h, k, 1, 0, 0)
|
||||
end
|
||||
heightmap[i][k] = height
|
||||
elseif height < heightmap[i][k] then
|
||||
for h = heightmap[i][k], height + 1, -1 do
|
||||
c:SetCell(i, h, k, 0, 0, 0)
|
||||
end
|
||||
heightmap[i][k] = height
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--copy heightmap into shellheightmap
|
||||
shellheightmap = {}
|
||||
for i = x - (range + 2), x + (range + 2) do
|
||||
if shellheightmap[i] == nil then
|
||||
shellheightmap[i] = {}
|
||||
end
|
||||
for k = z - (range + 2), z + (range + 2) do
|
||||
shellheightmap[i][k] = heightmap[i][k]
|
||||
end
|
||||
end
|
||||
--shell everything
|
||||
for i = x - range , x + range do
|
||||
for k = z - range, z + range do
|
||||
if shellheightmap[i][k] ~= oldheightmap[i][k] then
|
||||
shellheightmap = makeShell(i, k, heightmap, shellheightmap)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = x - (range + 2), x + (range + 2) do
|
||||
for k = z - (range + 2), z + (range + 2) do
|
||||
heightmap[i][k] = shellheightmap[i][k]
|
||||
end
|
||||
end
|
||||
|
||||
for i = x - (range + 1), x + (range + 1) do
|
||||
for k = z - (range + 1), z + (range + 1) do
|
||||
local height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 1, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap, 1) then
|
||||
break
|
||||
end
|
||||
end
|
||||
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, z1, x2, z2), 2) + math.pow(math.abs(y2-y1)*100/d, 2))
|
||||
end
|
||||
|
||||
function onClicked(mouse)
|
||||
if on then
|
||||
|
||||
local c = game.Workspace.Terrain
|
||||
oldheightmap = {}
|
||||
heightmap = {}
|
||||
local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.X
|
||||
local y = cellPos.Y
|
||||
local z = cellPos.Z
|
||||
|
||||
mousedown = true
|
||||
local originalY = mouse.Y
|
||||
local prevY = originalY
|
||||
local d = 0
|
||||
local range = 0
|
||||
while mousedown == true do
|
||||
|
||||
if math.abs(mouse.Y - prevY) >= 5 then
|
||||
prevY = mouse.Y
|
||||
r2 = r + math.floor(50 * 1/s * math.abs(originalY - prevY)/mouse.ViewSizeY)
|
||||
if r2 > range then
|
||||
range = r2
|
||||
end
|
||||
d = math.floor(50 * (originalY - prevY)/mouse.ViewSizeY)
|
||||
elevate(x, y, z, r, r2, d, range)
|
||||
end
|
||||
wait(0)
|
||||
end
|
||||
print("Elevated at: "..x..", "..y..", "..z)
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
frame.Visible = true
|
||||
for w = 0, 0.3, 0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
radl.Text = "Radius: "..r
|
||||
sfl.Text = "Slope: "..s
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
radl.Text = ""
|
||||
sfl.Text = ""
|
||||
for w = 0.3, 0, -0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
frame.Visible = false
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Position = UDim2.new(0.35, 0, 0.8, 0)
|
||||
frame.Size = UDim2.new(0.3, 0, 0.15, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
|
||||
--current radius display label
|
||||
radl = Instance.new("TextLabel", frame)
|
||||
radl.Position = UDim2.new(0.05, 0, 0.1, 0)
|
||||
radl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
radl.Text = ""
|
||||
radl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
radl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
radl.Font = Enum.Font.ArialBold
|
||||
radl.FontSize = Enum.FontSize.Size14
|
||||
radl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
radl.BackgroundTransparency = 1
|
||||
|
||||
--radius slider
|
||||
radSliderGui, radSliderPosition = RbxGui.CreateSlider(11, 0, UDim2.new(0.3, 0, 0.26, 0))
|
||||
radSliderGui.Parent = frame
|
||||
radBar = radSliderGui:FindFirstChild("Bar")
|
||||
radBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
radSliderPosition.Value = r + 1
|
||||
radSliderPosition.Changed:connect(function()
|
||||
r = radSliderPosition.Value - 1
|
||||
radl.Text = "Radius: "..r
|
||||
end)
|
||||
|
||||
--current slope factor display label
|
||||
sfl = Instance.new("TextLabel", frame)
|
||||
sfl.Position = UDim2.new(0.05, 0, 0.55, 0)
|
||||
sfl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
sfl.Text = ""
|
||||
sfl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
sfl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
sfl.Font = Enum.Font.ArialBold
|
||||
sfl.FontSize = Enum.FontSize.Size14
|
||||
sfl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
sfl.BackgroundTransparency = 1
|
||||
|
||||
--slope factor slider
|
||||
sfSliderGui, sfSliderPosition = RbxGui.CreateSlider(16, 0, UDim2.new(0.3, 0, 0.71, 0))
|
||||
sfSliderGui.Parent = frame
|
||||
sfBar = sfSliderGui:FindFirstChild("Bar")
|
||||
sfBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
sfSliderPosition.Value = s * 10 - 0.4
|
||||
sfSliderPosition.Changed:connect(function()
|
||||
s = sfSliderPosition.Value / 10 + 0.4
|
||||
sfl.Text = "Slope: "..s
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Elevation Plugin Loaded")
|
||||
@@ -0,0 +1,427 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
r = 5
|
||||
d = 0
|
||||
mousedown = false
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Elevation Brush", "brush.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function()
|
||||
onClicked(mouse)
|
||||
end)
|
||||
mouse.Button1Up:connect(function() mousedown = false end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--makes a column of blocks from 1 up to height at location (x,z) in cluster c
|
||||
--if add is true, blocks below height will be added
|
||||
--if clear is true, blocks above height will be cleared
|
||||
function coordHeight(x, z, height, add, clear)
|
||||
c = game.Workspace.Terrain
|
||||
if add then
|
||||
for h = 1, height do
|
||||
c:SetCell(x, h, z, 1, 0, 0)
|
||||
end
|
||||
end
|
||||
if clear then
|
||||
ysize = c.MaxExtents.Max.Y
|
||||
for h = height + 1, ysize - 1 do
|
||||
c:SetCell(x, h, z, 0, 0, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--find height at coordinate x, z
|
||||
function getHeight(x, z)
|
||||
c = game.Workspace.Terrain
|
||||
h = 0
|
||||
material, wedge, rotation = c:GetCell(x, h + 1, z)
|
||||
while material.Value > 0 do
|
||||
h = h + 1
|
||||
material, wedge, rotation = c:GetCell(x, h + 1, z)
|
||||
end
|
||||
return h
|
||||
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, z1, x2, z2), 2) + math.pow(math.abs(y2-y1)*100/d, 2))
|
||||
end
|
||||
|
||||
|
||||
|
||||
--makes a wedge at location x, y, z using info from heightmap instead of GetCell
|
||||
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
|
||||
--returns true if made a wedge, false if the cell remains a block
|
||||
function MakeWedge(x, y, z, heightmap, defaultmaterial)
|
||||
local c = game.Workspace.Terrain
|
||||
--gather info about all the cells around x, y, z
|
||||
local surroundings = {} --surroundings is a 3 x 3 x 3 array of the cells adjacent to x, y, z (1 if a cell is there, 0 if not)
|
||||
for i = x - 1, x + 1 do
|
||||
surroundings[i] = {}
|
||||
for j = y - 1, y + 1 do
|
||||
surroundings[i][j] = {}
|
||||
for k = z - 1, z + 1 do
|
||||
heightmapi = heightmap[i]
|
||||
height = nil
|
||||
if heightmapi then
|
||||
height = heightmapi[k]
|
||||
end
|
||||
if height and height >= j then
|
||||
surroundings[i][j][k] = 1
|
||||
else
|
||||
surroundings[i][j][k] = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--make some useful arrays and counters
|
||||
local sides = {} --sides is an array of the material of the 4 adjacent sides
|
||||
sides[0] = surroundings[x - 1][y][z]
|
||||
sides[1] = surroundings[x][y][z + 1]
|
||||
sides[2] = surroundings[x + 1][y][z]
|
||||
sides[3] = surroundings[x][y][z - 1]
|
||||
local adjacentSides = 0
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
adjacentSides = adjacentSides + 1
|
||||
end
|
||||
end
|
||||
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
|
||||
sidesAbove[0] = surroundings[x - 1][y + 1][z]
|
||||
sidesAbove[1] = surroundings[x][y + 1][z + 1]
|
||||
sidesAbove[2] = surroundings[x + 1][y + 1][z]
|
||||
sidesAbove[3] = surroundings[x][y + 1][z - 1]
|
||||
local adjacentSidesAbove = 0
|
||||
for n = 0, 3 do
|
||||
if sidesAbove[n] > 0 then
|
||||
adjacentSidesAbove = adjacentSidesAbove + 1
|
||||
end
|
||||
end
|
||||
local corners = {} --corners is an array of the material of the 4 adjacent corners
|
||||
corners[0] = surroundings[x - 1][y][z - 1]
|
||||
corners[1] = surroundings[x - 1][y][z + 1]
|
||||
corners[2] = surroundings[x + 1][y][z + 1]
|
||||
corners[3] = surroundings[x + 1][y][z - 1]
|
||||
local adjacentCorners = 0
|
||||
for n = 0, 3 do
|
||||
if corners[n] > 0 then
|
||||
adjacentCorners = adjacentCorners + 1
|
||||
end
|
||||
end
|
||||
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
|
||||
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
|
||||
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
|
||||
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
|
||||
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
|
||||
local adjacentCornersAbove = 0
|
||||
for n = 0, 3 do
|
||||
if cornersAbove[n] > 0 then
|
||||
adjacentCornersAbove = adjacentCornersAbove + 1
|
||||
end
|
||||
end
|
||||
--determine what type of wedge to make
|
||||
local material = nil
|
||||
local wedge = nil
|
||||
local rotation = nil
|
||||
if defaultmaterial then
|
||||
material = defaultmaterial
|
||||
else
|
||||
material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
|
||||
end
|
||||
wedge = 0 --default wedge is a block
|
||||
rotation = 0 --default rotation is 0
|
||||
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
if adjacentSides == 1 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 1) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 3 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
|
||||
wedge = 2
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
|
||||
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
|
||||
if adjacentCorners > 1 then
|
||||
for n = 0, 3 do
|
||||
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 4 and adjacentCorners == 3 then
|
||||
for n = 0, 3 do
|
||||
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
|
||||
if adjacentSides == 2 and adjacentCorners < 4 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
|
||||
wedge = 4
|
||||
rotation = n
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--brushes terrain at point (x, y, z) in cluster c
|
||||
function brush(x, y, z, r, d)
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
for i = x - (r + 3), x + (r + 3) do
|
||||
for k = z - (r + 3), z + (r + 3) do
|
||||
|
||||
if d >= 0 then
|
||||
inc = 1
|
||||
material = 1
|
||||
heightoffset = 0
|
||||
add = true
|
||||
else
|
||||
inc = -1
|
||||
material = 0
|
||||
heightoffset = 1
|
||||
add = false
|
||||
end
|
||||
|
||||
heightmapi = heightmap[i]
|
||||
if heightmapi then
|
||||
heightmapik = heightmapi[k]
|
||||
else
|
||||
heightmap[i] = {}
|
||||
end
|
||||
|
||||
if dist(x, z, i, k) < r then
|
||||
coordHeight(i, k, y + d, add, not add)
|
||||
end
|
||||
|
||||
heightmap[i][k] = getHeight(i, k)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
for ri = 0, r + 2 do
|
||||
i = x - ri
|
||||
for k = z - (r + 2), z + (r + 2) do
|
||||
height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 0, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap, 1) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
i = x + ri
|
||||
for k = z - (r + 2), z + (r + 2) do
|
||||
height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 0, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap, 1) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wait(0)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function onClicked(mouse)
|
||||
if on then
|
||||
|
||||
c = game.Workspace.Terrain
|
||||
heightmap = {}
|
||||
mousedown = true
|
||||
brushheight = nil
|
||||
while mousedown == true do
|
||||
local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
if brushheight == nil then
|
||||
brushheight = y
|
||||
end
|
||||
brush(x, brushheight, z, r, d)
|
||||
print("Brushed at: "..x..", "..brushheight..", "..z)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
frame.Visible = true
|
||||
for w = 0, 0.3, 0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
radl.Text = "Radius: "..r
|
||||
dfl.Text = "Height: "..d
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
radl.Text = ""
|
||||
dfl.Text = ""
|
||||
for w = 0.3, 0, -0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
frame.Visible = false
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Position = UDim2.new(0.35, 0, 0.8, 0)
|
||||
frame.Size = UDim2.new(0.3, 0, 0.15, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
|
||||
--current radius display label
|
||||
radl = Instance.new("TextLabel", frame)
|
||||
radl.Position = UDim2.new(0.05, 0, 0.1, 0)
|
||||
radl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
radl.Text = ""
|
||||
radl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
radl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
radl.Font = Enum.Font.ArialBold
|
||||
radl.FontSize = Enum.FontSize.Size14
|
||||
radl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
radl.BackgroundTransparency = 1
|
||||
|
||||
--radius slider
|
||||
radSliderGui, radSliderPosition = RbxGui.CreateSlider(5, 0, UDim2.new(0.3, 0, 0.26, 0))
|
||||
radSliderGui.Parent = frame
|
||||
radBar = radSliderGui:FindFirstChild("Bar")
|
||||
radBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
radSliderPosition.Value = r - 1
|
||||
radSliderPosition.Changed:connect(function()
|
||||
r = radSliderPosition.Value + 1
|
||||
radl.Text = "Radius: "..r
|
||||
end)
|
||||
|
||||
--current depth factor display label
|
||||
dfl = Instance.new("TextLabel", frame)
|
||||
dfl.Position = UDim2.new(0.05, 0, 0.55, 0)
|
||||
dfl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
dfl.Text = ""
|
||||
dfl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
dfl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
dfl.Font = Enum.Font.ArialBold
|
||||
dfl.FontSize = Enum.FontSize.Size14
|
||||
dfl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
dfl.BackgroundTransparency = 1
|
||||
|
||||
--depth factor slider
|
||||
dfSliderGui, dfSliderPosition = RbxGui.CreateSlider(61, 0, UDim2.new(0.3, 0, 0.71, 0))
|
||||
dfSliderGui.Parent = frame
|
||||
dfBar = dfSliderGui:FindFirstChild("Bar")
|
||||
dfBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
dfSliderPosition.Value = d + 31
|
||||
dfSliderPosition.Changed:connect(function()
|
||||
d = dfSliderPosition.Value - 31
|
||||
dfl.Text = "Height: "..d
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Elevation Plugin Loaded")
|
||||
@@ -0,0 +1,131 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Plateau", "plateaus.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--makes a plateau starting at point (x, y, z)
|
||||
function makePlateau(x, y, z)
|
||||
c = game.Workspace.Terrain
|
||||
q = {}
|
||||
index = 0
|
||||
q[index] = x
|
||||
q[index+1] = y
|
||||
q[index+2] = z
|
||||
insertindex = 3
|
||||
c:SetCell(q[index], q[index+1], q[index+2], 0, 0, 0)
|
||||
while q[index] do
|
||||
|
||||
insertindex = plateauHelper(insertindex, 0, 1, 0)
|
||||
insertindex = plateauHelper(insertindex, -1, 0, -1)
|
||||
insertindex = plateauHelper(insertindex, -1, 0, 0)
|
||||
insertindex = plateauHelper(insertindex, -1, 0, 1)
|
||||
insertindex = plateauHelper(insertindex, 0, 0, -1)
|
||||
insertindex = plateauHelper(insertindex, 0, 0, 1)
|
||||
insertindex = plateauHelper(insertindex, 1, 0, -1)
|
||||
insertindex = plateauHelper(insertindex, 1, 0, 0)
|
||||
insertindex = plateauHelper(insertindex, 1, 0, 1)
|
||||
|
||||
q[index] = nil
|
||||
q[index + 1] = nil
|
||||
q[index + 2] = nil
|
||||
index = index + 3
|
||||
if index % 1000 == 0 then
|
||||
wait()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function plateauHelper(insertindex, xoffset, yoffset, zoffset)
|
||||
material, wedge, rotation = c:GetCell(q[index] + xoffset, q[index+1] + yoffset, q[index+2] + zoffset)
|
||||
if material.Value > 0 then
|
||||
q[insertindex] = q[index] + xoffset
|
||||
q[insertindex+1] = q[index+1] + yoffset
|
||||
q[insertindex+2] = q[index+2] + zoffset
|
||||
c:SetCell(q[index] + xoffset, q[index+1] + yoffset, q[index+2] + zoffset, 0, 0, 0)
|
||||
insertindex = insertindex + 3
|
||||
end
|
||||
return insertindex
|
||||
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
|
||||
|
||||
function onClicked(mouse)
|
||||
if on then
|
||||
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
print("Plateau formed at: "..x..", "..y..", "..z)
|
||||
makePlateau(x, y, z)
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Plateaus Plugin Loaded")
|
||||
@@ -0,0 +1,386 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
r = 20
|
||||
d = 20
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Crater", "craters.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--makes a wedge at location x, y, z using info from heightmap instead of GetCell
|
||||
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
|
||||
--returns true if made a wedge, false if the cell remains a block
|
||||
function MakeWedge(x, y, z, heightmap, defaultmaterial)
|
||||
local c = game.Workspace.Terrain
|
||||
--gather info about all the cells around x, y, z
|
||||
|
||||
|
||||
local surroundings = {} --surroundings is a 3 x 3 x 3 array of the cells adjacent to x, y, z (1 if a cell is there, 0 if not)
|
||||
for i = x - 1, x + 1 do
|
||||
surroundings[i] = {}
|
||||
for j = y - 1, y + 1 do
|
||||
surroundings[i][j] = {}
|
||||
for k = z - 1, z + 1 do
|
||||
heightmapi = heightmap[i]
|
||||
height = nil
|
||||
if heightmapi then
|
||||
height = heightmapi[k]
|
||||
end
|
||||
if height then
|
||||
if height >= j then
|
||||
surroundings[i][j][k] = 1
|
||||
else
|
||||
surroundings[i][j][k] = 0
|
||||
end
|
||||
else -- need to get info from cell when our heightmap doesn't exist there! [otherwise, we can get holes through the terrain]
|
||||
local material, wedge, rotation = c:GetCell(i, j, k)
|
||||
surroundings[i][j][k] = material.Value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--make some useful arrays and counters
|
||||
local sides = {} --sides is an array of the material of the 4 adjacent sides
|
||||
sides[0] = surroundings[x - 1][y][z]
|
||||
sides[1] = surroundings[x][y][z + 1]
|
||||
sides[2] = surroundings[x + 1][y][z]
|
||||
sides[3] = surroundings[x][y][z - 1]
|
||||
local adjacentSides = 0
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
adjacentSides = adjacentSides + 1
|
||||
end
|
||||
end
|
||||
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
|
||||
sidesAbove[0] = surroundings[x - 1][y + 1][z]
|
||||
sidesAbove[1] = surroundings[x][y + 1][z + 1]
|
||||
sidesAbove[2] = surroundings[x + 1][y + 1][z]
|
||||
sidesAbove[3] = surroundings[x][y + 1][z - 1]
|
||||
local adjacentSidesAbove = 0
|
||||
for n = 0, 3 do
|
||||
if sidesAbove[n] > 0 then
|
||||
adjacentSidesAbove = adjacentSidesAbove + 1
|
||||
end
|
||||
end
|
||||
local corners = {} --corners is an array of the material of the 4 adjacent corners
|
||||
corners[0] = surroundings[x - 1][y][z - 1]
|
||||
corners[1] = surroundings[x - 1][y][z + 1]
|
||||
corners[2] = surroundings[x + 1][y][z + 1]
|
||||
corners[3] = surroundings[x + 1][y][z - 1]
|
||||
local adjacentCorners = 0
|
||||
for n = 0, 3 do
|
||||
if corners[n] > 0 then
|
||||
adjacentCorners = adjacentCorners + 1
|
||||
end
|
||||
end
|
||||
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
|
||||
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
|
||||
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
|
||||
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
|
||||
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
|
||||
local adjacentCornersAbove = 0
|
||||
for n = 0, 3 do
|
||||
if cornersAbove[n] > 0 then
|
||||
adjacentCornersAbove = adjacentCornersAbove + 1
|
||||
end
|
||||
end
|
||||
--determine what type of wedge to make
|
||||
local material = nil
|
||||
local wedge = nil
|
||||
local rotation = nil
|
||||
if defaultmaterial then
|
||||
material = defaultmaterial
|
||||
else
|
||||
material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
|
||||
end
|
||||
wedge = 0 --default wedge is a block
|
||||
rotation = 0 --default rotation is 0
|
||||
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
if adjacentSides == 1 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 1) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 3 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
|
||||
wedge = 2
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
|
||||
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
|
||||
if adjacentCorners > 1 then
|
||||
for n = 0, 3 do
|
||||
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 4 and adjacentCorners == 3 then
|
||||
for n = 0, 3 do
|
||||
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
|
||||
if adjacentSides == 2 and adjacentCorners < 4 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
|
||||
wedge = 4
|
||||
rotation = n
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--makes a crater at point (x, y, z) in cluster c
|
||||
--d is the depth factor, a percent of the depth of a perfect sphere
|
||||
function makeCrater(x, y, z, r, d)
|
||||
c = game.Workspace.Terrain
|
||||
local heightmap = {}
|
||||
for i = x - (r + 1), x + (r + 1) do
|
||||
heightmap[i] = {}
|
||||
end
|
||||
|
||||
for j = 0, r + 1 do
|
||||
local cellschanged = false
|
||||
for i = x - (r + 1), x + (r + 1) do
|
||||
for k = z - (r + 1), z + (r + 1) do
|
||||
distance = math.sqrt(math.pow(dist(x, z, i, k), 2) + math.pow(y - (y - j*(100/d)), 2))
|
||||
if distance < r then
|
||||
c:SetCell(i, y + j, k, 0, 0, 0)
|
||||
c:SetCell(i, y - j, k, 0, 0, 0)
|
||||
cellschanged = true
|
||||
elseif heightmap[i] and heightmap[i][k] == nil then
|
||||
material, wedge, rotation = c:GetCell(i, y - j, k)
|
||||
if material.Value > 0 then
|
||||
heightmap[i][k] = y - j
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if cellschanged == false then
|
||||
break
|
||||
end
|
||||
wait(0)
|
||||
end
|
||||
|
||||
for ri = 0, r do
|
||||
wait(0)
|
||||
|
||||
i = x - ri
|
||||
for k = z - r, z + r do
|
||||
height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 0, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap, nil) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
i = x + ri
|
||||
for k = z - r, z + r do
|
||||
height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 0, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap, nil) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function dist(x1, y1, x2, y2)
|
||||
return math.sqrt(math.pow(x2-x1, 2) + math.pow(y2-y1, 2))
|
||||
end
|
||||
|
||||
local debounce = false
|
||||
function onClicked(mouse)
|
||||
if on and not debounce then
|
||||
debounce = true
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
makeCrater(x, y, z, r, d)
|
||||
|
||||
print("Crater formed at: "..x..", "..y..", "..z)
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
frame.Visible = true
|
||||
for w = 0, 0.3, 0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0)
|
||||
end
|
||||
radl.Text = "Radius: "..r
|
||||
dfl.Text = "Depth: "..d.."%"
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
radl.Text = ""
|
||||
dfl.Text = ""
|
||||
for w = 0.3, 0, -0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0)
|
||||
end
|
||||
frame.Visible = false
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Position = UDim2.new(0.35, 0, 0.8, 0)
|
||||
frame.Size = UDim2.new(0.3, 0, 0.15, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
|
||||
--current radius display label
|
||||
radl = Instance.new("TextLabel", frame)
|
||||
radl.Position = UDim2.new(0.05, 0, 0.1, 0)
|
||||
radl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
radl.Text = ""
|
||||
radl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
radl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
radl.Font = Enum.Font.ArialBold
|
||||
radl.FontSize = Enum.FontSize.Size14
|
||||
radl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
radl.BackgroundTransparency = 1
|
||||
|
||||
--radius slider
|
||||
radSliderGui, radSliderPosition = RbxGui.CreateSlider(128, 0, UDim2.new(0.3, 0, 0.26, 0))
|
||||
radSliderGui.Parent = frame
|
||||
radBar = radSliderGui:FindFirstChild("Bar")
|
||||
radBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
radSliderPosition.Value = r
|
||||
radSliderPosition.Changed:connect(function()
|
||||
r = radSliderPosition.Value
|
||||
radl.Text = "Radius: "..r
|
||||
end)
|
||||
|
||||
--current depth factor display label
|
||||
dfl = Instance.new("TextLabel", frame)
|
||||
dfl.Position = UDim2.new(0.05, 0, 0.55, 0)
|
||||
dfl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
dfl.Text = ""
|
||||
dfl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
dfl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
dfl.Font = Enum.Font.ArialBold
|
||||
dfl.FontSize = Enum.FontSize.Size14
|
||||
dfl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
dfl.BackgroundTransparency = 1
|
||||
|
||||
--depth factor slider
|
||||
dfSliderGui, dfSliderPosition = RbxGui.CreateSlider(100, 0, UDim2.new(0.3, 0, 0.71, 0))
|
||||
dfSliderGui.Parent = frame
|
||||
dfBar = dfSliderGui:FindFirstChild("Bar")
|
||||
dfBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
dfSliderPosition.Value = d
|
||||
dfSliderPosition.Changed:connect(function()
|
||||
d = dfSliderPosition.Value
|
||||
dfl.Text = "Depth: "..d.."%"
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Craters Plugin Loaded")
|
||||
@@ -0,0 +1,383 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
r = 20
|
||||
d = 50
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Orb", "orbs.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--find height at coordinate x, z
|
||||
function getHeight(x, z)
|
||||
c = game.Workspace.Terrain
|
||||
h = 0
|
||||
material, wedge, rotation = c:GetCell(x, h + 1, z)
|
||||
while material.Value > 0 do
|
||||
h = h + 1
|
||||
material, wedge, rotation = c:GetCell(x, h + 1, z)
|
||||
end
|
||||
return h
|
||||
end
|
||||
|
||||
--makes a wedge at location x, y, z using info from heightmap instead of GetCell
|
||||
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
|
||||
--returns true if made a wedge, false if the cell remains a block
|
||||
function MakeWedge(x, y, z, heightmap, defaultmaterial)
|
||||
local c = game.Workspace.Terrain
|
||||
--gather info about all the cells around x, y, z
|
||||
local surroundings = {} --surroundings is a 3 x 3 x 3 array of the cells adjacent to x, y, z (1 if a cell is there, 0 if not)
|
||||
for i = x - 1, x + 1 do
|
||||
surroundings[i] = {}
|
||||
for j = y - 1, y + 1 do
|
||||
surroundings[i][j] = {}
|
||||
for k = z - 1, z + 1 do
|
||||
heightmapi = heightmap[i]
|
||||
height = nil
|
||||
if heightmapi then
|
||||
height = heightmapi[k]
|
||||
end
|
||||
if height and height >= j then
|
||||
surroundings[i][j][k] = 1
|
||||
else
|
||||
surroundings[i][j][k] = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--make some useful arrays and counters
|
||||
local sides = {} --sides is an array of the material of the 4 adjacent sides
|
||||
sides[0] = surroundings[x - 1][y][z]
|
||||
sides[1] = surroundings[x][y][z + 1]
|
||||
sides[2] = surroundings[x + 1][y][z]
|
||||
sides[3] = surroundings[x][y][z - 1]
|
||||
local adjacentSides = 0
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
adjacentSides = adjacentSides + 1
|
||||
end
|
||||
end
|
||||
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
|
||||
sidesAbove[0] = surroundings[x - 1][y + 1][z]
|
||||
sidesAbove[1] = surroundings[x][y + 1][z + 1]
|
||||
sidesAbove[2] = surroundings[x + 1][y + 1][z]
|
||||
sidesAbove[3] = surroundings[x][y + 1][z - 1]
|
||||
local adjacentSidesAbove = 0
|
||||
for n = 0, 3 do
|
||||
if sidesAbove[n] > 0 then
|
||||
adjacentSidesAbove = adjacentSidesAbove + 1
|
||||
end
|
||||
end
|
||||
local corners = {} --corners is an array of the material of the 4 adjacent corners
|
||||
corners[0] = surroundings[x - 1][y][z - 1]
|
||||
corners[1] = surroundings[x - 1][y][z + 1]
|
||||
corners[2] = surroundings[x + 1][y][z + 1]
|
||||
corners[3] = surroundings[x + 1][y][z - 1]
|
||||
local adjacentCorners = 0
|
||||
for n = 0, 3 do
|
||||
if corners[n] > 0 then
|
||||
adjacentCorners = adjacentCorners + 1
|
||||
end
|
||||
end
|
||||
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
|
||||
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
|
||||
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
|
||||
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
|
||||
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
|
||||
local adjacentCornersAbove = 0
|
||||
for n = 0, 3 do
|
||||
if cornersAbove[n] > 0 then
|
||||
adjacentCornersAbove = adjacentCornersAbove + 1
|
||||
end
|
||||
end
|
||||
--determine what type of wedge to make
|
||||
local material = nil
|
||||
local wedge = nil
|
||||
local rotation = nil
|
||||
if defaultmaterial then
|
||||
material = defaultmaterial
|
||||
else
|
||||
material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
|
||||
end
|
||||
wedge = 0 --default wedge is a block
|
||||
rotation = 0 --default rotation is 0
|
||||
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
if adjacentSides == 1 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 1) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 3 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
|
||||
wedge = 1
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
|
||||
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
|
||||
wedge = 2
|
||||
rotation = (n + 2) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
|
||||
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
|
||||
if adjacentCorners > 1 then
|
||||
for n = 0, 3 do
|
||||
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif adjacentSides == 4 and adjacentCorners == 3 then
|
||||
for n = 0, 3 do
|
||||
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
|
||||
wedge = 3
|
||||
rotation = (n + 3) % 4
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
|
||||
if adjacentSides == 2 and adjacentCorners < 4 then
|
||||
for n = 0, 3 do
|
||||
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
|
||||
wedge = 4
|
||||
rotation = n
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
c:SetCell(x, y, z, material, wedge, rotation)
|
||||
return false
|
||||
end
|
||||
|
||||
--makes an orb at point (x, y, z) in cluster c
|
||||
--d is the depth factor, a percent of the depth of a perfect sphere
|
||||
function makeBall(x, y, z, r, d)
|
||||
c = game.Workspace.Terrain
|
||||
local heightmap = {}
|
||||
for i = x - (r + 1), x + (r + 1) do
|
||||
heightmap[i] = {}
|
||||
end
|
||||
|
||||
for j = 0, r + 1 do
|
||||
local cellschanged = false
|
||||
for i = x - (r + 1), x + (r + 1) do
|
||||
for k = z - (r + 1), z + (r + 1) do
|
||||
distance = math.sqrt(math.pow(dist(x, z, i, k), 2) + math.pow(j*(100/d), 2))
|
||||
if distance < r then
|
||||
c:SetCell(i, y - j, k, 1, 0, 1)
|
||||
c:SetCell(i, y + j, k, 1, 0, 1)
|
||||
cellschanged = true
|
||||
heightmap[i][k] = y + j
|
||||
elseif heightmap[i][k] == nil then
|
||||
heightmap[i][k] = getHeight(i, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
if cellschanged == false then
|
||||
break
|
||||
end
|
||||
wait(0)
|
||||
end
|
||||
|
||||
for ri = 0, r do
|
||||
wait(0)
|
||||
|
||||
i = x - ri
|
||||
for k = z - r, z + r do
|
||||
height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 0, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
i = x + ri
|
||||
for k = z - r, z + r do
|
||||
height = heightmap[i][k]
|
||||
if height == nil then
|
||||
height = -1
|
||||
end
|
||||
for h = height, 0, -1 do
|
||||
if not MakeWedge(i, h, k, heightmap) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function dist(x1, y1, x2, y2)
|
||||
return math.sqrt(math.pow(x2-x1, 2) + math.pow(y2-y1, 2))
|
||||
end
|
||||
|
||||
local debounce = false
|
||||
function onClicked(mouse)
|
||||
if on and not debounce then
|
||||
debounce = true
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
local cellPos = c:WorldToCellPreferEmpty(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
makeBall(x, y, z, r, d)
|
||||
print("Orb created at: "..x..", "..y..", "..z)
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
frame.Visible = true
|
||||
for w = 0, 0.3, 0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0)
|
||||
end
|
||||
radl.Text = "Radius: "..r
|
||||
dfl.Text = "Height: "..d.."%"
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
radl.Text = ""
|
||||
dfl.Text = ""
|
||||
for w = 0.3, 0, -0.06 do
|
||||
frame.Size = UDim2.new(w, 0, w/2, 0)
|
||||
wait(0)
|
||||
end
|
||||
frame.Visible = false
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Position = UDim2.new(0.35, 0, 0.8, 0)
|
||||
frame.Size = UDim2.new(0.3, 0, 0.15, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
|
||||
--current radius display label
|
||||
radl = Instance.new("TextLabel", frame)
|
||||
radl.Position = UDim2.new(0.05, 0, 0.1, 0)
|
||||
radl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
radl.Text = ""
|
||||
radl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
radl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
radl.Font = Enum.Font.ArialBold
|
||||
radl.FontSize = Enum.FontSize.Size14
|
||||
radl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
radl.BackgroundTransparency = 1
|
||||
|
||||
--radius slider
|
||||
radSliderGui, radSliderPosition = RbxGui.CreateSlider(128, 0, UDim2.new(0.3, 0, 0.26, 0))
|
||||
radSliderGui.Parent = frame
|
||||
radBar = radSliderGui:FindFirstChild("Bar")
|
||||
radBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
radSliderPosition.Value = r
|
||||
radSliderPosition.Changed:connect(function()
|
||||
r = radSliderPosition.Value
|
||||
radl.Text = "Radius: "..r
|
||||
end)
|
||||
|
||||
--current depth factor display label
|
||||
dfl = Instance.new("TextLabel", frame)
|
||||
dfl.Position = UDim2.new(0.05, 0, 0.55, 0)
|
||||
dfl.Size = UDim2.new(0.2, 0, 0.35, 0)
|
||||
dfl.Text = ""
|
||||
dfl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
dfl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
dfl.Font = Enum.Font.ArialBold
|
||||
dfl.FontSize = Enum.FontSize.Size14
|
||||
dfl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
dfl.BackgroundTransparency = 1
|
||||
|
||||
--depth factor slider
|
||||
dfSliderGui, dfSliderPosition = RbxGui.CreateSlider(100, 0, UDim2.new(0.3, 0, 0.71, 0))
|
||||
dfSliderGui.Parent = frame
|
||||
dfBar = dfSliderGui:FindFirstChild("Bar")
|
||||
dfBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
dfSliderPosition.Value = d
|
||||
dfSliderPosition.Changed:connect(function()
|
||||
d = dfSliderPosition.Value
|
||||
dfl.Text = "Height: "..d.."%"
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Orbs Plugin Loaded")
|
||||
@@ -0,0 +1,202 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
x1 = 200
|
||||
y1 = 200
|
||||
x2 = 300
|
||||
y2 = 300
|
||||
h = 20
|
||||
on = false
|
||||
mode = 0
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Roads: Click once to set the starting point and again to set the endpoint of the road.", "roads.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
--makes a column of blocks from 0 up to height at location (x,z) in cluster c
|
||||
function coordHeight(x, z, height)
|
||||
c = game.Workspace.Terrain
|
||||
for h = 1, height do
|
||||
c:SetCell(x, h, z, 1, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function coordCheck(x, z, height)
|
||||
c = game.Workspace.Terrain
|
||||
for h = height, 0, -1 do
|
||||
material, wedge, rotation = c:GetCell(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)
|
||||
c = game.Workspace.Terrain
|
||||
if x2 < x1 then
|
||||
incx = -1
|
||||
n = 1
|
||||
else
|
||||
incx = 1
|
||||
n = -1
|
||||
end
|
||||
for x = x1, x2+n, incx do
|
||||
c:SetCell(x, h+1, z1, 0, 0, 0)
|
||||
c:SetCell(x, h+1, z1-1, 0, 0, 0)
|
||||
c:SetCell(x, h+1, z1+1, 0, 0, 0)
|
||||
c:SetCell(x, h+2, z1, 0, 0, 0)
|
||||
c:SetCell(x, h+2, z1-1, 0, 0, 0)
|
||||
c:SetCell(x, h+2, z1+1, 0, 0, 0)
|
||||
c:SetCell(x, h+3, z1, 0, 0, 0)
|
||||
c:SetCell(x, h+3, z1-1, 0, 0, 0)
|
||||
c:SetCell(x, h+3, z1+1, 0, 0, 0)
|
||||
c:SetCell(x, h, z1, 1, 0, 0)
|
||||
c:SetCell(x, h, z1-1, 1, 0, 0)
|
||||
c:SetCell(x, h, z1+1, 1, 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
|
||||
c:SetCell(x2, h+1, z, 0, 0, 0)
|
||||
c:SetCell(x2-1, h+1, z, 0, 0, 0)
|
||||
c:SetCell(x2+1, h+1, z, 0, 0, 0)
|
||||
c:SetCell(x2, h+2, z, 0, 0, 0)
|
||||
c:SetCell(x2-1, h+2, z, 0, 0, 0)
|
||||
c:SetCell(x2+1, h+2, z, 0, 0, 0)
|
||||
c:SetCell(x2, h+3, z, 0, 0, 0)
|
||||
c:SetCell(x2-1, h+3, z, 0, 0, 0)
|
||||
c:SetCell(x2+1, h+3, z, 0, 0, 0)
|
||||
c:SetCell(x2, h, z, 1, 0, 0)
|
||||
c:SetCell(x2-1, h, z, 1, 0, 0)
|
||||
c:SetCell(x2+1, h, z, 1, 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
|
||||
end
|
||||
|
||||
function onClicked (mouse)
|
||||
if on then
|
||||
|
||||
c = game.Workspace.Terrain
|
||||
|
||||
local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
local x = cellPos.x
|
||||
local y = cellPos.y
|
||||
local z = cellPos.z
|
||||
|
||||
if mode == 0 then
|
||||
x1 = x
|
||||
y1 = z
|
||||
h = y
|
||||
mode = 1
|
||||
elseif mode == 1 then
|
||||
x2 = x
|
||||
y2 = z
|
||||
makePath(x1, y1, x2, y2, h, true, c)
|
||||
mode = 0
|
||||
else
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
mode = 0
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Roads Plugin Loaded")
|
||||
@@ -0,0 +1,204 @@
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
|
||||
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() onClicked(mouse) end)
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Tree", "trees.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
local Base = Instance.new("Part")
|
||||
Base.Name = "Trunk"
|
||||
Base.formFactor = "Custom"
|
||||
Base.TopSurface = 0
|
||||
Base.BottomSurface = 0
|
||||
Base.Anchored = false
|
||||
Base.BrickColor = BrickColor.new("Reddish brown")
|
||||
local Leaves = Base:Clone()
|
||||
Leaves.Name = "Leaves"
|
||||
Leaves.CanCollide = false
|
||||
Leaves.BrickColor = BrickColor.new("Dark green")
|
||||
local leafmesh = Instance.new("SpecialMesh")
|
||||
leafmesh.MeshType = "FileMesh"
|
||||
leafmesh.MeshId = "http://www.watrbx.wtf/asset/?id=1290033"
|
||||
leafmesh.TextureId = "http://www.watrbx.wtf/asset/?id=2861779"
|
||||
leafmesh.Parent = Leaves
|
||||
Instance.new("CylinderMesh",Base)
|
||||
|
||||
|
||||
-- get dot product of yz angles
|
||||
function dot(c1,c2)
|
||||
local m = CFrame.Angles(math.pi/2,0,0)
|
||||
return (c1*m).lookVector:Dot((c2*m).lookVector)
|
||||
end
|
||||
|
||||
-- multiplier for various sizes of foliage
|
||||
local leaf_mult = {
|
||||
Vector3.new(1.5,1.5,1.2);
|
||||
Vector3.new(1.5,1,1.5);
|
||||
Vector3.new(1.2,1.5,1.5);
|
||||
Vector3.new(1.5,1.5,1.5);
|
||||
}
|
||||
|
||||
function Welder(p0, p1)
|
||||
local w = Instance.new("Weld")
|
||||
w.Part0 = p0
|
||||
w.Part1 = p1
|
||||
local CJ = CFrame.new(p0.Position)
|
||||
w.C0 = p0.CFrame:inverse() * CJ
|
||||
w.C1 = p1.CFrame:inverse() * CJ
|
||||
w.Parent = p0
|
||||
end
|
||||
|
||||
function Branch(base,c)
|
||||
if c <= 0 then
|
||||
-- if the complexity has run out, generate some foliage
|
||||
local leaves = Leaves:Clone()
|
||||
local vol = base.Size.x+base.Size.y+base.Size.z -- determine size based on branch size
|
||||
leaves.Mesh.Scale = leaf_mult[math.random(1,#leaf_mult)]*math.random(vol/3*10,vol/3*12)/10
|
||||
leaves.Size = leaves.Mesh.Scale*0.75
|
||||
leaves.CFrame = base.CFrame * CFrame.new(0,base.Size.y/2,0) -- center foliage at top of branch
|
||||
leaves.Parent = base.Parent
|
||||
Welder(leaves, base)
|
||||
else
|
||||
-- otherwise, make some more branches
|
||||
local pos = base.CFrame*CFrame.new(0,base.Size/2,0)
|
||||
local height = base.Size.y
|
||||
local width = base.Size.x
|
||||
local nb = math.random(2,2) -- # of possible branches (2 seems to work fine for now)
|
||||
local r = math.random(45,135) -- rotation of branches on y axis
|
||||
|
||||
-- branch split angle difference
|
||||
-- the less complexity, the greater the possible angle
|
||||
-- minimum: 20-75; maximum: 40-80
|
||||
local da = math.random(20+55/c,40+40/c)
|
||||
|
||||
-- branch angle (overall angle of all branches)
|
||||
local ba = math.random(-da/3,da/3)
|
||||
|
||||
-- ba+da/2 shouldn't be near or greater than 90 degrees
|
||||
|
||||
for i=0,nb-1 do -- for each branch
|
||||
local branch = base:Clone()
|
||||
branch.Name = "Branch"
|
||||
local h = height*math.random(95,115)/100 -- height .95 to 1.15 of original
|
||||
|
||||
-- make new cframe
|
||||
-- move new to top of base, then apply branch angle (ba)
|
||||
local new = branch.CFrame * CFrame.new(0,height/2,0) * CFrame.Angles(0,0,math.rad(ba))
|
||||
-- next, rotate branch so that it faces away from others, also apply overall rotation (r)
|
||||
-- also, apply the split angle (da)
|
||||
-- finally, move branch upward by half it's size
|
||||
new = new * CFrame.Angles(0,i*(math.pi*2/nb)+r,math.rad(da/2)) * CFrame.new(0,h/2,0)
|
||||
|
||||
-- determine width by branch's final angle; greater the angle, smaller the width
|
||||
-- also shave off a bit of width for more dramatic change in size
|
||||
-- a frustum cone mesh would really help here
|
||||
local w = dot(new,branch.CFrame)*width*0.9
|
||||
|
||||
branch.Size = Vector3.new(w,h,w)
|
||||
branch.CFrame = new
|
||||
branch.Parent = base.Parent
|
||||
Welder(branch, base)
|
||||
|
||||
-- create the next set of branches with one less complexity
|
||||
Branch(branch,c-1)
|
||||
end
|
||||
end
|
||||
--wait() -- remove to generate faster
|
||||
end
|
||||
|
||||
-- Main Function ----------------
|
||||
function GenerateTree(location,complexity,width,height)
|
||||
--[[
|
||||
location: position tree will "sprout" out of
|
||||
complexity: # of times to branch out
|
||||
determines overall size and quality of tree
|
||||
produces between m^c+(m^(c+1)-1)/(m-1) parts,
|
||||
where c is complexity,
|
||||
and m is either the min or max # of possible branches
|
||||
(currently, both min and max are 2)
|
||||
width: initial x/z size of tree base
|
||||
determines overall thickness of tree
|
||||
height: initial y size of tree base
|
||||
contributes to sparseness of tree
|
||||
]]
|
||||
print("TreeGen - complexity: " .. complexity .. ", width: " .. width .. ", height: " .. height)
|
||||
local tree = Instance.new("Model")
|
||||
tree.Name = "Tree"
|
||||
tree.Parent = workspace
|
||||
local base = Base:Clone()
|
||||
base.Parent = tree
|
||||
base.Size = Vector3.new(width,height,width)
|
||||
-- move up by half its height, and rotate randomly
|
||||
base.CFrame = CFrame.new(location) * CFrame.new(0,height/2,0) * CFrame.Angles(0,math.rad(math.random(1,360)),0)
|
||||
leafmesh.VertexColor = Vector3.new((math.random() * .1) + .9, (math.random() * .4) + .6, 1)
|
||||
-- start branching
|
||||
Branch(base,complexity)
|
||||
return base
|
||||
end
|
||||
|
||||
|
||||
function onClicked(mouse)
|
||||
if on then
|
||||
local targetPart = mouse.Target
|
||||
local newTrunk = GenerateTree(mouse.Hit.p, math.random(3,6), math.random(2,4), math.random(5,10))
|
||||
|
||||
if targetPart and targetPart:IsA("Terrain") then Welder(newTrunk, targetPart) end -- make trees stick to terrain
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Tree Plugin Loaded")
|
||||
@@ -0,0 +1,836 @@
|
||||
-- Local function definitions
|
||||
local c = game.Workspace.Terrain
|
||||
local SetCell = c.SetCell
|
||||
local GetCell = c.GetCell
|
||||
local WorldToCellPreferSolid = c.WorldToCellPreferSolid
|
||||
local CellCornerToWorld = c.CellCornerToWorld
|
||||
local WorldToCell = c.WorldToCell
|
||||
local AutoWedge = c.AutowedgeCells
|
||||
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
materialNames = {"Empty", "Grass", "Sand", "Granite", "Brick"}
|
||||
local currentMaterial = 1
|
||||
|
||||
local debounce = false
|
||||
local startCell = nil
|
||||
local endCell = nil
|
||||
local regionSelected = false
|
||||
local dragging = false
|
||||
local cloning = false
|
||||
local cloneHitCell = nil
|
||||
local boxSize = Vector3.new(0, 0, 0)
|
||||
|
||||
-- for region resizing
|
||||
local handles = Instance.new("Handles")
|
||||
local handlesWereDragged = false
|
||||
local dragStartX = 0
|
||||
local dragStartY = 0
|
||||
local dragStartZ = 0
|
||||
local dragEndX = 0
|
||||
local dragEndY = 0
|
||||
local dragEndZ = 0
|
||||
|
||||
|
||||
|
||||
local selectionBox = Instance.new("Part")
|
||||
selectionBox.Anchored = true
|
||||
selectionBox.CanCollide = false
|
||||
selectionBox.formFactor = "Custom"
|
||||
selectionBox.BottomSurface = "Smooth"
|
||||
selectionBox.TopSurface = "Smooth"
|
||||
selectionBox.BrickColor = BrickColor.new("Bright blue")
|
||||
selectionBox.Transparency = .7
|
||||
|
||||
local selectionLasso = Instance.new("SelectionBox")
|
||||
selectionLasso.Adornee = selectionBox
|
||||
|
||||
local cloneBox = Instance.new("Part")
|
||||
cloneBox.Anchored = true
|
||||
cloneBox.CanCollide = false
|
||||
cloneBox.formFactor = "Custom"
|
||||
cloneBox.BottomSurface = "Smooth"
|
||||
cloneBox.TopSurface = "Smooth"
|
||||
cloneBox.BrickColor = BrickColor.new("Deep orange")
|
||||
cloneBox.Transparency = .5
|
||||
|
||||
local cloneLasso = Instance.new("SelectionBox")
|
||||
cloneLasso.Color = BrickColor.new("Deep orange")
|
||||
cloneLasso.Adornee = cloneBox
|
||||
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() mouseDown(mouse) end)
|
||||
mouse.Button1Up:connect(function() mouseUp(mouse) end)
|
||||
mouse.Move:connect(function() mouseMove(mouse) end)
|
||||
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "RegionEdit", "")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
function putCloneDown()
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
centerX = math.floor((startX + endX)/2)
|
||||
centerY = math.floor((startY + endY)/2)
|
||||
centerZ = math.floor((startZ + endZ)/2)
|
||||
|
||||
xOffset = cloneHitCell.x - centerX
|
||||
yOffset = cloneHitCell.y - centerY
|
||||
zOffset = cloneHitCell.z - centerZ
|
||||
|
||||
xStep = 1
|
||||
yStep = 1
|
||||
zStep = 1
|
||||
|
||||
if xOffset > 0 then
|
||||
-- go backwards on x axis
|
||||
tempVal = startX
|
||||
startX = endX
|
||||
endX = tempVal
|
||||
|
||||
xStep = -1
|
||||
end
|
||||
if yOffset > 0 then
|
||||
-- go backwards on y axis
|
||||
tempVal = startY
|
||||
startY = endY
|
||||
endY = tempVal
|
||||
|
||||
yStep = -1
|
||||
end
|
||||
if zOffset > 0 then
|
||||
-- go backwards on z axis
|
||||
tempVal = startZ
|
||||
startZ = endZ
|
||||
endZ = tempVal
|
||||
|
||||
zStep = -1
|
||||
end
|
||||
|
||||
local count = 0
|
||||
for x = startX, endX, xStep do
|
||||
for y = startY, endY, yStep do
|
||||
for z = startZ, endZ, zStep do
|
||||
local mat, typ, orient = GetCell(c, x, y, z)
|
||||
SetCell(c, x+xOffset, y+yOffset, z+zOffset, mat, typ, orient)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if count > 10000 then count = 0 wait() end
|
||||
end
|
||||
|
||||
-- switch the selected region to the new one :)
|
||||
startCell = Vector3.new(startX+xOffset, startY+yOffset, startZ+zOffset)
|
||||
endCell = Vector3.new(endX+xOffset, endY+yOffset, endZ+zOffset)
|
||||
|
||||
-- make the clone button look deselected now, if it's not
|
||||
if clone then
|
||||
clone.BorderColor3 = Color3.new(0, 0, 0)
|
||||
clone.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
clone.BackgroundTransparency = 0.5
|
||||
end
|
||||
end
|
||||
|
||||
function dragRegion(face, dist)
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
if face == Enum.NormalId.Front then
|
||||
dragStartZ = -math.floor(dist)
|
||||
elseif face == Enum.NormalId.Back then
|
||||
dragEndZ = math.floor(dist)
|
||||
elseif face == Enum.NormalId.Bottom then
|
||||
dragStartY = -math.floor(dist)
|
||||
elseif face == Enum.NormalId.Top then
|
||||
dragEndY = math.floor(dist)
|
||||
elseif face == Enum.NormalId.Left then
|
||||
dragStartX = -math.floor(dist)
|
||||
elseif face == Enum.NormalId.Right then
|
||||
dragEndX = math.floor(dist)
|
||||
else return end
|
||||
|
||||
-- update the box display
|
||||
local newStartX = math.min(startCell.x + dragStartX, endCell.x + dragEndX)
|
||||
local newStartY = math.min(startCell.y + dragStartY, endCell.y + dragEndY)
|
||||
local newStartZ = math.min(startCell.z + dragStartZ, endCell.z + dragEndZ)
|
||||
local newEndX = math.max(startCell.x + dragStartX, endCell.x + dragEndX)
|
||||
local newEndY = math.max(startCell.y + dragStartY, endCell.y + dragEndY)
|
||||
local newEndZ = math.max(startCell.z + dragStartZ, endCell.z + dragEndZ)
|
||||
|
||||
local boxStart = CellCornerToWorld(c, newStartX, newStartY, newStartZ)
|
||||
local boxEnd = CellCornerToWorld(c, newEndX + 1, newEndY + 1, newEndZ + 1)
|
||||
boxSize = boxEnd - boxStart
|
||||
local boxCenter = (boxEnd + boxStart)/2
|
||||
|
||||
selectionBox.Size = boxSize
|
||||
selectionBox.CFrame = CFrame.new(boxCenter)
|
||||
|
||||
handlesWereDragged = true
|
||||
end
|
||||
|
||||
|
||||
function mouseDown(mouse)
|
||||
if on and not debounce and mouse.Target then
|
||||
startCell = nil
|
||||
endCell = nil
|
||||
regionSelected = false
|
||||
handles.Visible = false
|
||||
selectionBox.Parent = nil
|
||||
selectionLasso.Visible = false
|
||||
|
||||
local tempCell = WorldToCellPreferSolid(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
if GetCell(c, tempCell.x, tempCell.y, tempCell.z).Value == 0 then return end
|
||||
|
||||
dragging = true
|
||||
|
||||
startCell = tempCell
|
||||
elseif on and cloning and cloneHitCell and regionSelected then
|
||||
regionSelected = false
|
||||
handles.Visible = false
|
||||
print("Cloning")
|
||||
putCloneDown()
|
||||
|
||||
-- update selection box to new coords
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
local boxStart = CellCornerToWorld(c, startX, startY, startZ)
|
||||
local boxEnd = CellCornerToWorld(c, endX + 1, endY + 1, endZ + 1)
|
||||
boxSize = boxEnd - boxStart
|
||||
local boxCenter = (boxEnd + boxStart)/2
|
||||
selectionBox.Size = boxSize
|
||||
selectionBox.CFrame = CFrame.new(boxCenter)
|
||||
|
||||
--startCell = nil
|
||||
--endCell = nil
|
||||
--selectionLasso.Visible = false
|
||||
handles.Visible = true
|
||||
regionSelected = true
|
||||
cloneLasso.Visible = false
|
||||
cloning = false
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function mouseUp(mouse)
|
||||
dragging = false
|
||||
if not startCell or not endCell then return end
|
||||
if cloning then return end
|
||||
regionSelected = true
|
||||
print("Region Selected: "..startCell.x..", "..startCell.y..", "..startCell.z.." to "..endCell.x..", "..endCell.y..", "..endCell.z)
|
||||
|
||||
-- enforce ordering on startCell and endCell
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
startCell = Vector3.new(startX, startY, startZ)
|
||||
endCell = Vector3.new(endX, endY, endZ)
|
||||
|
||||
-- handle handle [lulz]
|
||||
handles.Visible = true
|
||||
|
||||
if handlesWereDragged then
|
||||
newStartX = math.min(startCell.x + dragStartX, endCell.x + dragEndX)
|
||||
newStartY = math.min(startCell.y + dragStartY, endCell.y + dragEndY)
|
||||
newStartZ = math.min(startCell.z + dragStartZ, endCell.z + dragEndZ)
|
||||
newEndX = math.max(startCell.x + dragStartX, endCell.x + dragEndX)
|
||||
newEndY = math.max(startCell.y + dragStartY, endCell.y + dragEndY)
|
||||
newEndZ = math.max(startCell.z + dragStartZ, endCell.z + dragEndZ)
|
||||
startCell = Vector3.new(newStartX, newStartY, newStartZ)
|
||||
endCell = Vector3.new(newEndX, newEndY, newEndZ)
|
||||
handlesWereDragged = false
|
||||
end
|
||||
|
||||
dragStartX = 0
|
||||
dragStartY = 0
|
||||
dragStartZ = 0
|
||||
dragEndX = 0
|
||||
dragEndY = 0
|
||||
dragEndZ = 0
|
||||
end
|
||||
|
||||
|
||||
function mouseMove(mouse)
|
||||
if on and cloning and regionSelected then
|
||||
cloneHitCell = WorldToCell(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
centerX = math.floor((startX + endX)/2)
|
||||
centerY = math.floor((startY + endY)/2)
|
||||
centerZ = math.floor((startZ + endZ)/2)
|
||||
|
||||
xOffset = cloneHitCell.x - centerX
|
||||
yOffset = cloneHitCell.y - centerY
|
||||
zOffset = cloneHitCell.z - centerZ
|
||||
|
||||
cloneBox.CFrame = selectionBox.CFrame + 4 * Vector3.new(xOffset, yOffset, zOffset) -- since cells are 4x4x4
|
||||
cloneLasso.Visible = true
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if not startCell or not dragging or debounce then return end
|
||||
|
||||
endCell = WorldToCellPreferSolid(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
local boxStart = CellCornerToWorld(c, startX, startY, startZ)
|
||||
local boxEnd = CellCornerToWorld(c, endX + 1, endY + 1, endZ + 1)
|
||||
boxSize = boxEnd - boxStart
|
||||
local boxCenter = (boxEnd + boxStart)/2
|
||||
|
||||
selectionBox.Size = boxSize
|
||||
selectionBox.CFrame = CFrame.new(boxCenter)
|
||||
--selectionBox.Parent = game.Workspace
|
||||
selectionLasso.Visible = true
|
||||
end
|
||||
|
||||
function onFill(newMaterial)
|
||||
if debounce then
|
||||
print("Cannot perform that operation until the previous one is complete.")
|
||||
return
|
||||
elseif not regionSelected then
|
||||
print("Please select a region first.")
|
||||
return
|
||||
else
|
||||
debounce = true
|
||||
print("Filling region.")
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
--c:SetCells(Region3int16.new(Vector3int16.new(startX, startY, startZ), Vector3int16.new(endX-startX, endY-startY, endZ-startZ)), newMaterial, 0, 0)
|
||||
local count = 0
|
||||
for x = startX, endX do
|
||||
for y = startY, endY do
|
||||
for z = startZ, endZ do
|
||||
SetCell(c, x, y, z, newMaterial, 0, 0)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if count > 10000 then count = 0 wait() end
|
||||
end
|
||||
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
function onMaterialChange(newMaterial)
|
||||
if debounce then
|
||||
print("Cannot perform that operation until the previous one is complete.")
|
||||
return
|
||||
elseif not regionSelected then
|
||||
print("Please select a region first.")
|
||||
return
|
||||
elseif newMaterial == 0 then
|
||||
print("Cannot change material to Empty. Use Fill button to erase a region.")
|
||||
return
|
||||
else
|
||||
debounce = true
|
||||
print("Changing material of region.")
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
local count = 0
|
||||
for x = startX, endX do
|
||||
for y = startY, endY do
|
||||
for z = startZ, endZ do
|
||||
local mat, typ, orient = GetCell(c, x, y, z)
|
||||
if mat.Value > 0 then SetCell(c, x, y, z, newMaterial, typ, orient) end
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if count > 10000 then count = 0 wait() end
|
||||
end
|
||||
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
function onRotate()
|
||||
if debounce then
|
||||
print("Cannot perform that operation until the previous one is complete.")
|
||||
return
|
||||
elseif not regionSelected then
|
||||
print("Please select a region first.")
|
||||
return
|
||||
else
|
||||
debounce = true
|
||||
print("Rotating region.")
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
local xCenter = (startX+endX)/2
|
||||
local zCenter = (startZ+endZ)/2
|
||||
local xSize = (endX - startX)
|
||||
local zSize = (endZ - startZ)
|
||||
local xHalfSize = math.floor(xSize / 2)
|
||||
local zHalfSize = math.floor(zSize / 2)
|
||||
local newXCenter = math.floor(xCenter) - zHalfSize + zSize/2
|
||||
local newZCenter = math.floor(zCenter) - xHalfSize + xSize/2
|
||||
|
||||
for y = startY, endY do
|
||||
-- extract the y-slice
|
||||
|
||||
local cellTable = {}
|
||||
|
||||
|
||||
for x = startX, endX do
|
||||
xIndex = x - xCenter
|
||||
if (startX+endX)%2 == 1 then
|
||||
if xIndex > 0 then xIndex = math.ceil(xIndex)
|
||||
else xIndex = math.floor(xIndex) end
|
||||
end
|
||||
|
||||
cellTable[xIndex] = {}
|
||||
for z = startZ, endZ do
|
||||
local mat, typ, orient = GetCell(c, x, y, z)
|
||||
zIndex = z - zCenter
|
||||
if (startZ+endZ)%2 == 1 then
|
||||
if zIndex > 0 then zIndex = math.ceil(zIndex)
|
||||
else zIndex = math.floor(zIndex) end
|
||||
end
|
||||
|
||||
-- store in our table
|
||||
cellTable[xIndex][zIndex] = Vector3.new(mat.Value, typ.Value, orient.Value)
|
||||
|
||||
-- and clear the y-slice, so we don't get duplication errors
|
||||
SetCell(c, x, y, z, 0, 0, 0)
|
||||
end
|
||||
end
|
||||
wait()
|
||||
|
||||
-- put it back, rotated into the y-slice
|
||||
for x = math.floor(xCenter) - zHalfSize, math.floor(xCenter) - zHalfSize + zSize do
|
||||
for z = math.floor(zCenter) - xHalfSize, math.floor(zCenter) - xHalfSize + xSize do
|
||||
xIndex = x - newXCenter
|
||||
zIndex = z - newZCenter
|
||||
if zSize%2 == 1 then
|
||||
if xIndex > 0 then xIndex = math.ceil(xIndex)
|
||||
else xIndex = math.floor(xIndex) end
|
||||
end
|
||||
if xSize%2 == 1 then
|
||||
if zIndex > 0 then zIndex = math.ceil(zIndex)
|
||||
else zIndex = math.floor(zIndex) end
|
||||
end
|
||||
SetCell(c, x, y, z, cellTable[zIndex][-xIndex].x, cellTable[zIndex][-xIndex].y, (cellTable[zIndex][-xIndex].z + 3)%4)
|
||||
end
|
||||
end
|
||||
wait()
|
||||
end
|
||||
|
||||
-- update selection to follow rotation
|
||||
startCell = Vector3.new(math.floor(xCenter) - zHalfSize, startY, math.floor(zCenter) - xHalfSize)
|
||||
endCell = Vector3.new(math.floor(xCenter) - zHalfSize + zSize, endY, math.floor(zCenter) - xHalfSize + xSize)
|
||||
|
||||
local boxStart = CellCornerToWorld(c, startCell.X, startCell.Y, startCell.Z)
|
||||
local boxEnd = CellCornerToWorld(c, endCell.X + 1, endCell.Y + 1, endCell.Z + 1)
|
||||
boxSize = boxEnd - boxStart
|
||||
local boxCenter = (boxEnd + boxStart)/2
|
||||
|
||||
selectionBox.Size = boxSize
|
||||
selectionBox.CFrame = CFrame.new(boxCenter)
|
||||
selectionLasso.Visible = true
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
function onAutoWedge()
|
||||
if debounce then
|
||||
print("Cannot perform that operation until the previous one is complete.")
|
||||
return
|
||||
elseif not regionSelected then
|
||||
print("Please select a region first.")
|
||||
return
|
||||
elseif newMaterial == 0 then
|
||||
print("Cannot change material to Empty. Use Fill button to erase a region.")
|
||||
return
|
||||
else
|
||||
debounce = true
|
||||
print("Smoothing region.")
|
||||
startX = math.min(startCell.x, endCell.x)
|
||||
startY = math.min(startCell.y, endCell.y)
|
||||
startZ = math.min(startCell.z, endCell.z)
|
||||
|
||||
endX = math.max(startCell.x, endCell.x)
|
||||
endY = math.max(startCell.y, endCell.y)
|
||||
endZ = math.max(startCell.z, endCell.Z)
|
||||
|
||||
local count = 0
|
||||
local numCellsInLayer = (endY - startY)*(endX - startX)
|
||||
for z = startZ, endZ do
|
||||
AutoWedge(c, Region3int16.new(Vector3int16.new(startX, startY, z), Vector3int16.new(endX, endY, z)))
|
||||
if count > 10000 then count = 0 wait() else count = count + numCellsInLayer end
|
||||
end
|
||||
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function onClone()
|
||||
if debounce then
|
||||
print("Cannot perform that operation until the previous one is complete.")
|
||||
return
|
||||
elseif not regionSelected then
|
||||
print("Please select a region first.")
|
||||
return
|
||||
else
|
||||
debounce = true
|
||||
cloneHitCell = nil
|
||||
cloning = true
|
||||
cloneBox.Size = boxSize
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
|
||||
frame.Visible = true
|
||||
for w = 0, 0.2, 0.1 do
|
||||
frame.Size = UDim2.new(w, 0, w, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
title.Text = "Region Editing"
|
||||
--freql.Text = materialString
|
||||
fill.Text = "Fill"
|
||||
matChange.Text = "Set Material"
|
||||
clone.Text = "Clone"
|
||||
autoWedge.Text = "Smooth"
|
||||
rotate.Text = "Rotate"
|
||||
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
selectionLasso.Visible = false
|
||||
cloneLasso.Visible = false
|
||||
startCell = nil
|
||||
endCell = nil
|
||||
regionSelected = false
|
||||
handles.Visible = false
|
||||
selectionBox.Parent = nil
|
||||
|
||||
-- reset variables
|
||||
currentMaterial = 1
|
||||
startCell = nil
|
||||
endCell = nil
|
||||
regionSelected = false
|
||||
dragging = false
|
||||
cloning = false
|
||||
cloneHitCell = nil
|
||||
boxSize = Vector3.new(0, 0, 0)
|
||||
debounce = false
|
||||
|
||||
-- for region resizing
|
||||
handlesWereDragged = false
|
||||
dragStartX = 0
|
||||
dragStartY = 0
|
||||
dragStartZ = 0
|
||||
dragEndX = 0
|
||||
dragEndY = 0
|
||||
dragEndZ = 0
|
||||
|
||||
toolbarbutton:SetActive(false)
|
||||
|
||||
title.Text = ""
|
||||
fill.Text = ""
|
||||
clone.Text = ""
|
||||
rotate.Text = ""
|
||||
matChange.Text = ""
|
||||
autoWedge.Text = ""
|
||||
for w = 0.2, 0, -0.1 do
|
||||
frame.Size = UDim2.new(w, 0, w, 0)
|
||||
wait(0.0000001)
|
||||
end
|
||||
frame.Visible = false
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
function updateMaterialChoice(choice)
|
||||
if choice == "Grass" then
|
||||
currentMaterial = 1
|
||||
elseif choice == "Sand" then
|
||||
currentMaterial = 2
|
||||
elseif choice == "Empty" then
|
||||
currentMaterial = 0
|
||||
elseif choice == "Brick" then
|
||||
currentMaterial = 3
|
||||
elseif choice == "Granite" then
|
||||
currentMaterial = 4
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
selectionLasso.Visible = false
|
||||
selectionLasso.Parent = g
|
||||
cloneLasso.Visible = false
|
||||
cloneLasso.Parent = g
|
||||
handles.Visible = false
|
||||
handles.Adornee = selectionBox
|
||||
handles.Parent = g
|
||||
handles.MouseDrag:connect(dragRegion)
|
||||
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Size = UDim2.new(0.2, 0, 0.2, 0)
|
||||
frame.Position = UDim2.new(0, 0, 0, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.Visible = false
|
||||
|
||||
--title
|
||||
title = Instance.new("TextLabel", frame)
|
||||
title.Position = UDim2.new(0.4, 0, 0.05, 0)
|
||||
title.Size = UDim2.new(0.2, 0, 0.05, 0)
|
||||
title.Text = ""
|
||||
title.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
title.TextColor3 = Color3.new(1, 1, 1)
|
||||
title.Font = Enum.Font.ArialBold
|
||||
title.FontSize = Enum.FontSize.Size24
|
||||
title.BorderColor3 = Color3.new(0, 0, 0)
|
||||
title.BackgroundTransparency = 1
|
||||
|
||||
--[[current frequency display label
|
||||
freql = Instance.new("TextLabel", frame)
|
||||
freql.Position = UDim2.new(0.15, 0, 0.4, 0)
|
||||
freql.Size = UDim2.new(0.1, 0, 0.05, 0)
|
||||
freql.Text = ""
|
||||
freql.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
freql.TextColor3 = Color3.new(1, 1, 1)
|
||||
freql.Font = Enum.Font.ArialBold
|
||||
freql.FontSize = Enum.FontSize.Size14
|
||||
freql.BorderColor3 = Color3.new(0, 0, 0)
|
||||
freql.BackgroundTransparency = 1
|
||||
|
||||
--frequency slider
|
||||
freqSliderGui, freqSliderPosition = RbxGui.CreateSlider(3, 0, UDim2.new(0.2, 0, 0.72, 0))
|
||||
freqSliderGui.Parent = frame
|
||||
freqbar = freqSliderGui:FindFirstChild("Bar")
|
||||
freqbar.Size = UDim2.new(0.75, 0, 0, 5)
|
||||
freqSliderPosition.Value = 2
|
||||
freqSliderPosition.Changed:connect(function()
|
||||
f = freqSliderPosition.Value
|
||||
if (f == 1) then materialString = "Material: Empty"
|
||||
elseif (f == 2) then materialString = "Material: Grass"
|
||||
elseif (f == 3) then materialString = "Material: Sand"
|
||||
else materialString = "Material: Undefined" end
|
||||
freql.Text = materialString
|
||||
end)]]--
|
||||
|
||||
local materialSelect, externalMaterialSelectFunction = RbxGui.CreateDropDownMenu(materialNames, updateMaterialChoice)
|
||||
materialSelect.Name = "MaterialSelect"
|
||||
materialSelect.Position = UDim2.new(.05, 0, .2, 0)
|
||||
materialSelect.Size = UDim2.new(.6, 0, .3, 0)
|
||||
materialSelect.Parent = frame
|
||||
|
||||
|
||||
|
||||
--fill region button
|
||||
fill = Instance.new("TextButton", frame)
|
||||
fill.Position = UDim2.new(0.370, 0, 0.85, 0)
|
||||
fill.Size = UDim2.new(0.15, 0, 0.1, 0)
|
||||
fill.Text = ""
|
||||
fill.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
fill.TextColor3 = Color3.new(1, 1, 1)
|
||||
fill.Font = Enum.Font.ArialBold
|
||||
fill.FontSize = Enum.FontSize.Size14
|
||||
fill.BorderColor3 = Color3.new(0, 0, 0)
|
||||
fill.BackgroundTransparency = 0.5
|
||||
fill.MouseEnter:connect(function()
|
||||
fill.BorderColor3 = Color3.new(1, 1, 1)
|
||||
fill.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
fill.BackgroundTransparency = 0.2
|
||||
end)
|
||||
fill.MouseButton1Click:connect(function() onFill(currentMaterial) end)
|
||||
fill.MouseLeave:connect(function()
|
||||
fill.BorderColor3 = Color3.new(0, 0, 0)
|
||||
fill.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
fill.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
matChange = Instance.new("TextButton", frame)
|
||||
matChange.Position = UDim2.new(0.025, 0, 0.85, 0)
|
||||
matChange.Size = UDim2.new(0.325, 0, 0.1, 0)
|
||||
matChange.Text = ""
|
||||
matChange.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
matChange.TextColor3 = Color3.new(1, 1, 1)
|
||||
matChange.Font = Enum.Font.ArialBold
|
||||
matChange.FontSize = Enum.FontSize.Size14
|
||||
matChange.BorderColor3 = Color3.new(0, 0, 0)
|
||||
matChange.BackgroundTransparency = 0.5
|
||||
matChange.MouseEnter:connect(function()
|
||||
matChange.BorderColor3 = Color3.new(1, 1, 1)
|
||||
matChange.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
matChange.BackgroundTransparency = 0.2
|
||||
end)
|
||||
matChange.MouseButton1Click:connect(function() onMaterialChange(currentMaterial) end)
|
||||
matChange.MouseLeave:connect(function()
|
||||
matChange.BorderColor3 = Color3.new(0, 0, 0)
|
||||
matChange.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
matChange.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
|
||||
|
||||
--clone region button
|
||||
clone = Instance.new("TextButton", frame)
|
||||
clone.Position = UDim2.new(0.5325, 0, 0.85, 0)
|
||||
clone.Size = UDim2.new(0.2, 0, 0.1, 0)
|
||||
clone.Text = ""
|
||||
clone.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
clone.TextColor3 = Color3.new(1, 1, 1)
|
||||
clone.Font = Enum.Font.ArialBold
|
||||
clone.FontSize = Enum.FontSize.Size14
|
||||
clone.BorderColor3 = Color3.new(0, 0, 0)
|
||||
clone.BackgroundTransparency = 0.5
|
||||
clone.MouseEnter:connect(function()
|
||||
clone.BorderColor3 = Color3.new(1, 1, 1)
|
||||
clone.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
clone.BackgroundTransparency = 0.2
|
||||
end)
|
||||
clone.MouseButton1Click:connect(onClone)
|
||||
clone.MouseLeave:connect(function()
|
||||
clone.BorderColor3 = Color3.new(0, 0, 0)
|
||||
clone.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
clone.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
--autowedge button
|
||||
autoWedge = Instance.new("TextButton", frame)
|
||||
autoWedge.Position = UDim2.new(0.75, 0, 0.85, 0)
|
||||
autoWedge.Size = UDim2.new(0.2, 0, 0.1, 0)
|
||||
autoWedge.Text = ""
|
||||
autoWedge.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
autoWedge.TextColor3 = Color3.new(1, 1, 1)
|
||||
autoWedge.Font = Enum.Font.ArialBold
|
||||
autoWedge.FontSize = Enum.FontSize.Size14
|
||||
autoWedge.BorderColor3 = Color3.new(0, 0, 0)
|
||||
autoWedge.BackgroundTransparency = 0.5
|
||||
autoWedge.MouseEnter:connect(function()
|
||||
autoWedge.BorderColor3 = Color3.new(1, 1, 1)
|
||||
autoWedge.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
autoWedge.BackgroundTransparency = 0.2
|
||||
end)
|
||||
autoWedge.MouseButton1Click:connect(onAutoWedge)
|
||||
autoWedge.MouseLeave:connect(function()
|
||||
autoWedge.BorderColor3 = Color3.new(0, 0, 0)
|
||||
autoWedge.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
autoWedge.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
--rotate button
|
||||
rotate = Instance.new("TextButton", frame)
|
||||
rotate.Position = UDim2.new(0.75, 0, 0.45, 0)
|
||||
rotate.Size = UDim2.new(0.2, 0, 0.1, 0)
|
||||
rotate.Text = ""
|
||||
rotate.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
rotate.TextColor3 = Color3.new(1, 1, 1)
|
||||
rotate.Font = Enum.Font.ArialBold
|
||||
rotate.FontSize = Enum.FontSize.Size14
|
||||
rotate.BorderColor3 = Color3.new(0, 0, 0)
|
||||
rotate.BackgroundTransparency = 0.5
|
||||
rotate.MouseEnter:connect(function()
|
||||
rotate.BorderColor3 = Color3.new(1, 1, 1)
|
||||
rotate.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
rotate.BackgroundTransparency = 0.2
|
||||
end)
|
||||
rotate.MouseButton1Click:connect(onRotate)
|
||||
rotate.MouseLeave:connect(function()
|
||||
rotate.BorderColor3 = Color3.new(0, 0, 0)
|
||||
rotate.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
|
||||
rotate.BackgroundTransparency = 0.5
|
||||
end)
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
print("Region Editing Plugin Loaded")
|
||||
@@ -0,0 +1,334 @@
|
||||
-----------------------------
|
||||
--LOCAL FUNCTION DEFINITIONS-
|
||||
-----------------------------
|
||||
local c = game.Workspace.Terrain
|
||||
local SetCell = c.SetCell
|
||||
local GetCell = c.GetCell
|
||||
local WorldToCellPreferSolid = c.WorldToCellPreferSolid
|
||||
|
||||
-----------------
|
||||
--DEFAULT VALUES-
|
||||
-----------------
|
||||
loaded = false
|
||||
on = false
|
||||
local materialToImageMap = {}
|
||||
local materialNames = {"Grass","Sand", "Brick", "Granite"}
|
||||
local currentMaterial = 1
|
||||
local changedDragging = 0
|
||||
|
||||
local debounce = false
|
||||
local dragging = false
|
||||
local r = 5
|
||||
|
||||
for i,v in pairs(materialNames) do
|
||||
materialToImageMap[v] = {}
|
||||
if v == "Grass" then
|
||||
materialToImageMap[v].Regular = "http://www.watrbx.wtf/asset/?id=56563112"
|
||||
elseif v == "Sand" then
|
||||
materialToImageMap[v].Regular = "http://www.watrbx.wtf/asset/?id=62356652"
|
||||
elseif v == "Brick" then
|
||||
materialToImageMap[v].Regular = "http://www.watrbx.wtf/asset/?id=65961537"
|
||||
materialToImageMap[v].Over = "http://www.watrbx.wtf/asset/?id=65961537"
|
||||
elseif v == "Granite" then
|
||||
materialToImageMap[v].Regular = "http://www.watrbx.wtf/asset/?id=65961588"
|
||||
materialToImageMap[v].Over = "http://www.watrbx.wtf/asset/?id=65961588"
|
||||
end
|
||||
end
|
||||
|
||||
for i,v in pairs(materialNames) do
|
||||
game:GetService("ContentProvider"):Preload(materialToImageMap[v].Regular)
|
||||
end
|
||||
|
||||
---------------
|
||||
--PLUGIN SETUP-
|
||||
---------------
|
||||
self = PluginManager():CreatePlugin()
|
||||
mouse = self:GetMouse()
|
||||
mouse.Button1Down:connect(function() mouseDown(mouse) end)
|
||||
mouse.Button1Up:connect(function() mouseUp(mouse) end)
|
||||
mouse.Move:connect(function() mouseMove(mouse) end)
|
||||
|
||||
self.Deactivation:connect(function()
|
||||
Off()
|
||||
end)
|
||||
toolbar = self:CreateToolbar("Terrain")
|
||||
toolbarbutton = toolbar:CreateButton("", "Material Brush", "materialBrush.png")
|
||||
toolbarbutton.Click:connect(function()
|
||||
if on then
|
||||
Off()
|
||||
elseif loaded then
|
||||
On()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
--FUNCTION DEFINITIONS-
|
||||
-----------------------
|
||||
|
||||
function paint(mouse)
|
||||
if mouse and mouse.Hit and c and not debounce then
|
||||
debounce = true
|
||||
local count = 0
|
||||
local cellPos = WorldToCellPreferSolid(c, mouse.Hit.p)
|
||||
for x = cellPos.x - r, cellPos.x + r do
|
||||
for y = cellPos.y - r, cellPos.y + r do
|
||||
for z = cellPos.z - r, cellPos.z + r do
|
||||
local tempCellPos = Vector3.new(x, y, z)
|
||||
local distSq = (tempCellPos - cellPos):Dot(tempCellPos - cellPos)
|
||||
if (distSq < r*r) then
|
||||
local oldMaterial, oldType, oldOrientation = GetCell(c, x, y, z)
|
||||
if oldMaterial.Value > 0 then SetCell(c, x, y, z, currentMaterial, oldType, oldOrientation) end
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if count > 10000 then count = 0 wait() end
|
||||
end
|
||||
debounce = false
|
||||
end
|
||||
end
|
||||
|
||||
function mouseDown(mouse)
|
||||
changedDragging = tick()
|
||||
if on and mouse.Target == game.Workspace.Terrain then
|
||||
dragging = true
|
||||
tweeningFrame = true
|
||||
frame:TweenPosition(UDim2.new(0,-245,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quad,0.5,true,function()
|
||||
hintFrame.Visible = true
|
||||
tweeningFrame = false
|
||||
end)
|
||||
paint(mouse)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function mouseUp(mouse)
|
||||
dragging = false
|
||||
changedDragging = tick()
|
||||
delay(5,function()
|
||||
local timeDiff = (changedDragging + 5) - tick()
|
||||
if timeDiff < 0.2 then
|
||||
tweeningFrame = true
|
||||
hintFrame.Visible = false
|
||||
frame:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quad,0.5,true,function()
|
||||
tweeningFrame = false
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function mouseMove(mouse)
|
||||
if on and dragging then
|
||||
paint(mouse)
|
||||
end
|
||||
end
|
||||
|
||||
function On()
|
||||
self:Activate(true)
|
||||
toolbarbutton:SetActive(true)
|
||||
|
||||
local gui = game:GetService("CoreGui"):FindFirstChild("MaterialPainterGui",true)
|
||||
|
||||
frame.Position = UDim2.new(0,0,0,0)
|
||||
frame.Visible = true
|
||||
hintFrame.Visible = false
|
||||
halfFrame.Parent = gui
|
||||
title.Text = "Material Painter"
|
||||
radl.Text = "Radius: "..r
|
||||
|
||||
on = true
|
||||
end
|
||||
|
||||
function Off()
|
||||
toolbarbutton:SetActive(false)
|
||||
|
||||
title.Text = ""
|
||||
radl.Text = ""
|
||||
frame.Visible = false
|
||||
hintFrame.Visible = false
|
||||
halfFrame.Parent = nil
|
||||
on = false
|
||||
end
|
||||
|
||||
|
||||
function updateMaterialChoice(choice)
|
||||
if choice == "Grass" then
|
||||
currentMaterial = 1
|
||||
elseif choice == "Sand" then
|
||||
currentMaterial = 2
|
||||
elseif choice == "Erase" then
|
||||
currentMaterial = 0
|
||||
elseif choice == "Brick" then
|
||||
currentMaterial = 3
|
||||
elseif choice == "Granite" then
|
||||
currentMaterial = 4
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
------
|
||||
--GUI-
|
||||
------
|
||||
|
||||
--load library for with sliders
|
||||
local RbxGui = LoadLibrary("RbxGui")
|
||||
local tweeningFrame = false
|
||||
|
||||
--screengui
|
||||
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
|
||||
g.Name = "MaterialPainterGui"
|
||||
|
||||
local selectedButton = nil
|
||||
|
||||
--frame
|
||||
frame = Instance.new("Frame", g)
|
||||
frame.Size = UDim2.new(0, 245, 0, 230)
|
||||
frame.Position = UDim2.new(0, 0, 0, 0)
|
||||
frame.BackgroundTransparency = 0.5
|
||||
frame.BorderSizePixel = 0
|
||||
frame.BackgroundColor3 = Color3.new(0,0,0)
|
||||
frame.Visible = false
|
||||
frame.Active = true
|
||||
|
||||
hintFrame = Instance.new("Frame",g)
|
||||
hintFrame.BackgroundTransparency = 0.5
|
||||
hintFrame.BackgroundColor3 = Color3.new(0,0,0)
|
||||
hintFrame.Size = UDim2.new(0,15,0,230)
|
||||
hintFrame.Visible = false
|
||||
|
||||
halfFrame = Instance.new("Frame",g)
|
||||
halfFrame.Name = "HalfFrame"
|
||||
halfFrame.Size = UDim2.new(0,123,0,230)
|
||||
halfFrame.BackgroundTransparency = 1
|
||||
halfFrame.MouseEnter:connect(function()
|
||||
if not dragging and frame.Position ~= UDim2.new(0, 0, 0, 0) and not tweeningFrame then
|
||||
tweeningFrame = true
|
||||
hintFrame.Visible = false
|
||||
frame:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quad,0.2,true,function() tweeningFrame = false end)
|
||||
end
|
||||
end)
|
||||
|
||||
--title
|
||||
title = Instance.new("TextLabel", frame)
|
||||
title.Position = UDim2.new(0, 0, 0, 3)
|
||||
title.Size = UDim2.new(1, 0, 0, 24)
|
||||
title.Text = ""
|
||||
title.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
title.TextColor3 = Color3.new(1, 1, 1)
|
||||
title.Font = Enum.Font.ArialBold
|
||||
title.FontSize = Enum.FontSize.Size18
|
||||
title.BorderColor3 = Color3.new(0, 0, 0)
|
||||
title.BackgroundTransparency = 1
|
||||
|
||||
--current radius display label
|
||||
radl = Instance.new("TextLabel", frame)
|
||||
radl.Position = UDim2.new(0, 10, 1, -20)
|
||||
radl.Size = UDim2.new(0.2, 0, 0, 14)
|
||||
radl.Text = ""
|
||||
radl.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
|
||||
radl.TextColor3 = Color3.new(0.95, 0.95, 0.95)
|
||||
radl.Font = Enum.Font.Arial
|
||||
radl.FontSize = Enum.FontSize.Size14
|
||||
radl.BorderColor3 = Color3.new(0, 0, 0)
|
||||
radl.BackgroundTransparency = 1
|
||||
|
||||
--radius slider
|
||||
radSliderGui, radSliderPosition = RbxGui.CreateSlider(10, 0, UDim2.new(0, 75, 1, -15))
|
||||
radSliderGui.Parent = frame
|
||||
radBar = radSliderGui:FindFirstChild("Bar")
|
||||
radBar.Size = UDim2.new(0.65, 0, 0, 5)
|
||||
radSliderPosition.Value = r - 1
|
||||
radSliderPosition.Changed:connect(function()
|
||||
r = radSliderPosition.Value
|
||||
radl.Text = "Radius: "..r
|
||||
end)
|
||||
|
||||
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid")
|
||||
scrollFrame.Size = UDim2.new(0,240,0,170)
|
||||
scrollFrame.Position = UDim2.new(0.5,-scrollFrame.Size.X.Offset/2,0,30)
|
||||
scrollFrame.Parent = frame
|
||||
|
||||
scrollUp.Parent = frame
|
||||
scrollUp.Visible = false
|
||||
scrollUp.Position = UDim2.new(1,-19,0,30)
|
||||
|
||||
scrollDown.Parent = frame
|
||||
scrollDown.Visible = false
|
||||
scrollDown.Position = UDim2.new(1,-19,0,30 - 17 + scrollFrame.Size.Y.Offset)
|
||||
|
||||
scrollFrame.ChildRemoved:connect(function()
|
||||
if #scrollFrame:GetChildren() < 35 then
|
||||
scrollUp.Visible = false
|
||||
scrollDown.Visible = false
|
||||
end
|
||||
end)
|
||||
|
||||
scrollFrame.ChildAdded:connect(function()
|
||||
if #scrollFrame:GetChildren() >= 35 then
|
||||
scrollUp.Visible = true
|
||||
scrollDown.Visible = true
|
||||
end
|
||||
end)
|
||||
|
||||
function createMaterialButton(name)
|
||||
local buttonWrap = Instance.new("TextButton")
|
||||
buttonWrap.Text = ""
|
||||
buttonWrap.Size = UDim2.new(0,32,0,32)
|
||||
buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
|
||||
buttonWrap.BorderSizePixel = 0
|
||||
buttonWrap.BackgroundTransparency = 1
|
||||
buttonWrap.AutoButtonColor = false
|
||||
buttonWrap.Name = tostring(name) .. "Button"
|
||||
|
||||
local imageButton = Instance.new("ImageButton")
|
||||
imageButton.AutoButtonColor = false
|
||||
imageButton.BackgroundTransparency = 1
|
||||
imageButton.Size = UDim2.new(0,30,0,30)
|
||||
imageButton.Position = UDim2.new(0,1,0,1)
|
||||
imageButton.Name = tostring(name) .. "Button"
|
||||
imageButton.Parent = buttonWrap
|
||||
imageButton.Image = materialToImageMap[name].Regular
|
||||
|
||||
imageButton.MouseEnter:connect(function()
|
||||
buttonWrap.BackgroundTransparency = 0
|
||||
end)
|
||||
imageButton.MouseLeave:connect(function()
|
||||
if selectedButton ~= buttonWrap then
|
||||
buttonWrap.BackgroundTransparency = 1
|
||||
end
|
||||
end)
|
||||
imageButton.MouseButton1Click:connect(function()
|
||||
updateMaterialChoice(name)
|
||||
if selectedButton ~= buttonWrap then
|
||||
buttonWrap.BackgroundTransparency = 0
|
||||
selectedButton.BackgroundTransparency = 1
|
||||
selectedButton = buttonWrap
|
||||
end
|
||||
end)
|
||||
|
||||
return buttonWrap
|
||||
end
|
||||
|
||||
for i = 1, #materialNames do
|
||||
local imageButton = createMaterialButton(materialNames[i])
|
||||
|
||||
if materialNames[i] == "Grass" then
|
||||
selectedButton = imageButton
|
||||
imageButton.BackgroundTransparency = 0
|
||||
end
|
||||
|
||||
imageButton.Parent = scrollFrame
|
||||
end
|
||||
|
||||
recalculateScroll()
|
||||
|
||||
|
||||
--------------------------
|
||||
--SUCCESSFUL LOAD MESSAGE-
|
||||
--------------------------
|
||||
loaded = true
|
||||
|
After Width: | Height: | Size: 1006 B |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |