Merge pull request #16156 from Treeston/3.3.5-instancerevive2

Game/Maps: Instance handling bug-fix follow-up
(cherry picked from commit ae4fcc3685079e1c24cd46545dae169d5be12046)
This commit is contained in:
Treeston
2016-03-21 22:41:02 +01:00
committed by Shauren
parent e6ab6b4b0b
commit 8225fb09c2
6 changed files with 45 additions and 33 deletions
@@ -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)
-1
View File
@@ -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;
+39 -6
View File
@@ -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);
+1
View File
@@ -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);
+1 -1
View File
@@ -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)
{
+4
View File
@@ -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)