From ec2631eca3a397dffd2e525b34c131c283beb167 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 12 Jul 2024 12:29:22 +0200 Subject: Core/Instances: New ZoneScript hook - OnCreatureGroupDepleted * Triggers when the CreatureGroup no longer has any alive members (either last alive member dies or is removed from the group) --- src/server/game/Entities/Creature/Creature.cpp | 13 +++++++--- .../game/Entities/Creature/CreatureGroups.cpp | 29 ++++++++++++++++++++++ src/server/game/Entities/Creature/CreatureGroups.h | 8 +++++- 3 files changed, 46 insertions(+), 4 deletions(-) (limited to 'src/server/game/Entities/Creature') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d466920c81f..9b3a159e2f7 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -362,7 +362,7 @@ void Creature::RemoveFromWorld() GetZoneScript()->OnCreatureRemove(this); if (m_formation) - sFormationMgr->RemoveCreatureFromGroup(m_formation, this); + FormationMgr::RemoveCreatureFromGroup(m_formation, this); Unit::RemoveFromWorld(); @@ -2216,8 +2216,15 @@ void Creature::setDeathState(DeathState s) SetNoSearchAssistance(false); //Dismiss group if is leader - if (m_formation && m_formation->GetLeader() == this) - m_formation->FormationReset(true); + if (m_formation) + { + if (m_formation->GetLeader() == this) + m_formation->FormationReset(true); + + if (ZoneScript* script = GetZoneScript()) + if (!m_formation->HasAliveMembers()) + script->OnCreatureGroupDepleted(m_formation); + } bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater() && !HasUnitState(UNIT_STATE_ROOT); SetHover(false, false); diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 4f04f26ea90..179e3c5179f 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -25,6 +25,7 @@ #include "MotionMaster.h" #include "MovementGenerator.h" #include "ObjectMgr.h" +#include "ZoneScript.h" FormationMgr::FormationMgr() = default; FormationMgr::~FormationMgr() = default; @@ -74,6 +75,12 @@ void FormationMgr::RemoveCreatureFromGroup(CreatureGroup* group, Creature* membe TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: {} from group {}", leaderSpawnId, member->GetSpawnId()); group->RemoveMember(member); + // If removed member was alive we need to check if we have any other alive members + // if not - fire OnCreatureGroupDepleted + if (ZoneScript* script = member->GetZoneScript()) + if (member->IsAlive() && !group->HasAliveMembers()) + script->OnCreatureGroupDepleted(group); + if (group->IsEmpty()) { if (leaderSpawnId) @@ -302,3 +309,25 @@ bool CreatureGroup::CanLeaderStartMoving() const return true; } + +bool CreatureGroup::HasAliveMembers() const +{ + return std::ranges::any_of(_members, [](Creature const* member) { return member->IsAlive(); }, &MembersMap::value_type::first); +} + +bool CreatureGroup::LeaderHasStringId(std::string_view id) const +{ + if (_leader) + return _leader->HasStringId(id); + + if (CreatureData const* leaderCreatureData = sObjectMgr->GetCreatureData(_leaderSpawnId)) + { + if (leaderCreatureData->StringId == id) + return true; + + if (ASSERT_NOTNULL(sObjectMgr->GetCreatureTemplate(leaderCreatureData->id))->StringId == id) + return true; + } + + return false; +} diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index be8a9967bf5..c7afaa1cedd 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -74,7 +74,9 @@ class TC_GAME_API CreatureGroup { private: Creature* _leader; - std::unordered_map _members; + + using MembersMap = std::unordered_map; + MembersMap _members; ObjectGuid::LowType _leaderSpawnId; bool _formed; @@ -103,6 +105,10 @@ class TC_GAME_API CreatureGroup void LeaderStartedMoving(); void MemberEngagingTarget(Creature* member, Unit* target); bool CanLeaderStartMoving() const; + + bool HasAliveMembers() const; + + bool LeaderHasStringId(std::string_view id) const; }; #define sFormationMgr FormationMgr::instance() -- cgit v1.2.3