diff options
| -rw-r--r-- | src/server/game/Groups/Group.cpp | 62 | ||||
| -rw-r--r-- | src/server/game/Groups/Group.h | 9 | ||||
| -rw-r--r-- | src/server/game/Groups/GroupMgr.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Groups/GroupMgr.h | 2 | ||||
| -rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 13 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 3 | 
7 files changed, 88 insertions, 9 deletions
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 3a63033575d..74fc5cbdfb7 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -63,7 +63,7 @@ Loot* Roll::getLoot()  Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL),  m_dungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL), m_raidDifficulty(RAID_DIFFICULTY_10MAN_NORMAL),  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_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0) +m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0), m_isLeaderOffline(false)  {      for (uint8 i = 0; i < TARGETICONCOUNT; ++i)          m_targetIcons[i].Clear(); @@ -99,6 +99,55 @@ Group::~Group()      delete[] m_subGroupsCounts;  } +void Group::Update(uint32 diff) +{ +    if (m_isLeaderOffline && (m_groupType == GROUPTYPE_NORMAL || m_groupType == GROUPTYPE_RAID)) +    { +        m_leaderOfflineTimer.Update(diff); +        if (m_leaderOfflineTimer.Passed()) +        { +            SelectNewPartyOrRaidLeader(); +            m_isLeaderOffline = false; +        } +    } +} + +void Group::SelectNewPartyOrRaidLeader() +{ +    Player* newLeader = nullptr; + +    // Attempt to give leadership to main assistant first +    if (m_groupType == GROUPTYPE_RAID) +    { +        for (auto 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 (auto 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(); @@ -2554,3 +2603,14 @@ void Group::ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)      else          slot->flags &= ~flag;  } + +void Group::StartLeaderOfflineTimer() +{ +    m_isLeaderOffline = true; +    m_leaderOfflineTimer.Reset(2 * MINUTE * IN_MILLISECONDS); +} + +void Group::StopLeaderOfflineTimer() +{ +    m_isLeaderOffline = false; +} diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 842c39cbcda..a7a962f5758 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -24,6 +24,7 @@  #include "GroupRefManager.h"  #include "Loot.h"  #include "SharedDefines.h" +#include "Timer.h"  #include <map>  class Battlefield; @@ -184,6 +185,8 @@ class TC_GAME_API Group          Group();          ~Group(); +        void Update(uint32 diff); +          // group manipulation methods          bool   Create(Player* leader);          void   LoadGroupFromDB(Field* field); @@ -327,6 +330,10 @@ class TC_GAME_API Group          InstanceGroupBind* GetBoundInstance(Difficulty difficulty, uint32 mapId);          BoundInstancesMap& GetBoundInstances(Difficulty difficulty); +        void StartLeaderOfflineTimer(); +        void StopLeaderOfflineTimer(); +        void SelectNewPartyOrRaidLeader(); +          // FG: evil hacks          void BroadcastGroupUpdate(void); @@ -363,5 +370,7 @@ class TC_GAME_API Group          uint32              m_counter;                      // used only in SMSG_GROUP_LIST          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;  };  #endif diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp index 8f2a8917ba6..2d44ee3b955 100644 --- a/src/server/game/Groups/GroupMgr.cpp +++ b/src/server/game/Groups/GroupMgr.cpp @@ -109,6 +109,12 @@ Group* GroupMgr::GetGroupByGUID(ObjectGuid::LowType groupId) const      return nullptr;  } +void GroupMgr::Update(uint32 diff) +{ +    for (auto group : GroupStore) +        group.second->Update(diff); +} +  void GroupMgr::AddGroup(Group* group)  {      GroupStore[group->GetLowGUID()] = group; diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h index b1cb956e8ad..68d176c8038 100644 --- a/src/server/game/Groups/GroupMgr.h +++ b/src/server/game/Groups/GroupMgr.h @@ -41,6 +41,8 @@ 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); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 72c7cc5ffed..adcb3421ccf 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -848,6 +848,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 dafb08bd2ce..3c1de96e01b 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -548,16 +548,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) -            _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 cb26d8a00bf..851072648a2 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2402,6 +2402,9 @@ void World::Update(uint32 diff)          Player::DeleteOldCharacters();      } +    sGroupMgr->Update(diff); +    sWorldUpdateTime.RecordUpdateTimeDuration("UpdateGroupMgr"); +      sLFGMgr->Update(diff);      sWorldUpdateTime.RecordUpdateTimeDuration("UpdateLFGMgr");  | 
