aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2017-02-05 01:57:15 +0100
committerShauren <shauren.trinity@gmail.com>2017-02-05 01:57:15 +0100
commite991a15dd7cbf5ba374f8942b7ea88f3a4d7b365 (patch)
treef03739080e27b68dd31471790b63f97db56abffa /src
parent331fa3e03c6e4f0f1994fe64472c3e90a47f0f1c (diff)
Core/Groups: Fixed UI bugs related to leaving and rejoining the same group
Closes #18789
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp27
-rw-r--r--src/server/game/Entities/Player/Player.h12
-rw-r--r--src/server/game/Groups/Group.cpp46
-rw-r--r--src/server/game/Groups/Group.h13
4 files changed, 69 insertions, 29 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 3823f256870..12763bf5982 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -18920,6 +18920,8 @@ void Player::_LoadGroup(PreparedQueryResult result)
uint8 subgroup = group->GetMemberGroup(GetGUID());
SetGroup(group, subgroup);
+ SetPartyType(group->GetGroupCategory(), GROUP_TYPE_NORMAL);
+ ResetGroupUpdateSequenceIfNeeded(group);
if (getLevel() >= LEVELREQUIREMENT_HEROIC)
{
// the group leader may change the instance difficulty while the player is offline
@@ -24760,6 +24762,31 @@ void Player::SetOriginalGroup(Group* group, int8 subgroup)
}
}
+void Player::SetPartyType(GroupCategory category, uint8 type)
+{
+ ASSERT(category < MAX_GROUP_CATEGORY);
+ uint8 value = GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_PARTY_TYPE);
+ value &= ~uint8(uint8(0xFF) << (category * 4));
+ value |= uint8(uint8(type) << (category * 4));
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_PARTY_TYPE, value);
+}
+
+void Player::ResetGroupUpdateSequenceIfNeeded(Group const* group)
+{
+ GroupCategory category = group->GetGroupCategory();
+ // Rejoining the last group should not reset the sequence
+ if (m_groupUpdateSequences[category].GroupGuid != group->GetGUID())
+ {
+ m_groupUpdateSequences[category].GroupGuid = group->GetGUID();
+ m_groupUpdateSequences[category].UpdateSequenceNumber = 1;
+ }
+}
+
+int32 Player::NextGroupUpdateSequenceNumber(GroupCategory category)
+{
+ return m_groupUpdateSequences[category].UpdateSequenceNumber++;
+}
+
void Player::UpdateUnderwaterState(Map* m, float x, float y, float z)
{
LiquidData liquid_status;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index cd7167b2d26..ffabf1aed11 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -55,6 +55,8 @@ class PlayerSocial;
class SpellCastTargets;
class PlayerAI;
+enum GroupCategory : uint8;
+
typedef std::deque<Mail*> PlayerMails;
#define PLAYER_MAX_SKILLS 128
@@ -1166,6 +1168,12 @@ struct ResurrectionData
uint32 Aura;
};
+struct GroupUpdateCounter
+{
+ ObjectGuid GroupGuid;
+ int32 UpdateSequenceNumber;
+};
+
enum TalentLearnResult
{
TALENT_LEARN_OK = 0,
@@ -2402,6 +2410,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; }
void RemoveGroupUpdateFlag(uint32 flag) { m_groupUpdateMask &= ~flag; }
+ void SetPartyType(GroupCategory category, uint8 type);
+ void ResetGroupUpdateSequenceIfNeeded(Group const* group);
+ int32 NextGroupUpdateSequenceNumber(GroupCategory category);
Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup(ObjectGuid guidMember = ObjectGuid::Empty) const;
@@ -2744,6 +2755,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
Group* m_groupInvite;
uint32 m_groupUpdateMask;
bool m_bPassOnGroupLoot;
+ std::array<GroupUpdateCounter, 2> m_groupUpdateSequences;
// last used pet number (for BG's)
uint32 m_lastpetnumber;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 24b2111796d..b6a1903da95 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -55,7 +55,7 @@ Loot* Roll::getLoot()
return getTarget();
}
-Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupFlags(GROUP_FLAG_NONE),
+Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupFlags(GROUP_FLAG_NONE), m_groupCategory(GROUP_CATEGORY_HOME),
m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(DIFFICULTY_10_N),
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_maxEnchantingLevel(0), m_dbStoreId(0),
@@ -105,7 +105,10 @@ bool Group::Create(Player* leader)
leader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
if (isBGGroup() || isBFGroup())
+ {
m_groupFlags = GROUP_MASK_BGRAID;
+ m_groupCategory = GROUP_CATEGORY_INSTANCE;
+ }
if (m_groupFlags & GROUP_FLAG_RAID)
_initRaidSubGroupsCounter();
@@ -227,6 +230,7 @@ void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uin
void Group::ConvertToLFG()
{
m_groupFlags = GroupFlags(m_groupFlags | GROUP_FLAG_LFG | GROUP_FLAG_LFG_RESTRICTED);
+ m_groupCategory = GROUP_CATEGORY_INSTANCE;
m_lootMethod = GROUP_LOOT;
if (!isBGGroup() && !isBFGroup())
{
@@ -392,7 +396,6 @@ bool Group::AddMember(Player* player)
member.group = subGroup;
member.flags = 0;
member.roles = 0;
- member.updateSequenceNumber = 1;
member.readyChecked = false;
m_memberSlots.push_back(member);
@@ -409,6 +412,9 @@ bool Group::AddMember(Player* player)
else //if player is not in group, then call set group
player->SetGroup(this, subGroup);
+ player->SetPartyType(m_groupCategory, GROUP_TYPE_NORMAL);
+ player->ResetGroupUpdateSequenceIfNeeded(this);
+
// if the same group invites the player back, cancel the homebind timer
player->m_InstanceValid = player->CheckInstanceValidity(false);
@@ -538,7 +544,6 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
if (GetMembersCount() > ((isBGGroup() || isLFGGroup() || isBFGroup()) ? 1u : 2u))
{
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
- uint8 partyIndex = 0;
if (player)
{
// Battleground group handling
@@ -550,15 +555,14 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
if (player->GetOriginalGroup() == this)
player->SetOriginalGroup(NULL);
else
- {
player->SetGroup(NULL);
- partyIndex = 1;
- }
// quest related GO state dependent from raid membership
player->UpdateForQuestWorldObjects();
}
+ player->SetPartyType(m_groupCategory, GROUP_TYPE_NONE);
+
WorldPacket data;
if (method == GROUP_REMOVEMETHOD_KICK || method == GROUP_REMOVEMETHOD_KICK_LFG)
@@ -611,11 +615,9 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
}
// Update subgroups
- int32 updateSequenceNumber = 1;
member_witerator slot = _getMemberWSlot(guid);
if (slot != m_memberSlots.end())
{
- updateSequenceNumber = slot->updateSequenceNumber;
SubGroupCounterDecrease(slot->group);
m_memberSlots.erase(slot);
}
@@ -651,7 +653,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
else if (player)
{
// send update to removed player too so party frames are destroyed clientside
- SendUpdateDestroyGroupToPlayer(player, partyIndex, updateSequenceNumber);
+ SendUpdateDestroyGroupToPlayer(player);
}
return true;
@@ -794,26 +796,16 @@ void Group::Disband(bool hideDestroy /* = false */)
player->SetGroup(NULL);
}
+ player->SetPartyType(m_groupCategory, GROUP_TYPE_NONE);
+
// quest related GO state dependent from raid membership
if (isRaidGroup())
player->UpdateForQuestWorldObjects();
- if (!player->GetSession())
- continue;
-
if (!hideDestroy)
player->SendDirectMessage(WorldPackets::Party::GroupDestroyed().Write());
- uint8 disbandedPartyIndex = 0;
-
- //we already removed player from group and in player->GetGroup() is his original group, send update
- if (Group* group = player->GetGroup())
- {
- group->SendUpdate();
- disbandedPartyIndex = 1;
- }
-
- SendUpdateDestroyGroupToPlayer(player, disbandedPartyIndex, citr->updateSequenceNumber);
+ SendUpdateDestroyGroupToPlayer(player);
_homebindIfInstance(player);
}
@@ -1428,13 +1420,13 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot)
WorldPackets::Party::PartyUpdate partyUpdate;
partyUpdate.PartyFlags = m_groupFlags;
- partyUpdate.PartyIndex = (player->GetOriginalGroup() && player->GetOriginalGroup() != this) ? 1 : 0; // 0 = original group, 1 = instance/bg group
+ partyUpdate.PartyIndex = m_groupCategory;
partyUpdate.PartyType = IsCreated() ? GROUP_TYPE_NORMAL : GROUP_TYPE_NONE;
partyUpdate.PartyGUID = m_guid;
partyUpdate.LeaderGUID = m_leaderGuid;
- partyUpdate.SequenceNum = slot->updateSequenceNumber++; // 3.3, value increases every time this packet gets sent
+ partyUpdate.SequenceNum = player->NextGroupUpdateSequenceNumber(m_groupCategory);
partyUpdate.MyIndex = -1;
uint8 index = 0;
@@ -1509,15 +1501,15 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot)
player->GetSession()->SendPacket(partyUpdate.Write());
}
-void Group::SendUpdateDestroyGroupToPlayer(Player* player, uint8 partyIndex, int32 sequenceNum) const
+void Group::SendUpdateDestroyGroupToPlayer(Player* player) const
{
WorldPackets::Party::PartyUpdate partyUpdate;
partyUpdate.PartyFlags = GROUP_FLAG_DESTROYED;
- partyUpdate.PartyIndex = partyIndex;
+ partyUpdate.PartyIndex = m_groupCategory;
partyUpdate.PartyType = GROUP_TYPE_NONE;
partyUpdate.PartyGUID = m_guid;
partyUpdate.MyIndex = -1;
- partyUpdate.SequenceNum = sequenceNum;
+ partyUpdate.SequenceNum = player->NextGroupUpdateSequenceNumber(m_groupCategory);
player->GetSession()->SendPacket(partyUpdate.Write());
}
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 6f92ca17fe9..6fe7fda3c74 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -116,6 +116,14 @@ enum GroupFlags
GROUP_MASK_BGRAID = GROUP_FLAG_FAKE_RAID | GROUP_FLAG_RAID,
};
+enum GroupCategory : uint8
+{
+ GROUP_CATEGORY_HOME = 0,
+ GROUP_CATEGORY_INSTANCE = 1,
+
+ MAX_GROUP_CATEGORY
+};
+
enum GroupUpdateFlags
{
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
@@ -218,7 +226,6 @@ class TC_GAME_API Group
uint8 group;
uint8 flags;
uint8 roles;
- int32 updateSequenceNumber;
bool readyChecked;
};
typedef std::list<MemberSlot> MemberSlotList;
@@ -287,6 +294,7 @@ class TC_GAME_API Group
bool isBGGroup() const;
bool isBFGroup() const;
bool IsCreated() const;
+ GroupCategory GetGroupCategory() const { return m_groupCategory; }
ObjectGuid GetLeaderGUID() const;
ObjectGuid GetGUID() const;
const char * GetLeaderName() const;
@@ -347,7 +355,7 @@ class TC_GAME_API Group
void SendTargetIconList(WorldSession* session, int8 partyIndex = 0);
void SendUpdate();
void SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot = NULL);
- void SendUpdateDestroyGroupToPlayer(Player* player, uint8 partyIndex, int32 sequenceNum) const;
+ void SendUpdateDestroyGroupToPlayer(Player* player) const;
void UpdatePlayerOutOfRange(Player* player);
template<class Worker>
@@ -419,6 +427,7 @@ class TC_GAME_API Group
ObjectGuid m_leaderGuid;
std::string m_leaderName;
GroupFlags m_groupFlags;
+ GroupCategory m_groupCategory;
Difficulty m_dungeonDifficulty;
Difficulty m_raidDifficulty;
Difficulty m_legacyRaidDifficulty;