(covering the arms of a tree monster with twig models)
Made this and thought other people might find it useful.
--[[ Start of `CoverPart` function]]
local RANDOM = Random.new(os.clock())
local function weldPartTo(p1, p0, n)
local w = p1:FindFirstChild(n)
if w then
w:Destroy()
end
w = Instance.new("WeldConstraint")
w.Name = n
w.Part0 = p0
w.Part1 = p1
w.Parent = p1
end
local function weldModelTo(m, p)
if m.ClassName == "Model" then
assert(m.PrimaryPart, "no primary part for model")
for _, d in ipairs(m:GetDescendants()) do
if d:IsA("BasePart") and d ~= m.PrimaryPart then
weldPartTo(d, m.PrimaryPart, "WeldToPrimaryPart")
end
end
weldPartTo(m.PrimaryPart, p, "WeldTo" .. p.Name)
else
weldPartTo(m, p, "WeldTo" .. p.Name)
end
end
local function getFaceSize3D(partSize, dir)
dir = dir:Abs()
local getFaceSizeVec = Vector3.new(
bit32.bxor(dir.X, 1),
bit32.bxor(dir.Y, 1),
bit32.bxor(dir.Z, 1)
)
local faceSize3D = partSize*getFaceSizeVec
return faceSize3D
end
local function CoverPart(
part: BasePart, --[[ The base part you want to cover randomly with objects]]
numPerFace: NumberRange, --[[ The number of objects (range) you want to put per face]]
maxLookAngle: number, --[[ The maximum angle (deg) the object should face towards from the normal of the face. This behaves similar to the `SpreadAngle` property of particle emitters]]
dst: Instance, --[[ The new parent of all the created objects]]
src: Instance --[[ The source container of objects to clone from]]
)
local objs = src:GetChildren()
--[[ !!WARNING!!]]
--[[ Do not uncomment this unless you are positive you want all children]]
--[[ of the `dst` instance to be destroyed upon calling this function.]]
--[[ Useful for quick iteration of random placements.]]
--[[----------------------]]
--[[dst:ClearAllChildren()]]
--[[----------------------]]
local partCF = part.CFrame
local partSize = part.Size
local i = 0
for _, normalId in ipairs(Enum.NormalId:GetEnumItems()) do
for i = 1, math.random(numPerFace.Min, numPerFace.Max) do
local dir = Vector3.FromNormalId(normalId)
local faceSize = getFaceSize3D(partSize, dir)
local os_faceOrigin = dir*partSize/2
local os_randFaceVec = RANDOM:NextUnitVector()*faceSize/2
local ws_randFacePos = partCF*(os_faceOrigin + os_randFaceVec)
local ws_randLookPos = ws_randFacePos + partCF:VectorToWorldSpace(dir)
local ws_randCF = CFrame.lookAt(ws_randFacePos, ws_randLookPos)
* CFrame.Angles(math.rad(math.random(-maxLookAngle, maxLookAngle)), math.rad(math.random(-maxLookAngle, maxLookAngle)), math.rad(360))
local obj = objs[i%3+1]:Clone()
obj:PivotTo(ws_randCF)
obj.Parent = dst
weldModelTo(obj, part)
end
end
end
--[[ End of `CoverPart` function]]
--[[ Using command line]]
for _, selectedPart in ipairs(game:GetService("Selection"):Get()) do
CoverPart(selectedPart, NumberRange.new(1, 2), 45, workspace.ElderTree.Sticks, game.ServerStorage.GenerateSticks.Sticks)
end