diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 7868fff6a..8ad8ab245 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -18,6 +18,7 @@ #include "Creature.h" #include "CreatureAI.h" #include "CreatureAIImpl.h" +#include "CreatureGroups.h" #include "CreatureTextMgr.h" #include "Log.h" #include "MapReference.h" @@ -292,7 +293,9 @@ bool CreatureAI::UpdateVictim() bool CreatureAI::_EnterEvadeMode() { if (!me->IsAlive()) + { return false; + } // don't remove vehicle auras, passengers aren't supposed to drop off the vehicle // don't remove clone caster on evade (to be verified) @@ -308,8 +311,15 @@ bool CreatureAI::_EnterEvadeMode() me->SetLastDamagedTime(0); me->SetCannotReachTarget(false); + if (CreatureGroup* formation = me->GetFormation()) + { + formation->MemberEvaded(me); + } + if (me->IsInEvadeMode()) + { return false; + } return true; } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 9f1983fdc..a62813dac 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -330,7 +330,8 @@ public: void UpdateWaypointID(uint32 wpID) { m_waypointID = wpID; } void SearchFormation(); - [[nodiscard]] CreatureGroup* GetFormation() const { return m_formation; } + [[nodiscard]] CreatureGroup const* GetFormation() const { return m_formation; } + [[nodiscard]] CreatureGroup* GetFormation() { return m_formation; } void SetFormation(CreatureGroup* formation) { m_formation = formation; } Unit* SelectVictim(); diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index e53dafc7e..86ffb9ca1 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -226,6 +226,47 @@ void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) } } +void CreatureGroup::MemberEvaded(Creature* member) +{ + uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI; + if (!(groupAI & std::underlying_type_t(GroupAIFlags::GROUP_AI_FLAG_EVADE_TOGETHER))) + { + return; + } + + for (auto const& itr : m_members) + { + Creature* pMember = itr.first; + + //Skip one check + if (pMember == member) + { + continue; + } + + if (!pMember->IsAlive()) + { + continue; + } + + if (pMember->IsInEvadeMode()) + { + continue; + } + + if (itr.second.HasGroupFlag(std::underlying_type_t(GroupAIFlags::GROUP_AI_FLAG_EVADE_TOGETHER))) + { + if (pMember->IsAIEnabled) + { + if (CreatureAI* pMemberAI = pMember->AI()) + { + pMemberAI->EnterEvadeMode(); + } + } + } + } +} + void CreatureGroup::FormationReset(bool dismiss, bool initMotionMaster) { if (m_members.size() && !(m_members.begin()->second.HasGroupFlag(std::underlying_type_t(GroupAIFlags::GROUP_AI_FLAG_FOLLOW_LEADER)))) diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index 571df399f..35c945b3c 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -30,7 +30,7 @@ enum class GroupAIFlags : uint16 { GROUP_AI_FLAG_MEMBER_ASSIST_LEADER = 0x001, GROUP_AI_FLAG_LEADER_ASSIST_MEMBER = 0x002, - //GROUP_AI_FLAG_UNK1 = 0x004, + GROUP_AI_FLAG_EVADE_TOGETHER = 0x004, //GROUP_AI_FLAG_UNK2 = 0x008, //GROUP_AI_FLAG_UNK3 = 0x010, //GROUP_AI_FLAG_UNK4 = 0x020, @@ -40,7 +40,7 @@ enum class GroupAIFlags : uint16 GROUP_AI_FLAG_FOLLOW_LEADER = 0x200, // Used to verify valid and usable flags - GROUP_AI_FLAG_SUPPORTED = GROUP_AI_FLAG_MEMBER_ASSIST_LEADER | GROUP_AI_FLAG_LEADER_ASSIST_MEMBER | GROUP_AI_FLAG_FOLLOW_LEADER + GROUP_AI_FLAG_SUPPORTED = GROUP_AI_FLAG_MEMBER_ASSIST_LEADER | GROUP_AI_FLAG_LEADER_ASSIST_MEMBER | GROUP_AI_FLAG_EVADE_TOGETHER | GROUP_AI_FLAG_FOLLOW_LEADER }; struct FormationInfo @@ -103,6 +103,7 @@ public: void LeaderMoveTo(float x, float y, float z, bool run); void MemberAttackStart(Creature* member, Unit* target); + void MemberEvaded(Creature* member); private: Creature* m_leader; //Important do not forget sometimes to work with pointers instead synonims :D:D