aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWyrserth <43747507+Wyrserth@users.noreply.github.com>2019-06-15 14:19:58 +0200
committerShauren <shauren.trinity@gmail.com>2021-12-11 13:06:25 +0100
commitcc141e9bad5dc06a56179f820670bd6944651804 (patch)
tree69510c12aaa38720886320906f24339a7841b71d /src
parent7b346bcf8d4c4b39685a46ef09f389c8a317b566 (diff)
Core/Group: implement automatic party/raid leader change when the leader has been offline for two minutes (#23398)
* Core/Group: implement automatic party/raid leader change when the leader has been offline for two minutes. * Add #23396 to make testing easier. * Prioritize assistants in raids. * Fix dumb mistake and apply suggested change, thanks VincentVanclef and jackpoz! (cherry picked from commit e906a2fe7d71fc17de9f7ea4778970beb3f9265e)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Groups/Group.cpp69
-rw-r--r--src/server/game/Groups/Group.h10
-rw-r--r--src/server/game/Groups/GroupMgr.cpp13
-rw-r--r--src/server/game/Groups/GroupMgr.h5
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp2
-rw-r--r--src/server/game/Server/WorldSession.cpp13
-rw-r--r--src/server/game/World/World.cpp3
7 files changed, 90 insertions, 25 deletions
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index b69beb76ebe..7cbcbecc934 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -62,7 +62,7 @@ Loot* Roll::getLoot()
Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupFlags(GROUP_FLAG_NONE), m_groupCategory(GROUP_CATEGORY_HOME),
m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(DIFFICULTY_10_N),
m_bgGroup(nullptr), m_bfGroup(nullptr), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
-m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_maxEnchantingLevel(0), m_dbStoreId(0),
+m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_maxEnchantingLevel(0), m_dbStoreId(0), m_isLeaderOffline(false),
m_readyCheckStarted(false), m_readyCheckTimer(Milliseconds::zero()), m_activeMarkers(0)
{
for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
@@ -102,6 +102,57 @@ Group::~Group()
delete[] m_subGroupsCounts;
}
+void Group::Update(uint32 diff)
+{
+ if (m_isLeaderOffline)
+ {
+ m_leaderOfflineTimer.Update(diff);
+ if (m_leaderOfflineTimer.Passed())
+ {
+ SelectNewPartyOrRaidLeader();
+ m_isLeaderOffline = false;
+ }
+ }
+
+ UpdateReadyCheck(diff);
+}
+
+void Group::SelectNewPartyOrRaidLeader()
+{
+ Player* newLeader = nullptr;
+
+ // Attempt to give leadership to main assistant first
+ if (isRaidGroup())
+ {
+ for (Group::MemberSlot const& memberSlot : m_memberSlots)
+ {
+ if ((memberSlot.flags & MEMBER_FLAG_ASSISTANT) == MEMBER_FLAG_ASSISTANT)
+ if (Player* player = ObjectAccessor::FindPlayer(memberSlot.guid))
+ {
+ newLeader = player;
+ break;
+ }
+ }
+ }
+
+ // If there aren't assistants in raid, or if the group is not a raid, pick the first available member
+ if (!newLeader)
+ {
+ for (Group::MemberSlot const& memberSlot : m_memberSlots)
+ if (Player* player = ObjectAccessor::FindPlayer(memberSlot.guid))
+ {
+ newLeader = player;
+ break;
+ }
+ }
+
+ if (newLeader)
+ {
+ ChangeLeader(newLeader->GetGUID());
+ SendUpdate();
+ }
+}
+
bool Group::Create(Player* leader)
{
ObjectGuid leaderGuid = leader->GetGUID();
@@ -2265,11 +2316,6 @@ uint8 Group::GetLfgRoles(ObjectGuid guid)
return slot->roles;
}
-void Group::Update(uint32 diff)
-{
- UpdateReadyCheck(diff);
-}
-
void Group::UpdateReadyCheck(uint32 diff)
{
if (!m_readyCheckStarted)
@@ -2681,6 +2727,17 @@ void Group::ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)
slot->flags &= ~flag;
}
+void Group::StartLeaderOfflineTimer()
+{
+ m_isLeaderOffline = true;
+ m_leaderOfflineTimer.Reset(2 * MINUTE * IN_MILLISECONDS);
+}
+
+void Group::StopLeaderOfflineTimer()
+{
+ m_isLeaderOffline = false;
+}
+
void Group::SetEveryoneIsAssistant(bool apply)
{
if (apply)
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 734931b4646..e8aac473ca9 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -24,6 +24,7 @@
#include "Loot.h"
#include "Object.h"
#include "SharedDefines.h"
+#include "Timer.h"
#include <map>
class Battlefield;
@@ -243,6 +244,8 @@ class TC_GAME_API Group
Group();
~Group();
+ void Update(uint32 diff);
+
// group manipulation methods
bool Create(Player* leader);
void LoadGroupFromDB(Field* field);
@@ -266,7 +269,6 @@ class TC_GAME_API Group
void SetEveryoneIsAssistant(bool apply);
// Update
- void Update(uint32 diff);
void UpdateReadyCheck(uint32 diff);
// Ready check
@@ -414,6 +416,10 @@ class TC_GAME_API Group
BoundInstancesMap::iterator GetBoundInstances(Difficulty difficulty);
BoundInstancesMap::iterator GetBoundInstanceEnd();
+ void StartLeaderOfflineTimer();
+ void StopLeaderOfflineTimer();
+ void SelectNewPartyOrRaidLeader();
+
// FG: evil hacks
void BroadcastGroupUpdate(void);
@@ -451,6 +457,8 @@ class TC_GAME_API Group
ObjectGuid m_guid;
uint32 m_maxEnchantingLevel;
uint32 m_dbStoreId; // Represents the ID used in database (Can be reused by other groups if group was disbanded)
+ bool m_isLeaderOffline;
+ TimeTrackerSmall m_leaderOfflineTimer;
// Ready Check
bool m_readyCheckStarted;
diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp
index b884890c0ba..8d58eb07a86 100644
--- a/src/server/game/Groups/GroupMgr.cpp
+++ b/src/server/game/Groups/GroupMgr.cpp
@@ -109,6 +109,12 @@ Group* GroupMgr::GetGroupByGUID(ObjectGuid const& groupId) const
return nullptr;
}
+void GroupMgr::Update(uint32 diff)
+{
+ for (std::pair<ObjectGuid::LowType const, Group*> const& group : GroupStore)
+ group.second->Update(diff);
+}
+
void GroupMgr::AddGroup(Group* group)
{
GroupStore[group->GetGUID().GetCounter()] = group;
@@ -244,10 +250,3 @@ void GroupMgr::LoadGroups()
TC_LOG_INFO("server.loading", ">> Loaded %u group-instance saves in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
}
-
-void GroupMgr::Update(uint32 diff)
-{
- for (GroupContainer::iterator itr = GroupStore.begin(); itr != GroupStore.end(); itr++)
- if (itr->second)
- itr->second->Update(diff);
-}
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
index 5d95b291291..781264b78f7 100644
--- a/src/server/game/Groups/GroupMgr.h
+++ b/src/server/game/Groups/GroupMgr.h
@@ -41,14 +41,13 @@ public:
Group* GetGroupByDbStoreId(uint32 storageId) const;
void SetGroupDbStoreSize(uint32 newSize) { GroupDbStore.resize(newSize); }
+ void Update(uint32 diff);
+
void LoadGroups();
ObjectGuid::LowType GenerateGroupId();
void AddGroup(Group* group);
void RemoveGroup(Group* group);
- void Update(uint32 diff);
-
-
protected:
ObjectGuid::LowType NextGroupId;
uint32 NextGroupDbStoreId;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 7006ff0d2cc..16aa7a09625 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1189,6 +1189,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
//pCurrChar->groupInfo.group->SendInit(this); // useless
group->SendUpdate();
group->ResetMaxEnchantingLevel();
+ if (group->GetLeaderGUID() == pCurrChar->GetGUID())
+ group->StopLeaderOfflineTimer();
}
// friend status
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index a1416d18410..3c5206e6c27 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -607,16 +607,13 @@ void WorldSession::LogoutPlayer(bool save)
///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
_player->UninviteFromGroup();
- // remove player from the group if he is:
- // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
- if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket[CONNECTION_TYPE_REALM])
- _player->RemoveFromGroup();
-
//! Send update to group and reset stored max enchanting level
- if (_player->GetGroup())
+ if (Group* group = _player->GetGroup())
{
- _player->GetGroup()->SendUpdate();
- _player->GetGroup()->ResetMaxEnchantingLevel();
+ group->SendUpdate();
+ group->ResetMaxEnchantingLevel();
+ if (group->GetLeaderGUID() == _player->GetGUID())
+ group->StartLeaderOfflineTimer();
}
//! Broadcast a logout message to the player's friends
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 2756ca2afc4..2e83c4365a7 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2633,6 +2633,9 @@ void World::Update(uint32 diff)
Player::DeleteOldCharacters();
}
+ sGroupMgr->Update(diff);
+ sWorldUpdateTime.RecordUpdateTimeDuration("UpdateGroupMgr");
+
sLFGMgr->Update(diff);
sWorldUpdateTime.RecordUpdateTimeDuration("UpdateLFGMgr");