diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-07-11 15:24:02 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-07-11 15:24:02 +0200 |
commit | 16bfbe1a3a12256d9476f3ae23e1f34f31f9cf07 (patch) | |
tree | c257908a693de34cd3a25611ec596dad1f7c366f | |
parent | c5c31c7c1efb26551b76a4046e9def8c5981864d (diff) |
Core/Creatures: Allow adding summons to CreatureGroup (only adding, no formation movement of linked aggro yet)
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureGroups.cpp | 136 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureGroups.h | 17 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/zone_elwynn_forest.cpp | 2 |
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) |