256 lines
8.6 KiB
Lua
256 lines
8.6 KiB
Lua
-- Underworlds undergen.lua
|
|
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
|
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
|
|
|
|
|
underworlds_mod.cave_width = 0.05 -- figurative width
|
|
local max_depth = 31000
|
|
|
|
|
|
local terrain_noise = {offset = 15, scale = 10, seed = 3721, spread = {x = 40, y = 40, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
|
|
local terrain_map
|
|
local terrain = {}
|
|
|
|
|
|
underworlds_mod.undergen = function(minp, maxp, data, p2data, area, node, underzone)
|
|
if not (minp and maxp and data and area and node and type(data) == 'table' and underzone and underworlds_mod.underzones) then
|
|
return
|
|
end
|
|
|
|
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
|
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
|
|
local map_min = {x = minp.x, y = minp.y - 1, z = minp.z}
|
|
|
|
if not terrain_map then
|
|
terrain_map = minetest.get_perlin_map(terrain_noise, {x=csize.x, y=csize.z})
|
|
|
|
if not terrain_map then
|
|
return
|
|
end
|
|
end
|
|
|
|
terrain = terrain_map:get2dMap_flat({x=minp.x, y=minp.z}, terrain)
|
|
if not terrain then
|
|
return
|
|
end
|
|
|
|
local math_random = math.random
|
|
local dis_map = {}
|
|
if underzone and underzone.city then
|
|
for i = 0, 10, 2 do
|
|
dis_map[i] = {}
|
|
for j = 0, 10, 2 do
|
|
dis_map[i][j] = math_random(6)
|
|
if dis_map[i][j] == 6 then
|
|
dis_map[i][j] = 5 + math_random(10)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local write = false
|
|
|
|
local index = 0
|
|
local index3d = 0
|
|
local cave_width = underworlds_mod.cave_width
|
|
local styx_sea_level = underworlds_mod.underzones['Styx'].sealevel
|
|
for z = minp.z, maxp.z do
|
|
for x = minp.x, maxp.x do
|
|
index = index + 1
|
|
index3d = (z - minp.z) * (csize.y + 2) * csize.x + (x - minp.x) + 1
|
|
local ivm = area:index(x, minp.y-1, z)
|
|
|
|
local column = 0
|
|
if terrain[index] < 30 then
|
|
column = 1
|
|
elseif terrain[index] < 35 then
|
|
column = 2
|
|
end
|
|
|
|
for y = minp.y-1, maxp.y+1 do
|
|
if underzone.regular_columns and (x - minp.x) < 8 and (z - minp.z) < 8 then
|
|
data[ivm] = node[underzone.column_node]
|
|
write = true
|
|
elseif underzone.column_node and not underzone.regular_columns and column == 2 then
|
|
if underzone.column_node_rare and math.random(70) == 1 then
|
|
data[ivm] = node[underzone.column_node_rare]
|
|
else
|
|
data[ivm] = node[underzone.column_node]
|
|
end
|
|
write = true
|
|
elseif (y < underzone.ceiling - (underzone.vary and terrain[index] or 0) and y > underzone.floor + (underzone.vary and terrain[index] or 0)) then
|
|
if underzone.sealevel and y <= underzone.sealevel then
|
|
data[ivm] = node["default:water_source"]
|
|
elseif underzone.lake and y < underzone.floor + underzone.lake_level then
|
|
data[ivm] = node[underzone.lake]
|
|
else
|
|
data[ivm] = node["air"]
|
|
end
|
|
write = true
|
|
elseif y < underzone.ceiling + 10 - (underzone.vary and terrain[index] or 0) and (not underworlds_mod.integration or data[ivm] ~= node['air']) then
|
|
data[ivm] = node["default:stone"]
|
|
elseif y > underzone.floor - 10 + (underzone.vary and terrain[index] or 0) and (not underworlds_mod.integration or data[ivm] ~= node['air']) then
|
|
data[ivm] = node["default:stone"]
|
|
end
|
|
|
|
ivm = ivm + area.ystride
|
|
index3d = index3d + csize.x
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local math_floor = math.floor
|
|
|
|
for z = minp.z, maxp.z do
|
|
for x = minp.x, maxp.x do
|
|
index = index + 1
|
|
index3d = (z - minp.z) * (csize.y + 2) * csize.x + (x - minp.x) + 1
|
|
local ivm = area:index(x, minp.y-1, z)
|
|
|
|
--local column = 0
|
|
--if terrain[index] < 30 then
|
|
-- column = 1
|
|
--elseif terrain[index] < 35 then
|
|
-- column = 2
|
|
--end
|
|
|
|
for y = minp.y-1, maxp.y+1 do
|
|
local node_below
|
|
if y > minp.y then
|
|
node_below = data[ivm - area.ystride]
|
|
end
|
|
local node_above = data[ivm + area.ystride]
|
|
|
|
for deco_non_loop = 1, 1 do
|
|
if data[ivm] == node["default:stone"] then
|
|
if node_above == node["air"] and underzone.dirt and math_random(underzone.dirt_chance) == 1 then
|
|
data[ivm] = node[underzone.dirt]
|
|
write = true
|
|
break
|
|
end
|
|
|
|
local air_above = false
|
|
for i = 1, underzone.stone_depth do
|
|
if data[ivm + area.ystride * i] == node["air"] or (y < styx_sea_level and data[ivm + area.ystride * i] == node["default:water_source"]) then
|
|
air_above = true
|
|
end
|
|
end
|
|
|
|
if air_above then
|
|
if underzone.deco and math_random(underzone.deco_chance) == 1 then
|
|
data[ivm] = node[underzone.deco]
|
|
write = true
|
|
break
|
|
else
|
|
data[ivm] = node[underzone.floor_node]
|
|
write = true
|
|
break
|
|
end
|
|
end
|
|
|
|
local air_below = false
|
|
for i = 1, underzone.stone_depth do
|
|
if data[ivm - area.ystride * i] == node["air"] then
|
|
air_below = true
|
|
end
|
|
end
|
|
|
|
if not air_above and underzone.floor_node == "default:sand" then
|
|
data[ivm] = node["default:sandstone"]
|
|
write = true
|
|
break
|
|
end
|
|
|
|
if air_below then
|
|
if underzone.deco and math_random(underzone.deco_chance) == 1 then
|
|
data[ivm] = node[underzone.deco]
|
|
write = true
|
|
break
|
|
else
|
|
data[ivm] = node[underzone.ceiling_node]
|
|
write = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- smallest city generator ever
|
|
if underzone.city and data[ivm] == node['air'] and math_floor((x - minp.x) / 8) % 2 == 0 and math_floor((z - minp.z) / 8) % 2 == 0 and y - underzone.floor < dis_map[math_floor((x - minp.x) / 8)][math_floor((z - minp.z) / 8)] * 4 + 1 and y - underzone.floor >= 0 then
|
|
local dx = (x - minp.x) % 16
|
|
local dy = y - underzone.floor + 1
|
|
local dz = (z - minp.z) % 16
|
|
if dx == 1 and dz == 1 then
|
|
data[ivm] = node["default:ladder_steel"]
|
|
p2data[ivm] = 3
|
|
--write_p2 = true
|
|
elseif ((dx == 0 or dx == 7) and (dz % 3 ~= 2 or dy % 4 == 0)) or ((dz == 0 or dz == 7) and (dx % 3 ~= 2 or dy % 4 == 0)) then
|
|
data[ivm] = node["underworlds:hot_iron"]
|
|
elseif dy % 4 == 0 then
|
|
data[ivm] = node["underworlds:hot_brass"]
|
|
end
|
|
write = true
|
|
break
|
|
end
|
|
|
|
if data[ivm] == node["air"] and y < maxp.y then
|
|
-- hanging down
|
|
-- stone hasn't yet been changed
|
|
if underzone.stalactite and node_above == node["default:stone"] and math_random(underzone.stalactite_chance) == 1 then
|
|
data[ivm] = node[underzone.stalactite]
|
|
write = true
|
|
break
|
|
end
|
|
|
|
-- fluids
|
|
if y > minp.y and underzone.fluid and node_below == node[underzone.floor_node] and math_random(underzone.fluid_chance) == 1 then
|
|
data[ivm] = node[underzone.fluid]
|
|
write = true
|
|
break
|
|
|
|
-- standing up
|
|
elseif node_below == node[underzone.floor_node] and underzone.stalagmite and math_random(underzone.stalagmite_chance) == 1 then
|
|
if type(underzone.stalagmite) == 'table' then
|
|
data[ivm] = node[underzone.stalagmite[math_random(#underzone.stalagmite)]]
|
|
else
|
|
data[ivm] = node[underzone.stalagmite]
|
|
end
|
|
write = true
|
|
break
|
|
|
|
-- vegetation
|
|
elseif node_below == node["underworlds:polluted_dirt"] then
|
|
if math_random(10) == 1 then
|
|
data[ivm] = node["default:dry_shrub"]
|
|
write = true
|
|
break
|
|
elseif math_random(50) == 1 then
|
|
local air_count = 0
|
|
local pos = {}
|
|
local j
|
|
for i = 1, 9 do
|
|
j = ivm + area.ystride * i
|
|
if j <= #data and data[j] == node["air"] then
|
|
air_count = air_count + 1
|
|
end
|
|
end
|
|
if air_count > 6 then
|
|
pos.x = x
|
|
pos.y = y
|
|
pos.z = z
|
|
underworlds_mod.place_schematic(minp, maxp, data, p2data, area, node, pos, underworlds_mod.schematics['decaying_tree'], true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
ivm = ivm + area.ystride
|
|
index3d = index3d + csize.x
|
|
end
|
|
end
|
|
end
|
|
|
|
return write
|
|
end
|