Files
PlaneBuilding/scratch/dct2/PiecesModule
T

175 lines
5.0 KiB
Plaintext

local script = script.Parent.Pieces.PieceScript
if not script.Parent:FindFirstChild("Roots") then game.ServerStorage.Roots.Parent = script.Parent end
local roots = {}
for _,root in pairs(script.Parent.Roots:GetChildren()) do
if root.Name == "Root" then
root.Anchored = true
root.Transparency = 1
root.CanCollide = false
table.insert(roots,root)
end
end
-- piece: {"X,Y,Z,NX,NY,NZ,A,B...} marking each property it has
local pieces = {}
for _,piece in pairs(script.Parent:GetChildren()) do
if piece:IsA("Model") then
-- Set of 'characteristics' this has, equivalent to (unary?) branches in lhmes14c
local characteristics = {}
local position = piece:GetPivot().Position
local closest_root
local closest = 32
for _,root in pairs(roots) do
local distance = (root.Position - position).Magnitude
if distance < closest then
closest = distance
closest_root = root
end
end
if closest_root then
closest_root.Parent = piece
piece.PrimaryPart = closest_root
end
-- Make sure there is a PrimaryPart
if not piece.PrimaryPart then
piece.PrimaryPart = piece:FindFirstChildWhichIsA("BasePart")
end
if not piece.PrimaryPart then
warn(string.format("Piece: '%s' has no viable PrimaryPart (empty), please provide one.",piece.Name))
continue
end
-- Weld all Parts together
piece.PrimaryPart.Anchored = true
local template_weld = Instance.new("WeldConstraint")
template_weld.Part0 = piece.PrimaryPart
for _,item in pairs(piece:GetChildren()) do
if item:IsA("BasePart") and item ~= piece.PrimaryPart then
local weld = template_weld:Clone()
weld.Parent = piece
weld.Part1 = item
end
end
-- Populate characteristics
for literal in string.gmatch(piece.Name,"[^%.]+") do
local value,class = string.match(literal,"^(!?)(.*)")
characteristics[class] = #value == 0
end
piece.Parent = game.ServerStorage
--piece:ScaleTo()
table.insert(pieces,{characteristics = characteristics,piece = piece})
end
end
-- Compute whether variants are viable and actually copy/rotate them as options
local rotator = {
["X"] = "Z",
["Z"] = "NX",
["NX"] = "NZ",
["NZ"] = "X"
}
local function alreadyExists(match)
for _,piece in pairs(pieces) do
local success = true
for class,value in pairs(match) do
if piece.characteristics[class] ~= value then success = false break end
end
if success then return true end
end
end
local function rotateClass(class)
return rotator[class] or class
end
local new_pieces = {}
for _,piece in pairs(pieces) do -- This isn't very optimised, but it runs at the start of the program, this is ok.
local r90 = {}
local r180 = {}
local r270 = {}
for class,value in pairs(piece.characteristics) do
local c90 = rotateClass(class)
local c180 = rotateClass(c90)
local c270 = rotateClass(c180)
r90[c90] = value
r180[c180] = value
r270[c270] = value
end
local function pieceFactory(angle,characteristics)
if not alreadyExists(characteristics) then
local new_piece = piece.piece:Clone()
new_piece.Name = "V."..new_piece.Name
new_piece:PivotTo(new_piece:GetPivot() * CFrame.Angles(0,math.rad(angle),0))
table.insert(new_pieces,{piece = new_piece,characteristics = characteristics})
end
end
pieceFactory(270,r90)
pieceFactory(180,r180)
pieceFactory(90,r270)
end
for _,piece in pairs(pieces) do table.insert(new_pieces,piece) end
pieces = new_pieces
--[[local city = function(x,y,z)
return (math.noise(x*0.16,y*0.16,z*0.16) - (y * 0.05) + 0.2) > 0
end]]
local scale = 4
local template_part = Instance.new("Part")
template_part.Anchored = true
template_part.Name = "PieceTemplate"
template_part.CanCollide = false
template_part.Transparency = 0.5
template_part.Size = Vector3.one * scale
local function block(x,y,z,f,city)
local X = city(x+f,y,z)
local Y = city(x,y+f,z)
local Z = city(x,y,z+f)
local NX = city(x-f,y,z)
local NY = city(x,y-f,z)
local NZ = city(x,y,z-f)
local match = { -- The matching characteristics table for the hypothetical piece in this place
X = X,
Y = Y,
Z = Z,
NX = NX,
NY = NY,
NZ = NZ
}
if X and Y and Z and NX and NY and NZ then return false end
local greatest_rank = 0 -- The amount of matching characteristics for the best matching piece
local greatest = template_part -- The physical piece
for _,piece in pairs(pieces) do -- Look through every known piece
local rank = 0
for class,value in pairs(match) do -- Assimilate a rank of the characteristics it shares with this hypothetical one
local this = piece.characteristics[class]
if value == this then rank = rank + 1 elseif this ~= nil then rank = rank - 1 end -- If it's greatest, make it so
end
if rank > greatest_rank or (rank == greatest_rank and (math.random(1,10) > 3)) then
greatest = piece.piece
greatest_rank = rank
end
end
greatest = greatest:Clone()
greatest.Parent = game.Workspace -- Position it
greatest:PivotTo(greatest:GetPivot().Rotation + Vector3.new(x,y,z))
return true
end
--[[local function gen()
for x = 1,20 do
for y = 1,15 do
for z = 1,20 do
if city(x,y,z) then
end
end
end
end
end]]
return {block=block}