From e7331fe8205f798a7b453961feb38aea64d55b47 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 20 Dec 2020 02:14:17 +0000 Subject: [PATCH] Improve Silverfish search * Start from the inside out, don't always look at the entire search space by bailing out randomly --- src/Mobs/Silverfish.cpp | 107 +++++++++++++++++++++++++++------------- src/Mobs/Silverfish.h | 5 +- 2 files changed, 75 insertions(+), 37 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; - } - auto Blocks = sSetBlockVector(); - for (int X = static_cast(GetPosX() - 10); X <= static_cast(GetPosX() + 10); X++) - { - for (int Y = static_cast(GetPosY() - 5); Y <= static_cast(GetPosY() + 5); Y++) + if ((a_TDI.DamageType != dtPoison) && (a_TDI.DamageType != dtPotionOfHarming)) { - for (int Z = static_cast(GetPosZ() - 10); Z <= static_cast(GetPosZ() + 10); Z++) + // 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++) { - Blocks.emplace_back(sSetBlock({X, Y, Z}, 0, 0)); + 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; + } } } } - m_World->GetBlocks(Blocks, true); - for (const auto & BlockInfo : Blocks) - { - if (BlockInfo.m_BlockType == E_BLOCK_SILVERFISH_EGG) - { - m_World->DigBlock(BlockInfo.GetAbsolutePos(), nullptr); - } - } - 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; } ; - - - -