summaryrefslogtreecommitdiffstats
path: root/src/Blocks/BlockStems.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Blocks/BlockStems.h')
-rw-r--r--src/Blocks/BlockStems.h169
1 files changed, 109 insertions, 60 deletions
diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h
index be64d81f8..fa80d4127 100644
--- a/src/Blocks/BlockStems.h
+++ b/src/Blocks/BlockStems.h
@@ -24,7 +24,32 @@ private:
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cEntity * a_Digger, const cItem * a_Tool) const override
{
- return cItem(StemPickupType, 1, 0);
+ /*
+ Use correct percent:
+ https://minecraft.gamepedia.com/Melon_Seeds#Breaking
+ https://minecraft.gamepedia.com/Pumpkin_Seeds#Breaking
+ */
+
+ // Age > 7 (Impossible)
+ if (a_BlockMeta > 7)
+ {
+ return cItem(StemPickupType);
+ }
+
+ const auto Threshold = GetRandomProvider().RandReal<double>(100);
+ double Cumulative = 0;
+ char Count = 0;
+
+ for (; Count < 4; Count++)
+ {
+ Cumulative += m_AgeSeedDropProbability[static_cast<size_t>(a_BlockMeta)][static_cast<size_t>(Count)];
+ if (Cumulative > Threshold)
+ {
+ break;
+ }
+ }
+
+ return cItem(StemPickupType, Count);
}
@@ -52,60 +77,51 @@ private:
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
{
- auto oldMeta = a_Chunk.GetMeta(a_RelPos);
- auto meta = oldMeta + a_NumStages;
- a_Chunk.SetBlock(a_RelPos, m_BlockType, static_cast<NIBBLETYPE>(std::min(meta, 7))); // Update the stem
- if (meta > 7)
- {
- if (growProduce(a_Chunk, a_RelPos))
- {
- return 8 - oldMeta;
- }
- else
- {
- return 7 - oldMeta;
- }
- }
- return meta - oldMeta;
+ const auto OldMeta = a_Chunk.GetMeta(a_RelPos);
+ const auto NewMeta = std::clamp<NIBBLETYPE>(static_cast<NIBBLETYPE>(OldMeta + a_NumStages), 0, 7);
+ a_Chunk.SetMeta(a_RelPos, NewMeta);
+ return NewMeta - OldMeta;
}
- /** Grows the final produce next to the stem at the specified pos.
- Returns true if successful, false if not. */
- static bool growProduce(cChunk & a_Chunk, Vector3i a_StemRelPos)
+
+
+
+
+ virtual void BearFruit(cChunk & a_Chunk, const Vector3i a_StemRelPos) const override
{
- auto & random = GetRandomProvider();
+ auto & Random = GetRandomProvider();
// Check if there's another produce around the stem, if so, abort:
- static const Vector3i neighborOfs[] =
+ static constexpr std::array<Vector3i, 4> NeighborOfs =
{
- { 1, 0, 0},
- {-1, 0, 0},
- { 0, 0, 1},
- { 0, 0, -1},
+ {
+ { 1, 0, 0},
+ {-1, 0, 0},
+ { 0, 0, 1},
+ { 0, 0, -1},
+ }
};
- bool isValid;
- BLOCKTYPE blockType[4];
- NIBBLETYPE blockMeta; // unused
- isValid = a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[0], blockType[0], blockMeta);
- isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[1], blockType[1], blockMeta);
- isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[2], blockType[2], blockMeta);
- isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[3], blockType[3], blockMeta);
+
+ std::array<BLOCKTYPE, 4> BlockType;
if (
- !isValid ||
- (blockType[0] == ProduceBlockType) ||
- (blockType[1] == ProduceBlockType) ||
- (blockType[2] == ProduceBlockType) ||
- (blockType[3] == ProduceBlockType)
+ !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[0], BlockType[0]) ||
+ !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[1], BlockType[1]) ||
+ !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[2], BlockType[2]) ||
+ !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[3], BlockType[3]) ||
+ (BlockType[0] == ProduceBlockType) ||
+ (BlockType[1] == ProduceBlockType) ||
+ (BlockType[2] == ProduceBlockType) ||
+ (BlockType[3] == ProduceBlockType)
)
{
- // Neighbors not valid or already taken by the same produce
- return false;
+ // Neighbors not valid or already taken by the same produce:
+ return;
}
// Pick a direction in which to place the produce:
int x = 0, z = 0;
- int checkType = random.RandInt(3); // The index to the neighbors array which should be checked for emptiness
- switch (checkType)
+ const auto CheckType = Random.RandInt<size_t>(3); // The index to the neighbors array which should be checked for emptiness
+ switch (CheckType)
{
case 0: x = 1; break;
case 1: x = -1; break;
@@ -114,7 +130,7 @@ private:
}
// Check that the block in that direction is empty:
- switch (blockType[checkType])
+ switch (BlockType[CheckType])
{
case E_BLOCK_AIR:
case E_BLOCK_SNOW:
@@ -123,39 +139,72 @@ private:
{
break;
}
- default: return false;
+ default: return;
}
// Check if there's soil under the neighbor. We already know the neighbors are valid. Place produce if ok
- BLOCKTYPE soilType;
- auto produceRelPos = a_StemRelPos + Vector3i(x, 0, z);
- VERIFY(a_Chunk.UnboundedRelGetBlock(produceRelPos.addedY(-1), soilType, blockMeta));
- switch (soilType)
+ BLOCKTYPE SoilType;
+ const auto ProduceRelPos = a_StemRelPos + Vector3i(x, 0, z);
+ VERIFY(a_Chunk.UnboundedRelGetBlockType(ProduceRelPos.addedY(-1), SoilType));
+
+ switch (SoilType)
{
case E_BLOCK_DIRT:
case E_BLOCK_GRASS:
case E_BLOCK_FARMLAND:
{
- // Place a randomly-facing produce:
- NIBBLETYPE meta = (ProduceBlockType == E_BLOCK_MELON) ? 0 : static_cast<NIBBLETYPE>(random.RandInt(4) % 4);
- auto produceAbsPos = a_Chunk.RelativeToAbsolute(produceRelPos);
+ const NIBBLETYPE Meta = (ProduceBlockType == E_BLOCK_MELON) ? 0 : static_cast<NIBBLETYPE>(Random.RandInt(4) % 4);
+
FLOGD("Growing melon / pumpkin at {0} (<{1}, {2}> from stem), overwriting {3}, growing on top of {4}, meta {5}",
- produceAbsPos,
+ a_Chunk.RelativeToAbsolute(ProduceRelPos),
x, z,
- ItemTypeToString(blockType[checkType]),
- ItemTypeToString(soilType),
- meta
+ ItemTypeToString(BlockType[CheckType]),
+ ItemTypeToString(SoilType),
+ Meta
);
- a_Chunk.GetWorld()->SetBlock(produceAbsPos, ProduceBlockType, meta);
- return true;
+
+ // Place a randomly-facing produce:
+ a_Chunk.SetBlock(ProduceRelPos, ProduceBlockType, Meta);
}
}
- return false;
}
+
+private:
+
+ // https://minecraft.gamepedia.com/Pumpkin_Seeds#Breaking
+ // https://minecraft.gamepedia.com/Melon_Seeds#Breaking
+ /** The array describes how many seed may be dropped at which age. The inner arrays describe the probability to drop 0, 1, 2, 3 seeds.
+ The outer describes the age of the stem. */
+ static constexpr std::array<std::array<double, 4>, 8> m_AgeSeedDropProbability
+ {
+ {
+ {
+ 81.3, 17.42, 1.24, 0.03
+ },
+ {
+ 65.1, 30.04, 4.62, 0.24
+ },
+ {
+ 51.2, 38.4, 9.6, 0.8
+ },
+ {
+ 39.44, 43.02, 15.64, 1.9
+ },
+ {
+ 29.13, 44.44, 22.22, 3.7
+ },
+ {
+ 21.6, 43.2, 28.8, 6.4
+ },
+ {
+ 15.17, 39.82, 34.84, 10.16
+ },
+ {
+ 10.16, 34.84, 39.82, 15.17
+ }
+ }
+ };
} ;
using cBlockMelonStemHandler = cBlockStemsHandler<E_BLOCK_MELON, E_ITEM_MELON_SEEDS>;
using cBlockPumpkinStemHandler = cBlockStemsHandler<E_BLOCK_PUMPKIN, E_ITEM_PUMPKIN_SEEDS>;
-
-
-