diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Groups/Group.cpp | 45 | ||||
-rw-r--r-- | src/server/game/Groups/Group.h | 1 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Maps/MapInstanced.cpp | 4 |
6 files changed, 45 insertions, 33 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index f30b4ac5c44..247de0befe6 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -18314,31 +18314,6 @@ void Player::SendRaidInfo() GetSession()->SendPacket(instanceInfo.Write()); } -/// convert the player's binds to the group -void Player::ConvertInstancesToGroup(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 (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) - { - if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficultyID(), 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; - } - } -} - bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report) { if (!IsGameMaster() && ar) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 0679fc9167f..a381c2dd351 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2353,7 +2353,6 @@ class Player : public Unit, public GridObject<Player> void SetPendingBind(uint32 instanceId, uint32 bindTimer); bool HasPendingBind() const { return _pendingBindId > 0; } void SendRaidInfo(); - static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader); bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false); bool CheckInstanceValidity(bool /*isLogin*/); bool CheckInstanceCount(uint32 instanceId) const; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 5f8813c2071..e3528d053f5 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -157,10 +157,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; @@ -410,9 +409,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 { @@ -693,7 +690,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex) } // 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); @@ -720,6 +717,42 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex) BroadcastPacket(groupNewLeader.Write(), 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->GetDifficultyID(), 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); diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index fab6edd5603..ba11dcff200 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -226,6 +226,7 @@ class Group bool AddMember(Player* player); bool RemoveMember(ObjectGuid guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker = ObjectGuid::Empty, const char* reason = NULL); void ChangeLeader(ObjectGuid guid, int8 partyIndex = 0); + static void ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader); void SetLootMethod(LootMethod method); void SetLooterGuid(ObjectGuid guid); void SetMasterLooterGuid(ObjectGuid guid); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 3dbed19fc98..d1beee19ac3 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3145,7 +3145,7 @@ bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { if (group) { - // solo saves should be reset when entering a group + // solo saves should have been reset when the map was loaded InstanceGroupBind* groupBind = group->GetBoundInstance(this); if (playerBind && playerBind->save != mapSave) { diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 4c065f836b9..e277746290a 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -164,7 +164,11 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, u { groupBind = group->GetBoundInstance(this); if (groupBind) + { + // solo saves should be reset when entering a group's instance + player->UnbindInstance(GetId(), player->GetDifficultyID(GetEntry())); pSave = groupBind->save; + } } } if (pSave) |