diff options
author | paramat <paramat@users.noreply.github.com> | 2017-06-11 06:02:20 +0100 |
---|---|---|
committer | paramat <mat.gregory@virginmedia.com> | 2017-06-19 02:20:04 +0100 |
commit | ea4d407082dd120bb6b3b1e9c869e88f26b001b1 (patch) | |
tree | a1ca192ae4ef304e30e7638fd553b71b691baa0a | |
parent | 8f2e60a9619f3db2dea752626e778f753c0714bc (diff) | |
download | minetest-ea4d407082dd120bb6b3b1e9c869e88f26b001b1.tar.gz minetest-ea4d407082dd120bb6b3b1e9c869e88f26b001b1.tar.bz2 minetest-ea4d407082dd120bb6b3b1e9c869e88f26b001b1.zip |
Mgv7 spawn search: Cope with extreme custom terrain and biome 'dust'
Previously, maximum spawn level was set to 'water_level + 16'. This would result
in spawn search failing if terrain had been customised to be much higher than
'water_level' at all points.
Also raise spawn level by 1 node to avoid spawning half-buried in a biome 'dust'
node such as 'default:snowblock'.
-rw-r--r-- | src/mapgen_v7.cpp | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 2048da1fe..ad242ae49 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -202,10 +202,7 @@ void MapgenV7Params::writeParams(Settings *settings) const int MapgenV7::getSpawnLevelAtPoint(v2s16 p) { - // Base terrain calculation - s16 y = baseTerrainLevelAtPoint(p.X, p.Y); - - // If enabled, check if inside a river + // If rivers are enabled, first check if in a river if (spflags & MGV7_RIDGES) { float width = 0.2; float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2; @@ -213,28 +210,41 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point } - // If mountains are disabled, terrain level is base terrain level - // Avoids spawn on non-existant mountain terrain + // Terrain noise 'offset' is the average level of that terrain. + // At least 50% of terrain will be below the higher of base and alt terrain + // 'offset's. + // Raising the maximum spawn level above 'water_level + 16' is necessary + // for when terrain 'offset's are set much higher than water_level. + s16 max_spawn_y = MYMAX(MYMAX(noise_terrain_alt->np.offset, + noise_terrain_base->np.offset), + water_level + 16); + // Base terrain calculation + s16 y = baseTerrainLevelAtPoint(p.X, p.Y); + + // If mountains are disabled, terrain level is base terrain level. + // Avoids mid-air spawn where mountain terrain would have been. if (!(spflags & MGV7_MOUNTAINS)) { - if (y <= water_level || y > water_level + 16) + if (y <= water_level || y > max_spawn_y) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point else - return y; + // + 1 to not be half-buried in a potential node-deep biome 'dust' + return y + 1; } - // Mountain terrain calculation - int iters = 128; - while (iters--) { + // Search upwards for first node without mountain terrain + int iters = 256; + while (iters > 0 && y <= max_spawn_y) { if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // If air above - if (y <= water_level || y > water_level + 16) + if (y <= water_level || y > max_spawn_y) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point else - return y; + return y + 1; } y++; + iters--; } - // Unsuitable spawn point, no mountain surface found + // Unsuitable spawn point return MAX_MAP_GENERATION_LIMIT; } |