Files
2025-09-18 17:55:52 -04:00

204 lines
5.6 KiB
Lua

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