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)
This commit is contained in:
Shauren
2024-07-12 12:29:22 +02:00
parent 9a7a83ef30
commit ec2631eca3
5 changed files with 63 additions and 6 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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()

View File

@@ -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;

View File

@@ -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*/) { }