This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
+570
View File
@@ -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")
+240
View File
@@ -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")
+234
View File
@@ -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")
+459
View File
@@ -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")
+427
View File
@@ -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")
+131
View File
@@ -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")
+386
View File
@@ -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")
+383
View File
@@ -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")
+202
View File
@@ -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")
+204
View File
@@ -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")
+836
View File
@@ -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
Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB