aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp25
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Groups/Group.cpp45
-rw-r--r--src/server/game/Groups/Group.h1
-rw-r--r--src/server/game/Maps/Map.cpp2
-rw-r--r--src/server/game/Maps/MapInstanced.cpp4
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 14b555adde9..f9b9acea2fb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -18594,31 +18594,6 @@ void Player::SendSavedInstances()
}
}
-/// 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->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;
- }
- }
-}
-
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 0072ec4125f..32a4fec27f2 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2116,7 +2116,6 @@ class Player : public Unit, public GridObject<Player>
bool HasPendingBind() const { return _pendingBindId > 0; }
void SendRaidInfo();
void SendSavedInstances();
- 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 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);
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 4d2ee57c9b2..42fd9b582e8 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -194,6 +194,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);
+ 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 27fb55bb4da..a2cb84359f2 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3030,7 +3030,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
{
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 74d490bf941..47b9b376b1e 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -163,7 +163,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->GetDifficulty(IsRaid()));
pSave = groupBind->save;
+ }
}
}
if (pSave)