diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-07-12 12:29:22 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-07-12 12:29:22 +0200 |
commit | ec2631eca3a397dffd2e525b34c131c283beb167 (patch) | |
tree | cd3fafd70074bf29af3e507b7e9dbd879fe9a2a4 | |
parent | 9a7a83ef3074faaad037cfb4c098784695f49d30 (diff) |
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)
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 13 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureGroups.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureGroups.h | 8 | ||||
-rw-r--r-- | src/server/game/Maps/ZoneScript.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Maps/ZoneScript.h | 12 |
5 files changed, 63 insertions, 6 deletions
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<Creature*, FormationInfo*> _members; + + using MembersMap = std::unordered_map<Creature*, FormationInfo*>; + 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() diff --git a/src/server/game/Maps/ZoneScript.cpp b/src/server/game/Maps/ZoneScript.cpp index 03ddf65e6cb..599847d911a 100644 --- a/src/server/game/Maps/ZoneScript.cpp +++ b/src/server/game/Maps/ZoneScript.cpp @@ -19,6 +19,13 @@ #include "Creature.h" #include "GameEventSender.h" +ControlZoneHandler::ControlZoneHandler() = default; +ControlZoneHandler::ControlZoneHandler(ControlZoneHandler const& right) = default; +ControlZoneHandler::ControlZoneHandler(ControlZoneHandler&& right) noexcept = default; +ControlZoneHandler& ControlZoneHandler::operator=(ControlZoneHandler const& right) = default; +ControlZoneHandler& ControlZoneHandler::operator=(ControlZoneHandler&& right) noexcept = default; +ControlZoneHandler::~ControlZoneHandler() = default; + ZoneScript::ZoneScript() = default; ZoneScript::ZoneScript(ZoneScript const& right) = default; ZoneScript::ZoneScript(ZoneScript&& right) noexcept = default; diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h index 3fd9e85aa19..8f37b2a3cf5 100644 --- a/src/server/game/Maps/ZoneScript.h +++ b/src/server/game/Maps/ZoneScript.h @@ -23,6 +23,7 @@ class AreaTrigger; class Creature; +class CreatureGroup; class GameObject; class Player; class Unit; @@ -41,8 +42,12 @@ enum class EncounterType : uint8 class TC_GAME_API ControlZoneHandler { public: - explicit ControlZoneHandler() = default; - virtual ~ControlZoneHandler() = default; + explicit ControlZoneHandler(); + ControlZoneHandler(ControlZoneHandler const& right); + ControlZoneHandler(ControlZoneHandler&& right) noexcept; + ControlZoneHandler& operator=(ControlZoneHandler const& right); + ControlZoneHandler& operator=(ControlZoneHandler&& right) noexcept; + virtual ~ControlZoneHandler(); virtual void HandleCaptureEventHorde([[maybe_unused]] GameObject* controlZone) { } virtual void HandleCaptureEventAlliance([[maybe_unused]] GameObject* controlZone) { } @@ -79,6 +84,9 @@ class TC_GAME_API ZoneScript virtual void OnUnitDeath([[maybe_unused]] Unit* unit) { } + // Triggers when the CreatureGroup no longer has any alive members (either last alive member dies or is removed from the group) + virtual void OnCreatureGroupDepleted([[maybe_unused]] CreatureGroup const* creatureGroup) { } + //All-purpose data storage ObjectGuid virtual ObjectGuid GetGuidData(uint32 /*DataId*/) const { return ObjectGuid::Empty; } virtual void SetGuidData(uint32 /*DataId*/, ObjectGuid /*Value*/) { } |