#include "Globals.h"
#include "Silverfish.h"
#include "../World.h"
#include "../Chunk.h"
#include "../Blocks/BlockHandler.h"
#include "../Blocks/BlockInfested.h"
bool cSilverfish::DoTakeDamage(TakeDamageInfo &a_TDI)
{
// Call on our brethren to attack!
// TODO: stop this if /gamerule mobGriefing is set to false
// If the entity didn't take any damage, bail:
if (!Super::DoTakeDamage(a_TDI))
{
return false;
}
// Or, conversely took lethal damage, bail:
if (m_Health <= 0)
{
return true;
}
if (a_TDI.Attacker == nullptr)
{
if ((a_TDI.DamageType != dtPoison) && (a_TDI.DamageType != dtPotionOfHarming))
{
// Bail if attacker doesn't exist and it wasn't a splash potion:
return true;
}
}
else if (!a_TDI.Attacker->IsPlayer())
{
// Bail if it wasn't a player attack:
return true;
}
auto & Random = GetRandomProvider();
// Tries to spawn another Silverfish, returning if the search should continue.
auto CheckInfested = [this, &Random, Position = GetPosition().Floor()](const Vector3i Offset) mutable
{
const auto Block = Position + Offset;
if (m_World->GetBlock(Block) == E_BLOCK_SILVERFISH_EGG)
{
m_World->DigBlock(Block);
return Random.RandBool();
}
return false;
};
// Search the faces of an increasingly large cube (so the positions closest get looked at first)
// of min 3, max 10, for infested blocks and spawn additional reinforcements:
for (int CubeSideLength = 3; CubeSideLength <= 10; CubeSideLength++)
{
const int HalfSide = CubeSideLength / 2;
for (int OffsetX = -HalfSide; OffsetX <= HalfSide; OffsetX++)
{
for (int OffsetZ = -HalfSide; OffsetZ <= HalfSide; OffsetZ++)
{
if (CheckInfested({ OffsetX, +HalfSide, OffsetZ }) || CheckInfested({ OffsetX, -HalfSide, OffsetZ }))
{
return true;
}
}
}
for (int OffsetX = -HalfSide; OffsetX <= HalfSide; OffsetX++)
{
for (int OffsetY = -HalfSide + 1; OffsetY <= HalfSide - 1; OffsetY++)
{
if (CheckInfested({ OffsetX, OffsetY, +HalfSide }) || CheckInfested({ OffsetX, OffsetY, -HalfSide }))
{
return true;
}
}
}
for (int OffsetZ = -HalfSide + 1; OffsetZ <= HalfSide - 1; OffsetZ++)
{
for (int OffsetY = -HalfSide + 1; OffsetY <= HalfSide - 1; OffsetY++)
{
if (CheckInfested({ +HalfSide, OffsetY, OffsetZ }) || CheckInfested({ -HalfSide, OffsetY, OffsetZ }))
{
return true;
}
}
}
}
return true;
}