GroupJoinBattlegroundResult Group::CanJoinBattleGroundQueue(BattleGround const* bgOrTemplate, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 /*MaxPlayerCount*/, bool isRated, uint32 arenaSlot) { BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->GetTypeID()); if (!bgEntry) return ERR_GROUP_JOIN_BATTLEGROUND_FAIL; // shouldn't happen // check for min / max count uint32 memberscount = GetMembersCount(); // only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas... if (bgOrTemplate->isArena() && memberscount != MinPlayerCount) return ERR_ARENA_TEAM_PARTY_SIZE; if (memberscount > bgEntry->maxGroupSize) // no MinPlayerCount for battlegrounds return ERR_BATTLEGROUND_NONE; // ERR_GROUP_JOIN_BATTLEGROUND_TOO_MANY handled on client side // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) Player* reference = GetFirstMember()->getSource(); // no reference found, can't join this way if (!reference) return ERR_BATTLEGROUND_JOIN_FAILED; PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgOrTemplate->GetMapId(), reference->getLevel()); if (!bracketEntry) return ERR_BATTLEGROUND_JOIN_FAILED; uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); Team team = reference->GetTeam(); // check every member of the group to be able to join for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->getSource(); // offline member? don't let join if (!member) return ERR_BATTLEGROUND_JOIN_FAILED; // don't allow cross-faction join as group if (member->GetTeam() != team) return ERR_BATTLEGROUND_JOIN_TIMED_OUT; // not in the same battleground level bracket, don't let join PvPDifficultyEntry const* memberBracketEntry = GetBattlegroundBracketByLevel(bracketEntry->mapId, member->getLevel()); if (memberBracketEntry != bracketEntry) return ERR_BATTLEGROUND_JOIN_RANGE_INDEX; // don't let join rated matches if the arena team id doesn't match if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) return ERR_BATTLEGROUND_JOIN_FAILED; // don't let join if someone from the group is already in that bg queue if (member->InBattleGroundQueueForBattleGroundQueueType(bgQueueTypeId)) return ERR_BATTLEGROUND_JOIN_FAILED; // not blizz-like // check for deserter debuff in case not arena queue if (bgOrTemplate->GetTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground()) return ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS; // check if member can join any more battleground queues if (!member->HasFreeBattleGroundQueueId()) return ERR_BATTLEGROUND_TOO_MANY_QUEUES; // not blizz-like } return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID()); }
void Group::GetDataForXPAtKill(Unit const* victim, uint32& count, uint32& sum_level, Player*& member_with_max_level, Player*& not_gray_member_with_max_level, Player* additional) { for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member || !member->isAlive()) // only for alive continue; // will proccesed later if (member == additional) continue; if (!member->IsAtGroupRewardDistance(victim)) // at req. distance continue; ++count; GetDataForXPAtKill_helper(member, victim, sum_level, member_with_max_level, not_gray_member_with_max_level); } if (additional) { if (additional->IsAtGroupRewardDistance(victim)) // at req. distance { ++count; GetDataForXPAtKill_helper(additional, victim, sum_level, member_with_max_level, not_gray_member_with_max_level); } } }
uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) { // check for min / max count uint32 memberscount = GetMembersCount(); if (memberscount < MinPlayerCount) return BG_JOIN_ERR_GROUP_NOT_ENOUGH; if (memberscount > MaxPlayerCount) return BG_JOIN_ERR_GROUP_TOO_MANY; // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) Player* reference = GetFirstMember()->getSource(); // no reference found, can't join this way if (!reference) return BG_JOIN_ERR_OFFLINE_MEMBER; BattleGroundBracketId bracket_id = reference->GetBattleGroundBracketIdFromLevel(bgTypeId); uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); Team team = reference->GetTeam(); // check every member of the group to be able to join for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->getSource(); // offline member? don't let join if (!member) return BG_JOIN_ERR_OFFLINE_MEMBER; // don't allow cross-faction join as group if (member->GetTeam() != team) return BG_JOIN_ERR_MIXED_FACTION; // not in the same battleground level bracket, don't let join if (member->GetBattleGroundBracketIdFromLevel(bgTypeId) != bracket_id) return BG_JOIN_ERR_MIXED_LEVELS; // don't let join rated matches if the arena team id doesn't match if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) return BG_JOIN_ERR_MIXED_ARENATEAM; // don't let join if someone from the group is already in that bg queue if (member->InBattleGroundQueueForBattleGroundQueueType(bgQueueTypeId)) return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE; // check for deserter debuff in case not arena queue if (bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground()) return BG_JOIN_ERR_GROUP_DESERTER; // check if member can join any more battleground queues if (!member->HasFreeBattleGroundQueueId()) return BG_JOIN_ERR_ALL_QUEUES_USED; } return BG_JOIN_ERR_OK; }
bool Group::InCombatToInstance(uint32 instanceId) { for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->getSource(); if (pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId) return true; } return false; }
void Group::BroadcastReadyCheck(WorldPacket* packet) { for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pl = itr->getSource(); if (pl && pl->GetSession()) if (IsLeader(pl->GetObjectGuid()) || IsAssistant(pl->GetObjectGuid())) pl->GetSession()->SendPacket(packet); } }
void Group::BroadcastReadyCheck(WorldPacket const& packet) const { for (auto itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* pl = itr->getSource(); if (pl && pl->GetSession()) if (IsLeader(pl->GetObjectGuid()) || IsAssistant(pl->GetObjectGuid())) pl->GetSession()->SendPacket(packet); } }
void Group::BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group, ObjectGuid ignore) { for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pl = itr->getSource(); if (!pl || (ignore && pl->GetObjectGuid() == ignore) || (ignorePlayersInBGRaid && pl->GetGroup() != this)) continue; if (pl->GetSession() && (group == -1 || itr->getSubGroup() == group)) pl->GetSession()->SendPacket(packet); } }
void Group::SetDifficulty(Difficulty difficulty) { m_difficulty = difficulty; if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE groupId='%u'", m_difficulty, m_Id); for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* player = itr->getSource(); if (!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC) continue; player->SetDifficulty(difficulty); player->SendDungeonDifficulty(true); } }
/** Provide rewards to group members at unit kill * * @param pVictim Killed unit * @param player_tap Player who tap unit if online, it can be group member or can be not if leaved after tap but before kill target * * Rewards received by group members and player_tap */ void Group::RewardGroupAtKill(Unit* pVictim, Player* player_tap) { bool PvP = pVictim->isCharmedOwnedByPlayerOrPlayer(); // prepare data for near group iteration (PvP and !PvP cases) uint32 xp = 0; uint32 count = 0; uint32 sum_level = 0; Player* member_with_max_level = NULL; Player* not_gray_member_with_max_level = NULL; GetDataForXPAtKill(pVictim, count, sum_level, member_with_max_level, not_gray_member_with_max_level, player_tap); if (member_with_max_level) { /// not get Xp in PvP or no not gray players in group xp = (PvP || !not_gray_member_with_max_level) ? 0 : MaNGOS::XP::Gain(not_gray_member_with_max_level, pVictim); /// skip in check PvP case (for speed, not used) bool is_raid = PvP ? false : sMapStore.LookupEntry(pVictim->GetMapId())->IsRaid() && isRaidGroup(); bool is_dungeon = PvP ? false : sMapStore.LookupEntry(pVictim->GetMapId())->IsDungeon(); float group_rate = MaNGOS::XP::xp_in_group_rate(count, is_raid); for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pGroupGuy = itr->getSource(); if (!pGroupGuy) continue; // will proccessed later if (pGroupGuy == player_tap) continue; if (!pGroupGuy->IsAtGroupRewardDistance(pVictim)) continue; // member (alive or dead) or his corpse at req. distance RewardGroupAtKill_helper(pGroupGuy, pVictim, count, PvP, group_rate, sum_level, is_dungeon, not_gray_member_with_max_level, member_with_max_level, xp); } if (player_tap) { // member (alive or dead) or his corpse at req. distance if (player_tap->IsAtGroupRewardDistance(pVictim)) RewardGroupAtKill_helper(player_tap, pVictim, count, PvP, group_rate, sum_level, is_dungeon, not_gray_member_with_max_level, member_with_max_level, xp); } } }
void Group::UpdatePlayerOutOfRange(Player* pPlayer) { if (!pPlayer || !pPlayer->IsInWorld()) return; if (pPlayer->GetGroupUpdateFlag() == GROUP_UPDATE_FLAG_NONE) return; WorldPacket data; pPlayer->GetSession()->BuildPartyMemberStatsChangedPacket(pPlayer, &data); for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) if (Player* player = itr->getSource()) if (player != pPlayer && !player->HaveAtClient(pPlayer)) player->GetSession()->SendPacket(&data); }
uint32 Group::GetMaxSkillValueForGroup(SkillType skill) { uint32 maxvalue = 0; for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; uint32 value = member->GetSkillValue(skill); if (maxvalue < value) maxvalue = value; } return maxvalue; }
void LfgGroup::KilledCreature(Creature *creature) { if ((creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) && m_instanceStatus == INSTANCE_NOT_SAVED) { m_instanceStatus = INSTANCE_SAVED; } if (!m_awarded && creature->GetEntry() == sLfgMgr.GetDungeonInfo(m_dungeonInfo->ID)->lastBossId) { //Last boss m_instanceStatus = INSTANCE_COMPLETED; //Reward here for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player *plr = itr->getSource(); if (!plr || !plr->IsInWorld()) continue; WorldPacket data(SMSG_LFG_PLAYER_REWARD); data << uint32(GetDungeonInfo((IsRandom() || IsFromRnd(plr->GetGUID())))->Entry()); data << uint32(m_dungeonInfo->Entry()); uint32 ID = GetDungeonInfo((IsRandom() || IsFromRnd(plr->GetGUID())))->ID; sLfgMgr.BuildRewardBlock(&data, ID, plr); plr->GetSession()->SendPacket(&data); LfgReward *reward = sLfgMgr.GetDungeonReward(ID, plr->m_lookingForGroup.DoneDungeon(ID, plr), plr->getLevel()); if (!reward) continue; plr->CompleteQuest(reward->questInfo->GetQuestId()); if (IsRandom()) plr->RemoveAurasDueToSpell(LFG_RANDOM_COOLDOWN); } m_awarded = true; } SendUpdate(); }
bool Group::_addMember(ObjectGuid guid, const char* name, bool isAssistant, uint8 group) { if (IsFull()) return false; if (!guid) return false; Player* player = sObjectMgr.GetPlayer(guid, false); uint32 lastMap = 0; if (player && player->IsInWorld()) lastMap = player->GetMapId(); else if (player && player->IsBeingTeleported()) lastMap = player->GetTeleportDest().mapid; MemberSlot member; member.guid = guid; member.name = name; member.group = group; member.assistant = isAssistant; member.lastMap = lastMap; m_memberSlots.push_back(member); SubGroupCounterIncrease(group); if (player) { player->SetGroupInvite(nullptr); // if player is in group and he is being added to BG raid group, then call SetBattleGroundRaid() if (player->GetGroup() && isBattleGroup()) player->SetBattleGroundRaid(this, group); // if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup() else if (player->GetGroup()) player->SetOriginalGroup(this, group); // if player is not in group, then call set group else player->SetGroup(this, group); if (player->IsInWorld()) { // if the same group invites the player back, cancel the homebind timer if (InstanceGroupBind* bind = GetBoundInstance(player->GetMapId())) if (bind->state->GetInstanceId() == player->GetInstanceId()) player->m_InstanceValid = true; } if (player->IsPvPFreeForAll()) { player->ForceHealthAndPowerUpdate(); for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* groupMember = itr->getSource(); if (groupMember && groupMember->GetSession()) groupMember->ForceHealthAndPowerUpdate(); } } } if (!isRaidGroup()) // reset targetIcons for non-raid-groups { for (auto& m_targetIcon : m_targetIcons) m_targetIcon.Clear(); } if (!isBattleGroup()) { // insert into group table CharacterDatabase.PExecute("INSERT INTO group_member(groupId,memberGuid,assistant,subgroup) VALUES('%u','%u','%u','%u')", m_Id, member.guid.GetCounter(), ((member.assistant == 1) ? 1 : 0), member.group); } return true; }
void LfgGroup::TeleportPlayer(Player *plr, DungeonInfo *dungeonInfo, uint32 originalDungeonId, bool newPlr) { if(newPlr) { plr->m_lookingForGroup.queuedDungeons.clear(); // must be before remove grom group if (Group *group = plr->GetGroup()) { if (!group->isLfgGroup()) { group->RemoveMember(plr->GetGUID(), 0); if (group->GetMembersCount() == 0) group->Disband(true); } plr->SetGroup(NULL); } plr->UnbindInstance(dungeonInfo->start_map, m_dungeonInfo->isHeroic() ? DUNGEON_DIFFICULTY_HEROIC : DUNGEON_DIFFICULTY_NORMAL); plr->ResetInstances(INSTANCE_RESET_GROUP_JOIN,false); plr->ResetInstances(INSTANCE_RESET_GROUP_JOIN,true); plr->ResetInstances(INSTANCE_RESET_ALL, true); plr->ResetInstances(INSTANCE_RESET_ALL, false); if (plr->getLevel() >= LEVELREQUIREMENT_HEROIC) { if (plr->GetDungeonDifficulty() != GetDungeonDifficulty()) plr->SetDungeonDifficulty(GetDungeonDifficulty()); if (plr->GetRaidDifficulty() != GetRaidDifficulty()) plr->SetRaidDifficulty(GetRaidDifficulty()); } plr->SetGroup(this, 0); plr->SetGroupInvite(NULL); uint32 taxi_start = 0; uint32 taxi_end = 0; uint32 mount_spell = 0; WorldLocation joinLoc; if (!plr->m_taxi.empty()) { taxi_start = plr->m_taxi.GetTaxiSource(); taxi_end = plr->m_taxi.GetTaxiDestination(); joinLoc = WorldLocation(plr->GetMapId(), plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetOrientation()); } else { // Mount spell id storing if (plr->IsMounted()) { Unit::AuraList const& auras = plr->GetAurasByType(SPELL_AURA_MOUNTED); if (!auras.empty()) mount_spell = (*auras.begin())->GetId(); } if(!mount_spell && plr->getClass() == CLASS_DRUID) { Unit::AuraList const& auras = plr->GetAurasByType(SPELL_AURA_MOD_SHAPESHIFT); if (!auras.empty()) mount_spell = (*auras.begin())->GetId(); } //Nearest graveyard if in dungeon if (plr->GetMap()->IsDungeon()) { if (const WorldSafeLocsEntry* entry = sObjectMgr.GetClosestGraveYard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId(), plr->GetTeam())) joinLoc = WorldLocation(entry->map_id, entry->x, entry->y, entry->z, 0.f); else joinLoc = plr->GetLocation(); } else joinLoc = plr->GetLocation(); } CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(plr->GetGUID())); CharacterDatabase.PExecute("INSERT INTO group_member(groupId,memberGuid,assistant,subgroup,lfg_join_x,lfg_join_y,lfg_join_z,lfg_join_o,lfg_join_map,taxi_start,taxi_end,mount_spell) " "VALUES('%u','%u','%u','%u','%f','%f','%f','%f','%u','%u','%u','%u')", m_Id, GUID_LOPART(plr->GetGUID()), 0, 1, joinLoc.x(), joinLoc.y(), joinLoc.z(), joinLoc.orientation, joinLoc.mapid, taxi_start, taxi_end, mount_spell); //Set info to player plr->m_lookingForGroup.joinLoc = joinLoc; plr->m_lookingForGroup.taxi_start = taxi_start; plr->m_lookingForGroup.taxi_end = taxi_end; plr->m_lookingForGroup.mount_spell = mount_spell; plr->m_lookingForGroup.roles = GetPlayerRole(plr->GetGUID()); if (IsRandom()) plr->CastSpell(plr, LFG_RANDOM_COOLDOWN, true); } // resurrect the player if (!plr->isAlive()) { plr->ResurrectPlayer(1.0f); plr->SpawnCorpseBones(); } // stop taxi flight at port if (plr->isInFlight()) { plr->GetMotionMaster()->MovementExpired(false); plr->GetMotionMaster()->Clear(false, true); plr->GetMotionMaster()->MoveIdle(); plr->m_taxi.ClearTaxiDestinations(); } plr->ScheduleDelayedOperation(DELAYED_LFG_ENTER_DUNGEON); plr->ScheduleDelayedOperation(DELAYED_SAVE_PLAYER); plr->ScheduleDelayedOperation(DELAYED_LFG_CLEAR_LOCKS); if(IsMixed()) { plr->m_lookingForGroup.SetMixedDungeon(dungeonInfo->start_map); if(newPlr) plr->setFaction(sWorld.getConfig(CONFIG_UINT32_TEAM_BG_FACTION_BLUE)); } if (IsInDungeon()) { if(newPlr) { for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player *player = itr->getSource(); if (!player || player->GetMapId() != GetDungeonInfo()->map) continue; plr->TeleportTo(player->GetLocation()); return; } } plr->TeleportTo(dungeonInfo->start_map, dungeonInfo->start_x, dungeonInfo->start_y, dungeonInfo->start_z, dungeonInfo->start_o); return; } //Must re-add player to reset id... Map *map = plr->GetMap(); if(map->GetId() == dungeonInfo->start_map) { map->Remove(plr, false); map->Add(plr); } plr->TeleportTo(dungeonInfo->start_map, dungeonInfo->start_x, dungeonInfo->start_y, dungeonInfo->start_z, dungeonInfo->start_o); }
// return true = remove from update list, false = continue bool LfgGroup::UpdateVoteToKick(uint32 diff) { if (!m_voteToKick.isInProggres) return true; if (diff) { if (m_voteToKick.GetTimeLeft() <= 0) { m_voteToKick.isInProggres = false; for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player *member = sObjectMgr.GetPlayer(citr->guid); if (!member || !member->GetSession()) continue; SendBootPlayer(member); } m_voteToKick.Reset(); return true; } return false; } //Send Update for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player *member = sObjectMgr.GetPlayer(citr->guid); if (!member || !member->GetSession()) continue; SendBootPlayer(member); } if (m_voteToKick.GetVotesNum(false) < 3) return false; else if (m_voteToKick.GetVotesNum(true) >= 3) { Player *victim = sObjectMgr.GetPlayer(m_voteToKick.victim); sLfgMgr.LfgLog("Remove member - afk rolecheck"); RemoveMember(m_voteToKick.victim, 1); if (victim && victim->GetSession()) { victim->ScheduleDelayedOperation(DELAYED_LFG_MOUNT_RESTORE); victim->ScheduleDelayedOperation(DELAYED_LFG_TAXI_RESTORE); victim->ScheduleDelayedOperation(DELAYED_LFG_CLEAR_LOCKS); victim->RemoveAurasDueToSpell(LFG_BOOST); WorldLocation teleLoc = victim->m_lookingForGroup.joinLoc; if (!teleLoc.coords.isNULL()) victim->TeleportTo(teleLoc); else victim->TeleportToHomebind(); } else { AreaTrigger const *trigger = sObjectMgr.GetGoBackTrigger(GetDungeonInfo()->map); if(trigger) Player::SavePositionInDB(trigger->target_mapId, trigger->target_X, trigger->target_Y, trigger->target_Z, trigger->target_Orientation, sTerrainMgr.GetZoneId(trigger->target_mapId, trigger->target_X, trigger->target_Y, trigger->target_Z), m_voteToKick.victim); } //Change leader if (m_voteToKick.victim == m_leaderGuid) { for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player *plr = sObjectMgr.GetPlayer(citr->guid); if (!plr || !plr->GetSession()) continue; if (plr->m_lookingForGroup.roles & LEADER) { ChangeLeader(plr->GetGUID()); break; } } if (m_voteToKick.victim == m_leaderGuid) ChangeLeader(GetFirstMember()->getSource()->GetGUID()); } m_voteToKick.Reset(); SendUpdate(); return true; } return false; }
uint32 Group::RemoveMember(ObjectGuid guid, uint8 method) { Player* player = sObjectMgr.GetPlayer(guid); #ifdef BUILD_PLAYERBOT // if master leaves group, all bots leave group if (player && player->GetPlayerbotMgr()) player->GetPlayerbotMgr()->RemoveAllBotsFromGroup(); #endif for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next()) { if (Player* groupMember = itr->getSource()) { if (groupMember->GetObjectGuid() == guid) continue; groupMember->RemoveAllGroupBuffsFromCaster(guid); if (player) player->RemoveAllGroupBuffsFromCaster(groupMember->GetObjectGuid()); } } // remove member and change leader (if need) only if strong more 2 members _before_ member remove if (GetMembersCount() > GetMembersMinCount()) { bool leaderChanged = _removeMember(guid); if (player) { // quest related GO state dependent from raid membership if (isRaidGroup()) player->UpdateForQuestWorldObjects(); WorldPacket data; if (method == 1) { data.Initialize(SMSG_GROUP_UNINVITE, 0); player->GetSession()->SendPacket(data); } // we already removed player from group and in player->GetGroup() is his original group! if (Group* group = player->GetGroup()) { group->SendUpdate(); } else { data.Initialize(SMSG_GROUP_LIST, 24); data << uint64(0) << uint64(0) << uint64(0); player->GetSession()->SendPacket(data); } _homebindIfInstance(player); } if (leaderChanged) { WorldPacket data(SMSG_GROUP_SET_LEADER, (m_leaderName.size() + 1)); data << m_leaderName; BroadcastPacket(data, true); } SendUpdate(); } // if group before remove <= 2 disband it else Disband(true); return m_memberSlots.size(); }