aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-07-11 15:24:02 +0200
committerShauren <shauren.trinity@gmail.com>2024-07-11 15:24:02 +0200
commit16bfbe1a3a12256d9476f3ae23e1f34f31f9cf07 (patch)
treec257908a693de34cd3a25611ec596dad1f7c366f /src/server
parentc5c31c7c1efb26551b76a4046e9def8c5981864d (diff)
Core/Creatures: Allow adding summons to CreatureGroup (only adding, no formation movement of linked aggro yet)
Diffstat (limited to 'src/server')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.cpp136
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.h17
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_elwynn_forest.cpp2
5 files changed, 81 insertions, 78 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 38d55b98bfa..d466920c81f 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -390,7 +390,7 @@ void Creature::SearchFormation()
return;
if (FormationInfo const* formationInfo = sFormationMgr->GetFormationInfo(lowguid))
- sFormationMgr->AddCreatureToGroup(formationInfo->LeaderSpawnId, this);
+ FormationMgr::AddCreatureToGroup(formationInfo->LeaderSpawnId, this);
}
bool Creature::IsFormationLeader() const
diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp
index 940624c2b6e..4f04f26ea90 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.cpp
+++ b/src/server/game/Entities/Creature/CreatureGroups.cpp
@@ -26,15 +26,8 @@
#include "MovementGenerator.h"
#include "ObjectMgr.h"
-#define MAX_DESYNC 5.0f
-
-FormationMgr::FormationMgr()
-{
-}
-
-FormationMgr::~FormationMgr()
-{
-}
+FormationMgr::FormationMgr() = default;
+FormationMgr::~FormationMgr() = default;
FormationMgr* FormationMgr::instance()
{
@@ -46,18 +39,17 @@ void FormationMgr::AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creatur
{
Map* map = creature->GetMap();
- auto itr = map->CreatureGroupHolder.find(leaderSpawnId);
- if (itr != map->CreatureGroupHolder.end())
+ auto [itr, isNew] = map->CreatureGroupHolder.try_emplace(leaderSpawnId, nullptr);
+ if (!isNew)
{
//Add member to an existing group
- TC_LOG_DEBUG("entities.unit", "Group found: {}, inserting creature {}, Group InstanceID {}", leaderSpawnId, creature->GetGUID().ToString(), creature->GetInstanceId());
+ TC_LOG_DEBUG("entities.unit", "Group found: {}, inserting creature {}, Group InstanceID {}", leaderSpawnId, creature->GetGUID(), creature->GetInstanceId());
// With dynamic spawn the creature may have just respawned
// we need to find previous instance of creature and delete it from the formation, as it'll be invalidated
auto bounds = Trinity::Containers::MapEqualRange(map->GetCreatureBySpawnIdStore(), creature->GetSpawnId());
- for (auto const& pair : bounds)
+ for (auto const& [spawnId, other] : bounds)
{
- Creature* other = pair.second;
if (other == creature)
continue;
@@ -69,8 +61,7 @@ void FormationMgr::AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creatur
{
//Create new group
TC_LOG_DEBUG("entities.unit", "Group not found: {}. Creating new group.", leaderSpawnId);
- CreatureGroup* group = new CreatureGroup(leaderSpawnId);
- itr = map->CreatureGroupHolder.emplace(leaderSpawnId, group).first;
+ itr->second = new CreatureGroup(leaderSpawnId);
}
itr->second->AddMember(creature);
@@ -78,17 +69,21 @@ void FormationMgr::AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creatur
void FormationMgr::RemoveCreatureFromGroup(CreatureGroup* group, Creature* member)
{
- TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: {} from group {}", group->GetLeaderSpawnId(), member->GetSpawnId());
+ ObjectGuid::LowType leaderSpawnId = group->GetLeaderSpawnId();
+
+ TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: {} from group {}", leaderSpawnId, member->GetSpawnId());
group->RemoveMember(member);
if (group->IsEmpty())
{
- Map* map = member->GetMap();
+ if (leaderSpawnId)
+ {
+ Map* map = member->GetMap();
+ TC_LOG_DEBUG("entities.unit", "Deleting group with InstanceID {}", map->GetInstanceId());
+ std::size_t erased = map->CreatureGroupHolder.erase(leaderSpawnId);
+ ASSERT(erased, "Not registered group " UI64FMTD " in map %u", leaderSpawnId, map->GetId());
+ }
- TC_LOG_DEBUG("entities.unit", "Deleting group with InstanceID {}", member->GetInstanceId());
- auto itr = map->CreatureGroupHolder.find(group->GetLeaderSpawnId());
- ASSERT(itr != map->CreatureGroupHolder.end(), "Not registered group " UI64FMTD " in map %u", group->GetLeaderSpawnId(), map->GetId());
- map->CreatureGroupHolder.erase(itr);
delete group;
}
}
@@ -112,28 +107,14 @@ void FormationMgr::LoadCreatureFormations()
Field* fields = result->Fetch();
//Load group member data
- FormationInfo member;
- member.LeaderSpawnId = fields[0].GetUInt64();
+ ObjectGuid::LowType leaderSpawnId = fields[0].GetUInt64();
ObjectGuid::LowType memberSpawnId = fields[1].GetUInt64();
- member.FollowDist = 0.f;
- member.FollowAngle = 0.f;
-
- //If creature is group leader we may skip loading of dist/angle
- if (member.LeaderSpawnId != memberSpawnId)
- {
- member.FollowDist = fields[2].GetFloat();
- member.FollowAngle = fields[3].GetFloat() * float(M_PI) / 180.0f;
- }
-
- member.GroupAI = fields[4].GetUInt32();
- for (uint8 i = 0; i < 2; ++i)
- member.LeaderWaypointIDs[i] = fields[5 + i].GetUInt16();
// check data correctness
{
- if (!sObjectMgr->GetCreatureData(member.LeaderSpawnId))
+ if (!sObjectMgr->GetCreatureData(leaderSpawnId))
{
- TC_LOG_ERROR("sql.sql", "creature_formations table leader guid {} incorrect (not exist)", member.LeaderSpawnId);
+ TC_LOG_ERROR("sql.sql", "creature_formations table leader guid {} incorrect (not exist)", leaderSpawnId);
continue;
}
@@ -143,16 +124,31 @@ void FormationMgr::LoadCreatureFormations()
continue;
}
- leaderSpawnIds.insert(member.LeaderSpawnId);
+ leaderSpawnIds.insert(leaderSpawnId);
+ }
+
+ FormationInfo& member = _creatureGroupMap[memberSpawnId];
+ member.LeaderSpawnId = leaderSpawnId;
+ member.FollowDist = 0.f;
+ member.FollowAngle = 0.f;
+
+ //If creature is group leader we may skip loading of dist/angle
+ if (member.LeaderSpawnId != memberSpawnId)
+ {
+ member.FollowDist = fields[2].GetFloat();
+ member.FollowAngle = fields[3].GetFloat() * float(M_PI) / 180.0f;
}
- _creatureGroupMap.emplace(memberSpawnId, std::move(member));
+ member.GroupAI = fields[4].GetUInt32();
+ for (uint8 i = 0; i < 2; ++i)
+ member.LeaderWaypointIDs[i] = fields[5 + i].GetUInt16();
+
++count;
} while (result->NextRow());
for (ObjectGuid::LowType leaderSpawnId : leaderSpawnIds)
{
- if (!_creatureGroupMap.count(leaderSpawnId))
+ if (!_creatureGroupMap.contains(leaderSpawnId))
{
TC_LOG_ERROR("sql.sql", "creature_formation contains leader spawn {} which is not included on its formation, removing", leaderSpawnId);
for (auto itr = _creatureGroupMap.begin(); itr != _creatureGroupMap.end();)
@@ -178,39 +174,34 @@ FormationInfo* FormationMgr::GetFormationInfo(ObjectGuid::LowType spawnId)
void FormationMgr::AddFormationMember(ObjectGuid::LowType spawnId, float followAng, float followDist, ObjectGuid::LowType leaderSpawnId, uint32 groupAI)
{
- FormationInfo member;
+ FormationInfo& member = _creatureGroupMap[spawnId];
member.LeaderSpawnId = leaderSpawnId;
member.FollowDist = followDist;
member.FollowAngle = followAng;
member.GroupAI = groupAI;
for (uint8 i = 0; i < 2; ++i)
member.LeaderWaypointIDs[i] = 0;
-
- _creatureGroupMap.emplace(spawnId, std::move(member));
}
CreatureGroup::CreatureGroup(ObjectGuid::LowType leaderSpawnId) : _leader(nullptr), _members(), _leaderSpawnId(leaderSpawnId), _formed(false), _engaging(false)
{
}
-CreatureGroup::~CreatureGroup()
-{
-}
+CreatureGroup::~CreatureGroup() = default;
void CreatureGroup::AddMember(Creature* member)
{
- TC_LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding unit {}.", member->GetGUID().ToString());
+ TC_LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding unit {}.", member->GetGUID());
//Check if it is a leader
- if (member->GetSpawnId() == _leaderSpawnId)
+ if ((_leaderSpawnId && member->GetSpawnId() == _leaderSpawnId)
+ || (!_leaderSpawnId && !_leader)) // in formations made of tempsummons first member to be added is leader
{
- TC_LOG_DEBUG("entities.unit", "Unit {} is formation leader. Adding group.", member->GetGUID().ToString());
+ TC_LOG_DEBUG("entities.unit", "Unit {} is formation leader. Adding group.", member->GetGUID());
_leader = member;
}
- // formation must be registered at this point
- FormationInfo* formationInfo = ASSERT_NOTNULL(sFormationMgr->GetFormationInfo(member->GetSpawnId()));
- _members.emplace(member, formationInfo);
+ _members.emplace(member, sFormationMgr->GetFormationInfo(member->GetSpawnId()));
member->SetFormation(this);
}
@@ -229,7 +220,11 @@ void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target)
if (_engaging)
return;
- uint8 groupAI = ASSERT_NOTNULL(sFormationMgr->GetFormationInfo(member->GetSpawnId()))->GroupAI;
+ FormationInfo const* formationInfo = Trinity::Containers::MapGetValuePtr(_members, member);
+ if (!formationInfo)
+ return;
+
+ uint32 groupAI = formationInfo->GroupAI;
if (!groupAI)
return;
@@ -243,9 +238,8 @@ void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target)
_engaging = true;
- for (auto const& pair : _members)
+ for (auto const& [other, _] : _members)
{
- Creature* other = pair.first;
if (other == member)
continue;
@@ -261,15 +255,16 @@ void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target)
void CreatureGroup::FormationReset(bool dismiss)
{
- for (auto const& pair : _members)
+ for (auto const& [member, _] : _members)
{
- if (pair.first != _leader && pair.first->IsAlive())
+ if (member != _leader && member->IsAlive())
{
if (dismiss)
- pair.first->GetMotionMaster()->Remove(FORMATION_MOTION_TYPE, MOTION_SLOT_DEFAULT);
+ member->GetMotionMaster()->Remove(FORMATION_MOTION_TYPE, MOTION_SLOT_DEFAULT);
else
- pair.first->GetMotionMaster()->MoveIdle();
- TC_LOG_DEBUG("entities.unit", "CreatureGroup::FormationReset: Set {} movement for member {}", dismiss ? "default" : "idle", pair.first->GetGUID().ToString());
+ member->GetMotionMaster()->MoveIdle();
+
+ TC_LOG_DEBUG("entities.unit", "CreatureGroup::FormationReset: Set {} movement for member {}", dismiss ? "default" : "idle", member->GetGUID());
}
}
@@ -281,27 +276,26 @@ void CreatureGroup::LeaderStartedMoving()
if (!_leader)
return;
- for (auto const& pair : _members)
+ for (auto const& [member, formationInfo] : _members)
{
- Creature* member = pair.first;
- if (member == _leader || !member->IsAlive() || member->IsEngaged() || !(pair.second->GroupAI & FLAG_IDLE_IN_FORMATION))
+ if (member == _leader || !member->IsAlive() || member->IsEngaged() || !formationInfo || !(formationInfo->GroupAI & FLAG_IDLE_IN_FORMATION))
continue;
- float angle = pair.second->FollowAngle + float(M_PI); // for some reason, someone thought it was a great idea to invert relativ angles...
- float dist = pair.second->FollowDist;
+ float angle = formationInfo->FollowAngle + float(M_PI); // for some reason, someone thought it was a great idea to invert relativ angles...
+ float dist = formationInfo->FollowDist;
if (!member->HasUnitState(UNIT_STATE_FOLLOW_FORMATION))
- member->GetMotionMaster()->MoveFormation(_leader, dist, angle, pair.second->LeaderWaypointIDs[0], pair.second->LeaderWaypointIDs[1]);
+ member->GetMotionMaster()->MoveFormation(_leader, dist, angle, formationInfo->LeaderWaypointIDs[0], formationInfo->LeaderWaypointIDs[1]);
}
}
bool CreatureGroup::CanLeaderStartMoving() const
{
- for (std::unordered_map<Creature*, FormationInfo*>::value_type const& pair : _members)
+ for (auto const& [member, _] : _members)
{
- if (pair.first != _leader && pair.first->IsAlive())
+ if (member != _leader && member->IsAlive())
{
- if (pair.first->IsEngaged() || pair.first->IsReturningHome())
+ if (member->IsEngaged() || member->IsReturningHome())
return false;
}
}
diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h
index daf37e9e934..be8a9967bf5 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.h
+++ b/src/server/game/Entities/Creature/CreatureGroups.h
@@ -54,10 +54,15 @@ class TC_GAME_API FormationMgr
std::unordered_map<ObjectGuid::LowType /*spawnID*/, FormationInfo> _creatureGroupMap;
public:
+ FormationMgr(FormationMgr const&) = delete;
+ FormationMgr(FormationMgr&&) = delete;
+ FormationMgr& operator=(FormationMgr const&) = delete;
+ FormationMgr& operator=(FormationMgr&&) = delete;
+
static FormationMgr* instance();
- void AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creature* creature);
- void RemoveCreatureFromGroup(CreatureGroup* group, Creature* creature);
+ static void AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creature* creature);
+ static void RemoveCreatureFromGroup(CreatureGroup* group, Creature* member);
void LoadCreatureFormations();
FormationInfo* GetFormationInfo(ObjectGuid::LowType spawnId);
@@ -68,7 +73,7 @@ class TC_GAME_API FormationMgr
class TC_GAME_API CreatureGroup
{
private:
- Creature* _leader; //Important do not forget sometimes to work with pointers instead synonims :D:D
+ Creature* _leader;
std::unordered_map<Creature*, FormationInfo*> _members;
ObjectGuid::LowType _leaderSpawnId;
@@ -78,6 +83,10 @@ class TC_GAME_API CreatureGroup
public:
//Group cannot be created empty
explicit CreatureGroup(ObjectGuid::LowType leaderSpawnId);
+ CreatureGroup(CreatureGroup const&) = delete;
+ CreatureGroup(CreatureGroup&&) = delete;
+ CreatureGroup& operator=(CreatureGroup const&) = delete;
+ CreatureGroup& operator=(CreatureGroup&&) = delete;
~CreatureGroup();
Creature* GetLeader() const { return _leader; }
@@ -86,7 +95,7 @@ class TC_GAME_API CreatureGroup
bool IsFormed() const { return _formed; }
bool IsLeader(Creature const* creature) const { return _leader == creature; }
- bool HasMember(Creature* member) const { return _members.count(member) > 0; }
+ bool HasMember(Creature* member) const { return _members.contains(member); }
void AddMember(Creature* member);
void RemoveMember(Creature* member);
void FormationReset(bool dismiss);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d7595c411f6..05ac26601ce 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -12295,7 +12295,7 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a
{
// If a player entered a vehicle that is part of a formation, remove it from said formation
if (CreatureGroup* creatureGroup = vehicleBaseCreature->GetFormation())
- sFormationMgr->RemoveCreatureFromGroup(creatureGroup, vehicleBaseCreature);
+ FormationMgr::RemoveCreatureFromGroup(creatureGroup, vehicleBaseCreature);
}
}
diff --git a/src/server/scripts/EasternKingdoms/zone_elwynn_forest.cpp b/src/server/scripts/EasternKingdoms/zone_elwynn_forest.cpp
index 9b38dbfa104..caa7fb2dd97 100644
--- a/src/server/scripts/EasternKingdoms/zone_elwynn_forest.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_elwynn_forest.cpp
@@ -122,7 +122,7 @@ struct npc_cameron : public ScriptedAI
for (ObjectGuid guid : _childrenGUIDs)
if (Creature* child = ObjectAccessor::GetCreature(*me, guid))
if (CreatureGroup* creatureGroup = child->GetFormation())
- sFormationMgr->RemoveCreatureFromGroup(creatureGroup, child);
+ FormationMgr::RemoveCreatureFromGroup(creatureGroup, child);
// Move each child to an random position
for (uint32 i = 0; i < _childrenGUIDs.size(); ++i)