summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Mobs/Silverfish.cpp99
-rw-r--r--src/Mobs/Silverfish.h5
2 files changed, 71 insertions, 33 deletions
diff --git a/src/Mobs/Silverfish.cpp b/src/Mobs/Silverfish.cpp
index 9fb570341..43686344b 100644
--- a/src/Mobs/Silverfish.cpp
+++ b/src/Mobs/Silverfish.cpp
@@ -8,53 +8,94 @@
#include "../Blocks/BlockHandler.h"
#include "../Blocks/BlockInfested.h"
+
+
+
+
bool cSilverfish::DoTakeDamage(TakeDamageInfo &a_TDI)
{
- bool SuperResult = Super::DoTakeDamage(a_TDI);
- // Todo: stop this if /gamerule mobGriefing is set to false
+ // Call on our brethren to attack!
+ // TODO: stop this if /gamerule mobGriefing is set to false
- // If the entity didn't take andy damage
- if (!SuperResult)
+ // If the entity didn't take any damage, bail:
+ if (!Super::DoTakeDamage(a_TDI))
{
- return SuperResult;
+ return false;
}
- // Entity does receive lethal damage or Attacker doesn't exist
- if ((m_Health < a_TDI.FinalDamage) ||
- ((a_TDI.Attacker == nullptr) && (a_TDI.DamageType != dtPoison) && (a_TDI.DamageType != dtPotionOfHarming)))
+ // Or, conversely took lethal damage, bail:
+ if (m_Health <= 0)
{
- return SuperResult;
+ return true;
}
- // If attacker is player or splash potion
- bool ShouldSpawn = (
- (a_TDI.DamageType == dtPoison) || (a_TDI.DamageType == dtPotionOfHarming) ||
- a_TDI.Attacker->IsPlayer()
- );
-
- if (!ShouldSpawn)
+ if (a_TDI.Attacker == nullptr)
{
- return SuperResult;
+ if ((a_TDI.DamageType != dtPoison) && (a_TDI.DamageType != dtPotionOfHarming))
+ {
+ // Bail if attacker doesn't exist and it wasn't a splash potion:
+ return true;
+ }
}
- auto Blocks = sSetBlockVector();
- for (int X = static_cast<int>(GetPosX() - 10); X <= static_cast<int>(GetPosX() + 10); X++)
+ 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++)
{
- for (int Y = static_cast<int>(GetPosY() - 5); Y <= static_cast<int>(GetPosY() + 5); Y++)
+ const int HalfSide = CubeSideLength / 2;
+
+ for (int OffsetX = -HalfSide; OffsetX <= HalfSide; OffsetX++)
{
- for (int Z = static_cast<int>(GetPosZ() - 10); Z <= static_cast<int>(GetPosZ() + 10); Z++)
+ for (int OffsetZ = -HalfSide; OffsetZ <= HalfSide; OffsetZ++)
{
- Blocks.emplace_back(sSetBlock({X, Y, Z}, 0, 0));
+ if (CheckInfested({ OffsetX, +HalfSide, OffsetZ }) || CheckInfested({ OffsetX, -HalfSide, OffsetZ }))
+ {
+ return true;
+ }
}
}
- }
- m_World->GetBlocks(Blocks, true);
- for (const auto & BlockInfo : Blocks)
- {
- if (BlockInfo.m_BlockType == E_BLOCK_SILVERFISH_EGG)
+
+ for (int OffsetX = -HalfSide; OffsetX <= HalfSide; OffsetX++)
{
- m_World->DigBlock(BlockInfo.GetAbsolutePos(), nullptr);
+ 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 SuperResult;
+ return true;
}
diff --git a/src/Mobs/Silverfish.h b/src/Mobs/Silverfish.h
index 78137701a..a9d3d2860 100644
--- a/src/Mobs/Silverfish.h
+++ b/src/Mobs/Silverfish.h
@@ -18,11 +18,8 @@ public:
Super("Silverfish", mtSilverfish, "entity.silverfish.hurt", "entity.silverfish.death", "entity.silverfish.ambient", 0.3, 0.4)
{
}
+
CLASS_PROTODEF(cSilverfish)
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
} ;
-
-
-
-