2019-10-16 04:06:34 -04:00
|
|
|
#pragma once
|
2015-08-19 12:45:53 -04:00
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
#include "BlockHandler.h"
|
2015-08-19 12:45:53 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
/** Base class for plants that use light values to decide whether to grow or not.
|
|
|
|
On block update, the plant decides whether to grow, die or stay as-is, based on the CanGrow() overridable method result. */
|
2019-10-16 04:06:34 -04:00
|
|
|
template <bool NeedsLightToGrow>
|
|
|
|
class cBlockPlant:
|
|
|
|
public cBlockHandler
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
2020-04-13 12:38:06 -04:00
|
|
|
using Super = cBlockHandler;
|
2019-10-16 04:06:34 -04:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
|
2015-08-19 12:45:53 -04:00
|
|
|
public:
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
cBlockPlant(BLOCKTYPE a_BlockType):
|
2020-04-13 12:38:06 -04:00
|
|
|
Super(a_BlockType)
|
2019-10-16 04:06:34 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-08-19 12:45:53 -04:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-17 05:36:37 -04:00
|
|
|
virtual void OnUpdate(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cBlockPluginInterface & a_PluginInterface,
|
|
|
|
cChunk & a_Chunk,
|
|
|
|
const Vector3i a_RelPos
|
|
|
|
) override
|
2019-10-11 05:02:53 -04:00
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
auto Action = CanGrow(a_Chunk, a_RelPos);
|
|
|
|
switch (Action)
|
2019-10-11 05:02:53 -04:00
|
|
|
{
|
|
|
|
case paGrowth:
|
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
Grow(a_Chunk, a_RelPos);
|
2019-10-11 05:02:53 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case paDeath:
|
|
|
|
{
|
2020-07-29 14:30:38 -04:00
|
|
|
a_ChunkInterface.SetBlock(a_Chunk.RelativeToAbsolute(a_RelPos), E_BLOCK_AIR, 0);
|
2019-10-11 05:02:53 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case paStay: break; // do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-08-19 12:45:53 -04:00
|
|
|
protected:
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
/** The action the plant can take on an update. */
|
2015-08-19 12:45:53 -04:00
|
|
|
enum PlantAction
|
|
|
|
{
|
|
|
|
paDeath,
|
|
|
|
paGrowth,
|
|
|
|
paStay
|
|
|
|
};
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-08-19 12:45:53 -04:00
|
|
|
/** Checks whether there is enough light for the plant to grow.
|
|
|
|
If the plant doesn't require light to grow, then it returns paGrowth.
|
|
|
|
If the plant requires light to grow and there is enough light, it returns paGrowth.
|
|
|
|
If the plant requires light to grow and there isn't enough light, it returns paStay.
|
2019-10-11 05:02:53 -04:00
|
|
|
If the plant requires light to grow and there is too little light, it returns paDeath. */
|
|
|
|
PlantAction HasEnoughLight(cChunk & a_Chunk, Vector3i a_RelPos)
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
|
|
|
// If the plant requires light to grow, check to see if there is enough light
|
|
|
|
// Otherwise, return true
|
2019-10-16 04:06:34 -04:00
|
|
|
if (!NeedsLightToGrow)
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
return paGrowth;
|
2015-08-19 12:45:53 -04:00
|
|
|
}
|
2019-10-11 05:02:53 -04:00
|
|
|
NIBBLETYPE Blocklight = a_Chunk.GetBlockLight(a_RelPos);
|
|
|
|
NIBBLETYPE SkyLight = a_Chunk.GetSkyLight (a_RelPos);
|
2019-10-16 04:06:34 -04:00
|
|
|
NIBBLETYPE Light = a_Chunk.GetTimeAlteredLight(SkyLight);
|
2015-08-19 12:45:53 -04:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
// If the amount of light provided by blocks is greater than the sky light, use it instead
|
|
|
|
if (Blocklight > Light)
|
|
|
|
{
|
|
|
|
Light = Blocklight;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Based on light levels, decide between growth, stay and death:
|
|
|
|
if (Light > 8)
|
|
|
|
{
|
|
|
|
return paGrowth;
|
|
|
|
}
|
|
|
|
else if ((Blocklight < 9) && (SkyLight < 9))
|
|
|
|
{
|
|
|
|
return paDeath;
|
|
|
|
}
|
|
|
|
|
|
|
|
return paStay;
|
2015-08-19 12:45:53 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-08-19 12:45:53 -04:00
|
|
|
/** Checks whether a plant can grow grow, based on what is returned from cBlockPlant::HasEnoughLight
|
|
|
|
and a random check based on what is returned from cBlockPlant::GetGrowthChance.
|
|
|
|
Can return three values.
|
|
|
|
paGrowth when the conditions are right for the plant to grow.
|
|
|
|
paStay when the conditions are not quite right.
|
|
|
|
paDeath is returned when there isn't enough light for the plant to survive.
|
|
|
|
Plants that don't require light will never have a paDeath returned
|
|
|
|
*/
|
2019-10-11 05:02:53 -04:00
|
|
|
virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos)
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
|
|
|
// Plant can grow if it has the required amount of light, and it passes a random chance based on surrounding blocks
|
2019-10-11 05:02:53 -04:00
|
|
|
auto action = HasEnoughLight(a_Chunk, a_RelPos);
|
|
|
|
if ((action == paGrowth) && !GetRandomProvider().RandBool(1.0 / GetGrowthChance(a_Chunk, a_RelPos)))
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
action = paStay;
|
2015-08-19 12:45:53 -04:00
|
|
|
}
|
2019-10-11 05:02:53 -04:00
|
|
|
return action;
|
2015-08-19 12:45:53 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
/** Generates an int value between 4 and 25 based on surrounding blocks that affect how quickly the plant grows.
|
2015-08-19 12:45:53 -04:00
|
|
|
The higher the value, the less likely the plant is to grow */
|
2019-10-11 05:02:53 -04:00
|
|
|
virtual int GetGrowthChance(cChunk & a_Chunk, Vector3i a_RelPos)
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
|
|
|
float Chance = 1.0f;
|
2019-10-11 05:02:53 -04:00
|
|
|
a_RelPos.y -= 1;
|
2015-08-19 12:45:53 -04:00
|
|
|
for (int x = -1; x < 2; ++x)
|
|
|
|
{
|
|
|
|
for (int z = -1; z < 2; ++z)
|
|
|
|
{
|
|
|
|
float Adjustment = 0.0f;
|
|
|
|
BLOCKTYPE Block;
|
|
|
|
NIBBLETYPE Meta;
|
|
|
|
|
|
|
|
// If the chunk we are trying to get the block information from is loaded
|
2019-10-11 05:02:53 -04:00
|
|
|
if (a_Chunk.UnboundedRelGetBlock(a_RelPos + Vector3i(x, 0, z), Block, Meta))
|
2015-08-19 12:45:53 -04:00
|
|
|
{
|
2017-07-03 12:34:27 -04:00
|
|
|
cBlockHandler * Handler = BlockHandler(Block);
|
2015-08-19 12:45:53 -04:00
|
|
|
|
|
|
|
// If the block affects growth, add to the adjustment
|
|
|
|
if (Handler->CanSustainPlant(m_BlockType))
|
|
|
|
{
|
|
|
|
Adjustment = 1.0f;
|
|
|
|
|
|
|
|
// Farmland alters the chance further if it is watered
|
|
|
|
if ((Block == E_BLOCK_FARMLAND) && (Meta != 0))
|
|
|
|
{
|
|
|
|
Adjustment = 3.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is not the block right underneath the plant, it has little effect on the growth
|
|
|
|
if ((x != 0) || (z != 0))
|
|
|
|
{
|
|
|
|
Adjustment /= 4.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
Chance += Adjustment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FloorC(24.0f / Chance) + 1;
|
|
|
|
}
|
|
|
|
};
|