Here's a simplification of the code for erasing the plant from the map column:
-- Erase plant from correct map column
map_block_column = df.global.world.map.column_index[base.x//48*3][base.y//48*3]
for i,plant in pairs(map_block_column.plants) do
if plant.pos == base then
map_block_column.plants:erase(i)
break
end
end
"//" is integer division, which avoids the need for "math.floor()".
Note that "n//m" equals "n - n%m", because it's the non-remainder portion. Edit: I guess it's "(n - n%m)/m".
Dividing by 48 instead of 3 (since 48 = 3 * 16) takes care of the column conversion.
(It's worth pointing out that "base.x//48" is a mid-level tile coord. MLT's are 3*3 tile block columns, so "base.x//48*3" is a tile block column coord. It all checks out.)
Reused "map_block_column" instead of calculating it again.
Some shroom trees use just "body.connection_north" to indicate part of their cap, so you'll need to add that to "getPositions()". You also used z1,y1,x1 in the displace logic instead of the loop variables z,y,x.
You're probably going to need to remove roots, unless that's handled automatically somehow. "tree.roots" is similar to "tree.body", except it's upside-down. It's indexed from 0 to "tree.root_depth - 1". Presence of a root is indicated by "trunk" flag. Should be as simple as adding a second z loop after the first one. (Technically, you could get away with just "tree.roots[0]" in the current version of DF, but a loop is forward compatible for root_depth > 1.)
Changes:
...
local z1 = tree.pos.z
local z2 = tree.pos.z + tree.tree_info.body_height - 1
local z_root1 = tree.pos.z - 1
local z_root2 = tree.pos.z - tree.tree_info.root_depth
for x = x1,x2 do
for y = y1,y2 do
for z = z1,z2 do
pos = {x=x,y=y,z=z}
body = tree.tree_info.body[pos.z-z]:_displace((pos.y - y) * tree.tree_info.dim_x + (pos.x - x))
if body.trunk or body.twigs or body.branches or body.connection_north then
positions[#positions+1] = pos
end
end
for z = z_root2,z_root1 do
pos = {x=x,y=y,z=z}
root = tree.tree_info.root[pos.z - z - 1]:_displace((pos.y - y) * tree.tree_info.dim_x + (pos.x - x))
if root.trunk then
positions[#positions+1] = pos
end
end
end
...
I also simplified the if statements for body checks.
All that's left is to account for "position.z < base.z" for the tiletypes. Assuming roots can't grow in stone (need to test this,) then all you have to do is convert those positions to soil walls (tiletype 261.)
For the base, the floor tiletype should chose randomly from {348,349,350,351} instead of just 350 for tile variations. (That was probably already on the to-do list.)