add generator param 'wide-structs-chunks-radius' & make caves more interesting

This commit is contained in:
MihailRis 2024-10-10 03:57:43 +03:00
parent a578cca325
commit 50eb83ad9b
4 changed files with 49 additions and 23 deletions

View File

@ -31,21 +31,35 @@ end
function place_structures_wide(x, z, w, d, seed, chunk_height)
local placements = {}
if math.random() < 0.1 then -- generate caves
local sy = math.random() * (chunk_height / 6) + 80
local ey = math.max(1, sy - chunk_height / 4)
local my = (sy + ey) / 2 + math.random() * 24 - 12
local sx = x + math.random() * 60 - 30
local ex = x + math.random() * 60 - 30
local mx = (sx + ex) / 2 + math.random() * 32 - 16
local sz = z + math.random() * 60 - 30
local ez = z + math.random() * 60 - 30
local mz = (sz + ez) / 2 + math.random() * 32 - 16
if math.random() < 0.3 then -- generate caves
local sx = x + math.random() * 10 - 5
local sy = math.random() * (chunk_height / 6) + 40
local sz = z + math.random() * 10 - 5
local dir = math.random() * math.pi * 2
local dir_inertia = (math.random() - 0.5) * 2
local elevation = -sy / (chunk_height / 6)
local width = math.random()*3+2
table.insert(placements,
{":line", 0, {sx, sy, sz}, {mx, my, mz}, width})
table.insert(placements,
{":line", 0, {mx, my, mz}, {ex, ey, ez}, width})
for i=1,10 do
local dx = math.sin(dir) * 10
local dz = -math.cos(dir) * 10
local ex = sx + dx
local ey = sy + elevation
local ez = sz + dz
table.insert(placements,
{":line", 0, {sx, sy, sz}, {ex, ey, ez}, width})
sx = ex
sy = ey
sz = ez
dir_inertia = dir_inertia * 0.8 + (math.random() - 0.5) * math.pow(math.random(), 2) * 8
elevation = elevation * 0.9 + (math.random() - 0.4) * (1.0-math.pow(math.random(), 4)) * 8
dir = dir + dir_inertia
end
end
return placements
end

View File

@ -196,6 +196,7 @@ void ContentLoader::loadGenerator(
map.at("biome-bpd").get(def.biomesBPD);
map.at("heights-bpd").get(def.heightsBPD);
map.at("sea_level").get(def.seaLevel);
map.at("wide-structs-chunks-radius").get(def.wideStructsChunksRadius);
auto folder = generatorsDir / fs::u8path(name + ".files");
auto scriptFile = folder / fs::u8path("script.lua");

View File

@ -204,6 +204,10 @@ struct GeneratorDef {
/// @brief Heightmap blocks per dot
uint heightsBPD = 4;
/// @brief Number of chunks must be generated before and after wide
/// structures placement triggered
uint wideStructsChunksRadius = 3;
std::unordered_map<std::string, size_t> structuresIndices;
std::vector<std::unique_ptr<VoxelStructure>> structures;
std::vector<Biome> biomes;

View File

@ -17,16 +17,20 @@
static debug::Logger logger("world-generator");
static inline constexpr uint MAX_PARAMETERS = 4;
static inline constexpr uint MAX_CHUNK_PROTOTYPE_LEVELS = 10;
static inline constexpr uint BASIC_PROTOTYPE_LAYERS = 5;
WorldGenerator::WorldGenerator(
const GeneratorDef& def, const Content* content, uint64_t seed
)
: def(def),
content(content),
seed(seed),
surroundMap(0, MAX_CHUNK_PROTOTYPE_LEVELS)
seed(seed),
surroundMap(0, BASIC_PROTOTYPE_LAYERS + def.wideStructsChunksRadius * 2)
{
uint levels = BASIC_PROTOTYPE_LAYERS + def.wideStructsChunksRadius * 2;
surroundMap = SurroundMap(0, levels);
logger.info() << "total number of prototype levels is " << levels;
surroundMap.setOutCallback([this](int const x, int const z, int8_t) {
const auto& found = prototypes.find({x, z});
if (found == prototypes.end()) {
@ -41,16 +45,17 @@ WorldGenerator::WorldGenerator(
}
prototypes[{x, z}] = generatePrototype(x, z);
});
surroundMap.setLevelCallback(4, [this](int const x, int const z) {
surroundMap.setLevelCallback(def.wideStructsChunksRadius + 1,
[this](int const x, int const z) {
generateStructuresWide(requirePrototype(x, z), x, z);
});
surroundMap.setLevelCallback(7, [this](int const x, int const z) {
surroundMap.setLevelCallback(levels-3, [this](int const x, int const z) {
generateBiomes(requirePrototype(x, z), x, z);
});
surroundMap.setLevelCallback(8, [this](int const x, int const z) {
surroundMap.setLevelCallback(levels-2, [this](int const x, int const z) {
generateHeightmap(requirePrototype(x, z), x, z);
});
surroundMap.setLevelCallback(9, [this](int const x, int const z) {
surroundMap.setLevelCallback(levels-1, [this](int const x, int const z) {
generateStructures(requirePrototype(x, z), x, z);
});
for (int i = 0; i < def.structures.size(); i++) {
@ -180,8 +185,10 @@ void WorldGenerator::placeLine(const LinePlacement& line) {
int czb = floordiv(aabb.b.z, CHUNK_D);
for (int cz = cza; cz <= czb; cz++) {
for (int cx = cxa; cx <= cxb; cx++) {
auto& otherPrototype = requirePrototype(cx, cz);
otherPrototype.lines.push_back(line);
const auto& found = prototypes.find({cx, cz});
if (found != prototypes.end()) {
found->second->lines.push_back(line);
}
}
}
}