From fbf5cf7aa61a48f916afd81ac7e282eac8d50e6f Mon Sep 17 00:00:00 2001 From: Cocosushi6 Date: Thu, 3 May 2018 20:25:08 +0200 Subject: Generate cacti and sugarcane with different heights (#4137) When generating foliage, create cacti with height in the interval [1; MaxCactusHeight] and sugarcane with height in [1; MaxSugarcaneHeight] (with MaxCactusHeight and MaxSugarcaneHeight declared in world.ini) Fixes #4135 --- src/Generating/FinishGen.cpp | 105 ++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 25 deletions(-) (limited to 'src/Generating/FinishGen.cpp') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 8c54be0d0..ec5c0c144 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -671,24 +671,66 @@ void cFinishGenVines::GenFinish(cChunkDesc & a_ChunkDesc) //////////////////////////////////////////////////////////////////////////////// // cFinishGenSprinkleFoliage: -bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ) +bool cFinishGenSprinkleFoliage::TryAddCactus(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ) { + if (!IsDesertVariant(a_ChunkDesc.GetBiome(a_RelX, a_RelZ))) + { + return false; + } + + int CactusHeight = 1 + (m_Noise.IntNoise2DInt(a_RelX, a_RelZ) % m_MaxCactusHeight); + + // We'll be doing comparison with blocks above, so the coords should be 1 block away from chunk top + if (a_RelY + CactusHeight >= cChunkDef::Height - 1) + { + CactusHeight = cChunkDef::Height - a_RelY - 1; + } + // We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges: if ( - (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || - (a_RelY < 1) || (a_RelY >= cChunkDef::Height - 2) || - (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1) + (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || + (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1) ) { return false; } - // Only allow dirt, grass or sand below sugarcane: + for (int i = 0; i < CactusHeight; i++) + { + const bool cactusExists = i != 0; + + const int y = a_RelY + 1; + if ( + cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX + 1, y, a_RelZ)) || + cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX - 1, y, a_RelZ)) || + cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX, y, a_RelZ + 1)) || + cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX, y, a_RelZ - 1)) + ) + { + return cactusExists; + } + + // All conditions are met, we can place a cactus here + a_ChunkDesc.SetBlockType(a_RelX, ++a_RelY, a_RelZ, E_BLOCK_CACTUS); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// cFinishGenSprinkleFoliage: + +bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ) +{ + int SugarcaneHeight = 1 + (m_Noise.IntNoise2DInt(a_RelX, a_RelZ) % m_MaxSugarcaneHeight); + + // Only allow dirt, grass, sand and sugarcane below sugarcane: switch (a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ)) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_SAND: + case E_BLOCK_SUGARCANE: { break; } @@ -698,19 +740,39 @@ bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_ } } - // Water is required next to the block below the sugarcane: + // We'll be doing comparison with blocks above, so the coords should be 1 block away from chunk top + if (a_RelY + SugarcaneHeight >= cChunkDef::Height - 1) + { + SugarcaneHeight = cChunkDef::Height - a_RelY - 1; + } + + // We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges: + if ( + (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || + (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1) + ) + { + return false; + } + + // Water is required next to the block below the sugarcane (if the block below isn't sugarcane already) if ( !IsWater(a_ChunkDesc.GetBlockType(a_RelX - 1, a_RelY, a_RelZ)) && !IsWater(a_ChunkDesc.GetBlockType(a_RelX + 1, a_RelY, a_RelZ)) && !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ - 1)) && - !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ + 1)) + !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ + 1)) && + a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ) != E_BLOCK_SUGARCANE ) { return false; } - // All conditions met, place a sugarcane here: - a_ChunkDesc.SetBlockType(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_SUGARCANE); + for (int i = 0; i < SugarcaneHeight; i++) + { + // All conditions met, place a sugarcane here + a_ChunkDesc.SetBlockType(a_RelX, ++a_RelY, a_RelZ, E_BLOCK_SUGARCANE); + } + return true; } @@ -778,7 +840,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) } else if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) { - ++Top; + // Checks and block placing are handled in the TryAddSugarcane method } else if ((val1 > 0.5) && (val2 < -0.5)) { @@ -789,29 +851,22 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) case E_BLOCK_SAND: { - int y = Top + 1; - if ( - (x > 0) && (x < cChunkDef::Width - 1) && - (z > 0) && (z < cChunkDef::Width - 1) && - (val1 + val2 > 0.5f) && - (a_ChunkDesc.GetBlockType(x + 1, y, z) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x - 1, y, z) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x, y, z + 1) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x, y, z - 1) == E_BLOCK_AIR) && - IsDesertVariant(a_ChunkDesc.GetBiome(x, z)) - ) + if (val1 + val2 > 0.5f) { - a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_CACTUS); + if (!TryAddCactus(a_ChunkDesc, x, Top, z)) + { + TryAddSugarcane(a_ChunkDesc, x, Top, z); + } } - else if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) + else { - ++Top; + TryAddSugarcane(a_ChunkDesc, x, Top, z); } break; } } // switch (TopBlock) a_ChunkDesc.SetHeight(x, z, Top); - } // for y + } // for x } // for z } -- cgit v1.2.3