bool Group::Create(ObjectGuid guid, const char* name) { m_leaderGuid = guid; m_leaderName = name; m_groupType = isBGGroup() ? GROUPTYPE_BGRAID : GROUPTYPE_NORMAL; if (m_groupType & GROUPTYPE_RAID) _initRaidSubGroupsCounter(); m_lootMethod = GROUP_LOOT; m_lootThreshold = ITEM_QUALITY_UNCOMMON; m_masterLooterGuid = guid; m_currentLooterGuid = guid; // used for round robin looter m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL; m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; if (!isBGGroup()) { m_Id = sObjectMgr.GenerateGroupLowGuid(); Player* leader = sObjectMgr.GetPlayer(guid); if (leader) { m_dungeonDifficulty = leader->GetDungeonDifficulty(); m_raidDifficulty = leader->GetRaidDifficulty(); } Player::ConvertInstancesToGroup(leader, this, guid); // store group in database CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM groups WHERE groupId ='%u'", m_Id); CharacterDatabase.PExecute("DELETE FROM group_member WHERE groupId ='%u'", m_Id); CharacterDatabase.PExecute("INSERT INTO groups (groupId,leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,groupType,difficulty,raiddifficulty) " "VALUES ('%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')", m_Id, m_leaderGuid.GetCounter(), m_mainTankGuid.GetCounter(), m_mainAssistantGuid.GetCounter(), uint32(m_lootMethod), m_masterLooterGuid.GetCounter(), uint32(m_lootThreshold), m_targetIcons[0].GetRawValue(), m_targetIcons[1].GetRawValue(), m_targetIcons[2].GetRawValue(), m_targetIcons[3].GetRawValue(), m_targetIcons[4].GetRawValue(), m_targetIcons[5].GetRawValue(), m_targetIcons[6].GetRawValue(), m_targetIcons[7].GetRawValue(), uint8(m_groupType), uint32(m_dungeonDifficulty), uint32(m_raidDifficulty)); } if (!AddMember(guid, name)) return false; if (!isBGGroup()) CharacterDatabase.CommitTransaction(); _updateLeaderFlag(); return true; }
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); MemberSlot member; member.guid = guid; member.name = name; member.group = group; member.assistant = isAssistant; m_memberSlots.push_back(member); SubGroupCounterIncrease(group); if (player) { player->SetGroupInvite(NULL); // if player is in group and he is being added to BG raid group, then call SetBattleGroundRaid() if (player->GetGroup() && isBGGroup()) 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 (!isRaidGroup()) // reset targetIcons for non-raid-groups { for (int i = 0; i < TARGET_ICON_COUNT; ++i) m_targetIcons[i].Clear(); } if (!isBGGroup()) { // 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 Group::SendUpdate() { for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player* player = sObjectMgr.GetPlayer(citr->guid); if (!player || !player->GetSession() || player->GetGroup() != this) continue; // guess size WorldPacket data(SMSG_GROUP_LIST, (1 + 1 + 1 + 1 + 8 + 4 + GetMembersCount() * 20)); data << uint8(m_groupType); // group type (flags in 3.3) data << uint8(citr->group); // groupid data << uint8(GetFlags(*citr)); // group flags data << uint8(isBGGroup() ? 1 : 0); // 2.0.x, isBattleGroundGroup? if (m_groupType & GROUPTYPE_LFD) { data << uint8(0); data << uint32(0); } data << GetObjectGuid(); // group guid data << uint32(0); // 3.3, this value increments every time SMSG_GROUP_LIST is sent data << uint32(GetMembersCount() - 1); for (member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2) { if (citr->guid == citr2->guid) continue; Player* member = sObjectMgr.GetPlayer(citr2->guid); uint8 onlineState = (member && member->GetSession() && !member->GetSession()->PlayerLogout()) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0); data << citr2->name; data << citr2->guid; data << uint8(onlineState); data << uint8(citr2->group); // groupid data << uint8(GetFlags(*citr2)); // group flags data << uint8(0); // 3.3, role? } ObjectGuid masterLootGuid = (m_lootMethod == MASTER_LOOT) ? m_masterLooterGuid : ObjectGuid(); data << m_leaderGuid; // leader guid if (GetMembersCount() - 1) { data << uint8(m_lootMethod); // loot method data << masterLootGuid; // master loot guid data << uint8(m_lootThreshold); // loot threshold data << uint8(m_dungeonDifficulty); // Dungeon Difficulty data << uint8(m_raidDifficulty); // Raid Difficulty data << uint8(0); // 3.3, dynamic difficulty? } player->GetSession()->SendPacket(&data); } }
bool Group::AddMember(ObjectGuid guid, const char* name) { if (!_addMember(guid, name)) return false; SendUpdate(); if (Player* player = sObjectMgr.GetPlayer(guid)) { if (!IsLeader(player->GetObjectGuid()) && !isBGGroup()) { // reset the new member's instances, unless he is currently in one of them // including raid/heroic instances that they are not permanently bound to! player->ResetInstances(INSTANCE_RESET_GROUP_JOIN); if (player->getLevel() >= LEVELREQUIREMENT_HEROIC && player->GetDifficulty() != GetDifficulty()) { player->SetDifficulty(GetDifficulty()); player->SendDungeonDifficulty(true); } } player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); UpdatePlayerOutOfRange(player); // used by eluna GlobalEluna(OnAddMember(this, player->GetObjectGuid())); // quest related GO state dependent from raid membership if (isRaidGroup()) player->UpdateForQuestWorldObjects(); } return true; }
bool Group::AddMember(ObjectGuid guid, const char* name) { if (!_addMember(guid, name)) return false; SendUpdate(); if (Player* player = sObjectMgr.GetPlayer(guid)) { if (!IsLeader(player->GetObjectGuid()) && !isBGGroup()) { // reset the new member's instances, unless he is currently in one of them // including raid instances that they are not permanently bound to! player->ResetInstances(INSTANCE_RESET_GROUP_JOIN); } player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); UpdatePlayerOutOfRange(player); // quest related GO state dependent from raid membership if (isRaidGroup()) player->UpdateForQuestWorldObjects(); } return true; }
InstanceGroupBind* Group::BindToInstance(DungeonPersistentState* state, bool permanent, bool load) { if (state && !isBGGroup()) { InstanceGroupBind& bind = m_boundInstances[state->GetMapId()]; if (bind.state) { // when a boss is killed or when copying the players's binds to the group if (permanent != bind.perm || state != bind.state) if (!load) CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u', permanent = '%u' WHERE leaderGuid = '%u' AND instance = '%u'", state->GetInstanceId(), permanent, GetLeaderGuid().GetCounter(), bind.state->GetInstanceId()); } else if (!load) CharacterDatabase.PExecute("INSERT INTO group_instance (leaderGuid, instance, permanent) VALUES ('%u', '%u', '%u')", GetLeaderGuid().GetCounter(), state->GetInstanceId(), permanent); if (bind.state != state) { if (bind.state) bind.state->RemoveGroup(this); state->AddGroup(this); } bind.state = state; bind.perm = permanent; if (!load) DEBUG_LOG("Group::BindToInstance: Group (Id: %d) is now bound to map %d, instance %d", GetId(), state->GetMapId(), state->GetInstanceId()); return &bind; } else return NULL; }
void Group::_setLeader(ObjectGuid guid) { member_citerator slot = _getMemberCSlot(guid); if (slot == m_memberSlots.end()) return; if (!isBGGroup()) { uint32 slot_lowguid = slot->guid.GetCounter(); uint32 leader_lowguid = m_leaderGuid.GetCounter(); // TODO: set a time limit to have this function run rarely cause it can be slow CharacterDatabase.BeginTransaction(); // update the group's bound instances when changing leaders // remove all permanent binds from the group // in the DB also remove solo binds that will be replaced with permbinds // from the new leader CharacterDatabase.PExecute( "DELETE FROM group_instance WHERE leaderguid='%u' AND (permanent = 1 OR " "instance IN (SELECT instance FROM character_instance WHERE guid = '%u')" ")", leader_lowguid, slot_lowguid); Player* player = sObjectMgr.GetPlayer(slot->guid); if (player) { for (BoundInstancesMap::iterator itr = m_boundInstances.begin(); itr != m_boundInstances.end();) { if (itr->second.perm) { itr->second.state->RemoveGroup(this); m_boundInstances.erase(itr++); } else ++itr; } } // update the group's solo binds to the new leader CharacterDatabase.PExecute("UPDATE group_instance SET leaderGuid='%u' WHERE leaderGuid = '%u'", slot_lowguid, leader_lowguid); // copy the permanent binds from the new leader to the group // overwriting the solo binds with permanent ones if necessary // in the DB those have been deleted already Player::ConvertInstancesToGroup(player, this, slot->guid); // update the group leader CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE groupId='%u'", slot_lowguid, m_Id); CharacterDatabase.CommitTransaction(); } _updateLeaderFlag(true); m_leaderGuid = slot->guid; m_leaderName = slot->name; _updateLeaderFlag(); }
void Group::ResetInstances(InstanceResetMethod method, Player* SendMsgTo) { if (isBGGroup()) return; // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_GROUP_DISBAND for (BoundInstancesMap::iterator itr = m_boundInstances.begin(); itr != m_boundInstances.end();) { DungeonPersistentState* state = itr->second.state; const MapEntry* entry = sMapStore.LookupEntry(itr->first); if (!entry || (!state->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND)) { ++itr; continue; } if (method == INSTANCE_RESET_ALL) { // the "reset all instances" method can only reset normal maps if (entry->map_type == MAP_RAID) { ++itr; continue; } } bool isEmpty = true; // if the map is loaded, reset it if (Map* map = sMapMgr.FindMap(state->GetMapId(), state->GetInstanceId())) if (map->IsDungeon() && !(method == INSTANCE_RESET_GROUP_DISBAND && !state->CanReset())) isEmpty = ((DungeonMap*)map)->Reset(method); if (SendMsgTo) { if (isEmpty) SendMsgTo->SendResetInstanceSuccess(state->GetMapId()); else SendMsgTo->SendResetInstanceFailed(0, state->GetMapId()); } if (isEmpty || method == INSTANCE_RESET_GROUP_DISBAND) { // do not reset the instance, just unbind if others are permanently bound to it if (state->CanReset()) state->DeleteFromDB(); else CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", state->GetInstanceId()); // i don't know for sure if hash_map iterators m_boundInstances.erase(itr); itr = m_boundInstances.begin(); // this unloads the instance save unless online players are bound to it // (eg. permanent binds or GM solo binds) state->RemoveGroup(this); } else ++itr; } }
uint32 Group::RemoveMember(ObjectGuid guid, uint8 method) { //Playerbot mod - if master leaves group, all bots leave group { Player* const player = sObjectMgr.GetPlayer(guid); if (player && player->GetPlayerbotMgr()) player->GetPlayerbotMgr()->RemoveAllBotsFromGroup(); } //END Playerbot mod // remove member and change leader (if need) only if strong more 2 members _before_ member remove if (GetMembersCount() > uint32(isBGGroup() ? 1 : 2)) // in BG group case allow 1 members group { bool leaderChanged = _removeMember(guid); if (Player* player = sObjectMgr.GetPlayer(guid)) { // 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_memberSlots.front().name.size() + 1)); data << m_memberSlots.front().name; BroadcastPacket(&data, true); } SendUpdate(); } // if group before remove <= 2 disband it else Disband(true); return m_memberSlots.size(); }
void LfgGroup::SendUpdate() { Player *player; for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { player = sObjectMgr.GetPlayer(citr->guid); if (!player || !player->GetSession() || player->GetGroup() != this ) continue; // guess size WorldPacket data(SMSG_GROUP_LIST, (1+1+1+1+8+4+GetMembersCount()*20)); data << uint8(m_groupType); // group type (flags in 3.3) data << uint8(citr->group); // groupid data << uint8(GetFlags(*citr)); // group flags data << uint8(GetPlayerRole(citr->guid)); // 2.0.x, isBattleGroundGroup? <--- Its flags or maybe more likely roles....? data << uint8(m_instanceStatus); // Instance status 0= not saved, 1= saved, 2 = completed data << uint32(GetDungeonInfo(IsFromRnd(citr->guid))->Entry());// dungeon entry data << uint64(0x1F54000004D3B000); // related to voice chat? data << uint32(0); // 3.3, this value increments every time SMSG_GROUP_LIST is sent data << uint32(GetMembersCount()-1); for(member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2) { if (citr->guid == citr2->guid) continue; Player* member = sObjectMgr.GetPlayer(citr2->guid); uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0); if(member) { if(member->isAFK()) onlineState |= MEMBER_STATUS_AFK; if(member->isDND()) onlineState |= MEMBER_STATUS_DND; } data << citr2->name; data << uint64(citr2->guid); data << uint8(onlineState); // online-state data << uint8(citr2->group); // groupid data << uint8(GetFlags(*citr2)); // group flags data << uint8(GetPlayerRole(citr2->guid)); // 3.3, role? } data << uint64(m_leaderGuid); // leader guid if (GetMembersCount()-1) { data << uint8(m_lootMethod); // loot method data << uint64(m_looterGuid); // looter guid data << uint8(m_lootThreshold); // loot threshold data << uint8(m_dungeonDifficulty); // Dungeon Difficulty data << uint8(m_raidDifficulty); // Raid Difficulty data << uint8(0); // 3.3, dynamic difficulty? } player->GetSession()->SendPacket( &data ); } }
void Group::SendUpdate() { for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { Player* player = sObjectMgr.GetPlayer(citr->guid); if (!player || !player->GetSession() || player->GetGroup() != this) continue; // guess size WorldPacket data(SMSG_GROUP_LIST, (1 + 1 + 1 + 1 + 8 + 4 + GetMembersCount() * 20)); data << uint8(m_groupType); // group type data << uint8(isBGGroup() ? 1 : 0); // 2.0.x, isBattleGroundGroup? data << uint8(citr->group); // groupid data << uint8(citr->assistant ? 0x01 : 0); // 0x2 main assist, 0x4 main tank data << GetObjectGuid(); // group guid data << uint32(GetMembersCount() - 1); for (member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2) { if (citr->guid == citr2->guid) continue; Player* member = sObjectMgr.GetPlayer(citr2->guid); uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0); data << citr2->name; data << citr2->guid; // online-state data << uint8(sObjectMgr.GetPlayer(citr2->guid) ? 1 : 0); data << uint8(citr2->group); // groupid data << uint8(citr2->assistant ? 0x01 : 0); // 0x2 main assist, 0x4 main tank } ObjectGuid masterLootGuid = (m_lootMethod == MASTER_LOOT) ? m_masterLooterGuid : ObjectGuid(); data << m_leaderGuid; // leader guid if (GetMembersCount() - 1) { data << uint8(m_lootMethod); // loot method data << masterLootGuid; // master loot guid data << uint8(m_lootThreshold); // loot threshold data << uint8(m_difficulty); // Heroic Mod Group } player->GetSession()->SendPacket(&data); } }
bool Group::_setAssistantFlag(ObjectGuid guid, const bool& state) { member_witerator slot = _getMemberWSlot(guid); if (slot == m_memberSlots.end()) return false; slot->assistant = state; if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET assistant='%u' WHERE memberGuid='%u'", (state == true) ? 1 : 0, guid.GetCounter()); return true; }
bool Group::_removeMember(ObjectGuid guid) { Player* player = sObjectMgr.GetPlayer(guid); if (player) { // if we are removing player from battleground raid if (isBGGroup()) player->RemoveFromBattleGroundRaid(); else { // we can remove player who is in battleground from his original group if (player->GetOriginalGroup() == this) player->SetOriginalGroup(nullptr); else player->SetGroup(nullptr); } } member_witerator slot = _getMemberWSlot(guid); if (slot != m_memberSlots.end()) { SubGroupCounterDecrease(slot->group); m_memberSlots.erase(slot); } if (!isBGGroup()) CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", guid.GetCounter()); if (m_leaderGuid == guid) // leader was removed { _updateLeaderFlag(true); if (GetMembersCount() > 0) _setLeader(m_memberSlots.front().guid); return true; } return false; }
void Group::ConvertToRaid() { m_groupType = GROUPTYPE_RAID; _initRaidSubGroupsCounter(); if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE groupId='%u'", m_Id); SendUpdate(); // update quest related GO states (quest activity dependent from raid membership) for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) if (Player* player = sObjectMgr.GetPlayer(citr->guid)) player->UpdateForQuestWorldObjects(); }
bool Group::_setMembersGroup(ObjectGuid guid, uint8 group) { member_witerator slot = _getMemberWSlot(guid); if (slot == m_memberSlots.end()) return false; slot->group = group; SubGroupCounterIncrease(group); if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, guid.GetCounter()); return true; }
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); } }
void Group::SendUpdate() { Player* player; for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { player = sObjectMgr.GetPlayer(citr->guid); if (!player || !player->GetSession() || player->GetGroup() != this) continue; // guess size WorldPacket data(SMSG_GROUP_LIST, (1 + 1 + 1 + 4 + GetMembersCount() * 20) + 8 + 1 + 8 + 1); data << (uint8)m_groupType; // group type data << (uint8)(citr->group | (citr->assistant ? 0x80 : 0)); // own flags (groupid | (assistant?0x80:0)) data << uint32(GetMembersCount() - 1); for (member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2) { if (citr->guid == citr2->guid) continue; Player* member = sObjectMgr.GetPlayer(citr2->guid); uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE; onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0); data << citr2->name; data << citr2->guid; // online-state data << uint8(sObjectMgr.GetPlayer(citr2->guid) ? 1 : 0); data << (uint8)(citr2->group | (citr2->assistant ? 0x80 : 0)); } ObjectGuid masterLootGuid = (m_lootMethod == MASTER_LOOT) ? m_masterLooterGuid : ObjectGuid(); data << m_leaderGuid; // leader guid if (GetMembersCount() - 1) { data << uint8(m_lootMethod); // loot method data << masterLootGuid; // master loot guid data << uint8(m_lootThreshold); // loot threshold } player->GetSession()->SendPacket(&data); } }
bool Group::_setMainTank(ObjectGuid guid) { if (m_mainTankGuid == guid) return false; if (guid) { member_citerator slot = _getMemberCSlot(guid); if (slot == m_memberSlots.end()) return false; if (m_mainAssistantGuid == guid) _setMainAssistant(ObjectGuid()); } m_mainTankGuid = guid; if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET mainTank='%u' WHERE groupId='%u'", m_mainTankGuid.GetCounter(), m_Id); return true; }
void Group::ResetInstances(InstanceResetMethod method, bool isRaid, Player* SendMsgTo) { if (isBGGroup()) return; // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND // we assume that when the difficulty changes, all instances that can be reset will be Difficulty diff = GetDifficulty(isRaid); typedef std::set<uint32> OfflineMapSet; OfflineMapSet mapsWithOfflinePlayer; // to store map of offline players if (method != INSTANCE_RESET_GROUP_DISBAND) { // Store maps in which are offline members for instance reset check. for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) { if (!ObjectAccessor::FindPlayer(itr->guid)) mapsWithOfflinePlayer.insert(itr->lastMap); // add last map from offline player } } for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end();) { DungeonPersistentState* state = itr->second.state; const MapEntry* entry = sMapStore.LookupEntry(itr->first); if (!entry || entry->IsRaid() != isRaid || (!state->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND)) { ++itr; continue; } if (method == INSTANCE_RESET_ALL) { // the "reset all instances" method can only reset normal maps if (entry->map_type == MAP_RAID || diff == DUNGEON_DIFFICULTY_HEROIC) { ++itr; continue; } } bool isEmpty = true; // check if there are offline members on the map if (method != INSTANCE_RESET_GROUP_DISBAND && mapsWithOfflinePlayer.find(state->GetMapId()) != mapsWithOfflinePlayer.end()) isEmpty = false; // if the map is loaded, reset it if can if (isEmpty && entry->IsDungeon() && !(method == INSTANCE_RESET_GROUP_DISBAND && !state->CanReset())) if (Map* map = sMapMgr.FindMap(state->GetMapId(), state->GetInstanceId())) isEmpty = ((DungeonMap*)map)->Reset(method); if (SendMsgTo) { if (isEmpty) SendMsgTo->SendResetInstanceSuccess(state->GetMapId()); else SendMsgTo->SendResetInstanceFailed(0, state->GetMapId()); } // TODO - Adapt here when clear how difficulty changes must be handled if (isEmpty || method == INSTANCE_RESET_GROUP_DISBAND || method == INSTANCE_RESET_CHANGE_DIFFICULTY) { // do not reset the instance, just unbind if others are permanently bound to it if (state->CanReset()) state->DeleteFromDB(); else CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", state->GetInstanceId()); // i don't know for sure if hash_map iterators m_boundInstances[diff].erase(itr); itr = m_boundInstances[diff].begin(); // this unloads the instance save unless online players are bound to it // (eg. permanent binds or GM solo binds) state->RemoveGroup(this); } else ++itr; } }
void Group::Disband(bool hideDestroy) { Player* player; for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { player = sObjectMgr.GetPlayer(citr->guid); if (!player) continue; // we cannot call _removeMember because it would invalidate member iterator // if we are removing player from battleground raid if (isBGGroup()) player->RemoveFromBattleGroundRaid(); else { // we can remove player who is in battleground from his original group if (player->GetOriginalGroup() == this) player->SetOriginalGroup(NULL); else player->SetGroup(NULL); } // quest related GO state dependent from raid membership if (isRaidGroup()) player->UpdateForQuestWorldObjects(); if (!player->GetSession()) continue; WorldPacket data; if (!hideDestroy) { data.Initialize(SMSG_GROUP_DESTROYED, 0); player->GetSession()->SendPacket(&data); } // we already removed player from group and in player->GetGroup() is his original group, send update 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); } m_memberSlots.clear(); RemoveAllInvites(); if (!isBGGroup()) { CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM groups WHERE groupId='%u'", m_Id); CharacterDatabase.PExecute("DELETE FROM group_member WHERE groupId='%u'", m_Id); CharacterDatabase.CommitTransaction(); ResetInstances(INSTANCE_RESET_GROUP_DISBAND, NULL); } m_leaderGuid.Clear(); m_leaderName.clear(); }