diff options
| author | treeston <treeston.mmoc@gmail.com> | 2016-01-03 14:38:36 +0100 | 
|---|---|---|
| committer | treeston <treeston.mmoc@gmail.com> | 2016-01-04 15:48:53 +0100 | 
| commit | 0f0a51b87a1c8c4c0809b9328a3ddb606b138c4b (patch) | |
| tree | ab6b415add1b144345b4735e360fd5138ba326af /src/server/game/Groups/Group.cpp | |
| parent | 8a0bbc386982612077e6f83f1816b02be757e371 (diff) | |
Game/Maps: Instance handling follow-up:
- Fix a bug where a player could maintain a conflicting non-perm solo bind if they were in the instance when invited to group. Closes #16150.
- If a group is created while the leader is in an instance that nobody is bound to, the group will take over the instance and bind to it. This stops the homebind timer when reforming group after disconnects and the like.
Diffstat (limited to 'src/server/game/Groups/Group.cpp')
| -rw-r--r-- | src/server/game/Groups/Group.cpp | 45 | 
1 files changed, 39 insertions, 6 deletions
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index d0e70eb3dbb..8ebc71b0146 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -148,10 +148,9 @@ bool Group::Create(Player* leader)          CharacterDatabase.Execute(stmt); +        Group::ConvertLeaderInstancesToGroup(leader, this, false);          ASSERT(AddMember(leader)); // If the leader can't be added to a new group because it appears full, something is clearly wrong. - -        Player::ConvertInstancesToGroup(leader, this, false);      }      else if (!AddMember(leader))          return false; @@ -375,9 +374,7 @@ bool Group::AddMember(Player* player)          player->SetGroup(this, subGroup);      // if the same group invites the player back, cancel the homebind timer -    InstanceGroupBind* bind = GetBoundInstance(player); -    if (bind && bind->save->GetInstanceId() == player->GetInstanceId()) -        player->m_InstanceValid = true; +    player->m_InstanceValid = player->CheckInstanceValidity(false);      if (!isRaidGroup())                                      // reset targetIcons for non-raid-groups      { @@ -654,7 +651,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)          }          // Copy the permanent binds from the new leader to the group -        Player::ConvertInstancesToGroup(newLeader, this, true); +        Group::ConvertLeaderInstancesToGroup(newLeader, this, true);          // Update the group leader          PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER); @@ -680,6 +677,42 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)      BroadcastPacket(&data, true);  } +/// convert the player's binds to the group +void Group::ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader) +{ +    // copy all binds to the group, when changing leader it's assumed the character +    // will not have any solo binds +    for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) +    { +        for (Player::BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) +        { +            if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficulty(), itr->first)) +                group->BindToInstance(itr->second.save, itr->second.perm, false); + +            // permanent binds are not removed +            if (switchLeader && !itr->second.perm) +            { +                // increments itr in call +                player->UnbindInstance(itr, Difficulty(i), false); +            } +            else +                ++itr; +        } +    } + +    /* if group leader is in a non-raid dungeon map and nobody is actually bound to this map then the group can "take over" the instance * +    * (example: two-player group disbanded by disconnect where the player reconnects within 60 seconds and the group is reformed)       */ +    if (Map* playerMap = player->GetMap()) +        if (!switchLeader && playerMap->IsNonRaidDungeon()) +            if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(playerMap->GetInstanceId())) +                if (save->GetGroupCount() == 0 && save->GetPlayerCount() == 0) +                { +                    TC_LOG_DEBUG("maps", "Group::ConvertLeaderInstancesToGroup: Group for player %s is taking over unbound instance map %d with Id %d", player->GetName().c_str(), playerMap->GetId(), playerMap->GetInstanceId()); +                    // if nobody is saved to this, then the save wasn't permanent +                    group->BindToInstance(save, false, false); +                } +} +  void Group::Disband(bool hideDestroy /* = false */)  {      sScriptMgr->OnGroupDisband(this);  | 
