//////////////////////////////////////////////////////////////// ///This function handles CMSG_GROUP_ACCEPT: //////////////////////////////////////////////////////////////// void WorldSession::HandleGroupAcceptOpcode( WorldPacket & recv_data ) { if(!_player->IsInWorld()) return; Player *player = objmgr.GetPlayer(_player->GetInviter()); if ( !player ) return; player->SetInviter(0); _player->SetInviter(0); Group *grp = player->GetGroup(); if(grp) { grp->AddMember(_player->m_playerInfo); if(grp->GetLeader()->m_loggedInPlayer) _player->iInstanceType = grp->GetLeader()->m_loggedInPlayer->iInstanceType; _player->GetSession()->OutPacket(MSG_SET_DUNGEON_DIFFICULTY, 4, &_player->iInstanceType); return; } // If we're this far, it means we have no existing group, and have to make one. grp = new Group(true); grp->AddMember(player->m_playerInfo); // add the inviter first, therefore he is the leader grp->AddMember(_player->m_playerInfo); // add us. _player->iInstanceType = player->iInstanceType; _player->GetSession()->OutPacket(MSG_SET_DUNGEON_DIFFICULTY, 4, &player->iInstanceType); }
void WorldSession::HandleReadyCheckOpcode(WorldPacket& recv_data) { Group * pGroup = _player->GetGroup(); if(!pGroup || !_player->IsInWorld()) return; if(recv_data.size() == 0) { if(pGroup->GetLeader() == _player->m_playerInfo) { WorldPacket data(MSG_RAID_READY_CHECK, 8); data << GetPlayer()->GetGUID(); /* send packet to group */ pGroup->SendPacketToAll(&data); } else { SendNotification(NOTIFICATION_MESSAGE_NO_PERMISSION); } } else { uint8 ready; recv_data >> ready; WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); data << _player->GetGUID(); data << ready; if(pGroup->GetLeader() && pGroup->GetLeader()->m_loggedInPlayer) pGroup->GetLeader()->m_loggedInPlayer->GetSession()->SendPacket(&data); } }
//////////////////////////////////////////////////////////////// ///This function handles CMSG_GROUP_ACCEPT: //////////////////////////////////////////////////////////////// void WorldSession::HandleGroupAcceptOpcode( WorldPacket & recv_data ) { if(!_player->IsInWorld()) return; Player *player = objmgr.GetPlayer(_player->GetInviter()); if ( !player ) return; player->SetInviter(0); _player->SetInviter(0); Group *grp = player->GetGroup(); if(grp) { grp->AddMember(_player); _player->iInstanceType = grp->GetLeader()->iInstanceType; _player->GetSession()->OutPacket(CMSG_DUNGEON_DIFFICULTY, 4, &grp->GetLeader()->iInstanceType); sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); return; } // If we're this far, it means we have no existing group, and have to make one. grp = new Group; grp->AddMember(player); // add the inviter first, therefore he is the leader grp->AddMember(_player); // add us. _player->iInstanceType = player->iInstanceType; _player->GetSession()->OutPacket(CMSG_DUNGEON_DIFFICULTY, 4, &player->iInstanceType); sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); // Currentgroup and all that shit are set by addmember. }
TEST(NeffKeyShuffle, Disconnect) { SessionCreator callback = SessionCreator(TCreateRound<NeffKeyShuffle>); Group::SubgroupPolicy sg_policy = Group::ManagedSubgroup; ConnectionManager::UseTimer = false; SessionLeader::EnableLogOffMonitor = false; Timer::GetInstance().UseVirtualTime(); int count = Random::GetInstance().GetInt(TEST_RANGE_MIN, TEST_RANGE_MAX); QVector<TestNode *> nodes; Group group; ConstructOverlay(count, nodes, group, sg_policy); CreateSessions(nodes, group, Id(), callback); group = BuildGroup(nodes, group); int leader = group.GetIndex(group.GetLeader()); int disconnector = Random::GetInstance().GetInt(0, count); if(sg_policy == Group::ManagedSubgroup) { while(leader == disconnector || nodes[disconnector]->ident.GetSuperPeer()) { disconnector = Random::GetInstance().GetInt(0, count); } } else { while(leader == disconnector) { disconnector = Random::GetInstance().GetInt(0, count); } } qDebug() << "Node count" << nodes.size(); qDebug() << "Leader" << group.GetLeader(); qDebug() << "Disconnector" << nodes[disconnector]->ident.GetLocalId(); SignalCounter sc, src; RoundCollector rc; foreach(TestNode *node, nodes) { QObject::connect(node->session.data(), SIGNAL(RoundStarting(const QSharedPointer<Round> &)), &sc, SLOT(Counter())); QObject::connect(node->session.data(), SIGNAL(RoundFinished(const QSharedPointer<Round> &)), &src, SLOT(Counter())); QObject::connect(node->session.data(), SIGNAL(RoundFinished(const QSharedPointer<Round> &)), &rc, SLOT(RoundFinished(const QSharedPointer<Round> &))); node->session->Start(); }
void WorldSession::HandleLfgLeaveOpcode(WorldPacket& recv_data) { Log.Debug("LfgHandler", "CMSG_LFG_LEAVE"); Group* grp = GetPlayer()->GetGroup(); Log.Debug("LfgHandler", "CMSG_LFG_LEAVE %u in group: %u", GetPlayer()->GetGUID(), grp ? 1 : 0); // Check cheating - only leader can leave the queue if (!grp || grp->GetLeader()->guid == GetPlayer()->GetGUID()) sLfgMgr.Leave(GetPlayer(), grp); }
void WorldSession::HandleConvertGroupToRaidOpcode(WorldPacket & recv_data) { if(!_player->IsInWorld()) return; // This is just soooo easy now Group *pGroup = _player->GetGroup(); if(!pGroup) return; if ( pGroup->GetLeader() != _player->m_playerInfo ) //access denied { SendPartyCommandResult(_player, 0, "", ERR_PARTY_YOU_ARE_NOT_LEADER); return; } pGroup->ExpandToRaid(); SendPartyCommandResult(_player, 0, "", ERR_PARTY_NO_ERROR); }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo* inf = WorldMapInfoStorage.LookupEntry(mapid); Group* pGroup; InstanceMap* instancemap; Instance* in; if(inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type == INSTANCE_BATTLEGROUND) return INSTANCE_ABORT_NOT_FOUND; pGroup = plr->GetGroup(); // players without groups cannot enter raids and heroic instances if(pGroup == NULL && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; if(pGroup == NULL && (inf->type == INSTANCE_NONRAID && plr->iInstanceType == MODE_HEROIC) && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // players without raid groups cannot enter raid instances if(pGroup != NULL && pGroup->GetGroupType() != GROUP_TYPE_RAID && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // We deny transfer if we requested a heroic instance of a map that has no heroic mode // We are trying to enter into a non-multi instance with a heroic group, downscaling if(inf->type == INSTANCE_NONRAID && plr->GetDungeonDifficulty() == MODE_HEROIC) { plr->SetDungeonDifficulty(MODE_NORMAL); plr->SendDungeonDifficulty(); Group* grp = plr->GetGroup(); if(grp != NULL) grp->SetDungeonDifficulty(MODE_NORMAL); } // if it's not a normal / 10men normal then check if we even have this mode if(inf->type == INSTANCE_RAID && plr->GetRaidDifficulty() != MODE_NORMAL_10MEN) { uint32 newtype = 0; if(!inf->HasDifficulty(plr->GetRaidDifficulty())) { // no it doesn't so we will downscale it /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This part is totally speculative, if you know how this is done actually then do change it // switch(plr->GetRaidDifficulty()) { case MODE_NORMAL_25MEN: case MODE_HEROIC_10MEN: { newtype = MODE_NORMAL_10MEN; break; } case MODE_HEROIC_25MEN: { newtype = MODE_NORMAL_25MEN; break; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // check if we have this mode if(!inf->HasDifficulty(newtype)) { //appearantly we don't so we set to 10men normal, which is the default for old raids too //regardless of their playerlimit newtype = MODE_NORMAL_10MEN; } // Setting the new mode on us and our group if(plr->GetRaidDifficulty() != newtype) { plr->SetRaidDifficulty(newtype); plr->SendRaidDifficulty(); Group* grp = plr->GetGroup(); if(grp != NULL) grp->SetRaidDifficulty(newtype); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // If we are here, it means: // 1.) We're a simple non-raid and non-heroic dungeon // 2.) We're a multi-dungeon set to heroic and we are in a group // 3.) We're a raid, and we are in a raid group // 4.) We're a raid, we are in a raid group, and we have the right mode set // // So, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // Otherwise, we will try to create them a new one. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// m_mapLock.Acquire(); instancemap = m_instances[mapid]; // If there are no instances of this map yet, we need to create the map if(instancemap == NULL) { if(instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; // this is the case when we enter an already existing instance ( with summons for example ) if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { in = itr->second; if(!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... m_mapLock.Release(); sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if(pGroup) in->m_creatorGroup = pGroup->GetID(); m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else // this is the case when we enter the normal way (e.g. we enter thru the portal ) { in = NULL; if(pGroup != NULL) // we are in a group { uint32 grpdiff; // We want to use the raid difficulty for raids, and dungeon difficulty for dungeons if(inf->type == INSTANCE_RAID) grpdiff = pGroup->m_raiddifficulty; else grpdiff = pGroup->m_difficulty; if((inf->type == INSTANCE_MULTIMODE && grpdiff == MODE_HEROIC) || inf->type == INSTANCE_RAID) { // This is the case when we don't have this map on this difficulty saved yet for the player entering if(plr->GetPersistentInstanceId(mapid, grpdiff) == 0) { // The group has this instance saved already so we will use it if(pGroup->m_instanceIds[mapid][ grpdiff ] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][ grpdiff ]); } else if(sWorld.instance_TakeGroupLeaderID) { PlayerInfo* pLeaderInfo = pGroup->GetLeader(); if(pLeaderInfo) { pLeaderInfo->savedInstanceIdsLock.Acquire(); PlayerInstanceMap::iterator itrLeader = pLeaderInfo->savedInstanceIds[ grpdiff ].find(mapid); if(itrLeader != pLeaderInfo->savedInstanceIds[ grpdiff ].end()) { in = sInstanceMgr.GetInstanceByIds(mapid, (*itrLeader).second); } pLeaderInfo->savedInstanceIdsLock.Release(); } } } // If we have it saved to the player then use that if(in == NULL && plr->GetPersistentInstanceId(mapid, grpdiff) != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, plr->GetPersistentInstanceId(mapid, grpdiff)); } } else { if(pGroup->m_instanceIds[mapid][ grpdiff ] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][ grpdiff ]); } } } if(in == NULL) { // We are not in a group, so we will look for an instance that we own and has the right difficulty uint32 diff; if(inf->type == INSTANCE_RAID) diff = plr->GetRaidDifficulty(); else diff = plr->GetDungeonDifficulty(); for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(in->m_difficulty == diff && PlayerOwnsInstance(in, plr)) break; in = NULL; } } // We've found an instance! if(in != NULL) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr) { if(in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if(in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } if(!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if(pGroup) in->m_creatorGroup = pGroup->GetID(); plr->SetInstanceID(in->m_instanceId); // found our instance, allow him in. return INSTANCE_OK; } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; switch(inf->type) { case INSTANCE_NONRAID: case INSTANCE_MULTIMODE: in->m_difficulty = plr->GetDungeonDifficulty(); break; case INSTANCE_RAID: in->m_difficulty = plr->GetRaidDifficulty(); break; } in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapInfo = inf; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_isBattleground = false; in->m_persistent = IS_PERSISTENT_INSTANCE(in) && objmgr.m_InstanceBossInfoMap[mapid] == NULL; in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; if(sWorld.instance_SlidingExpiration) { if(inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_HEROIC) in->m_expiration = UNIXTIME + TIME_DAY; else in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } else { if(inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) { in->m_expiration = UNIXTIME - (UNIXTIME % TIME_DAY) + ((UNIXTIME % TIME_DAY) > (sWorld.instance_DailyHeroicInstanceResetHour * TIME_HOUR) ? 82800 : -3600) + ((sWorld.instance_DailyHeroicInstanceResetHour - sWorld.GMTTimeZone) * TIME_HOUR); } else if(IS_PERSISTENT_INSTANCE(in)) { if(m_nextInstanceReset[in->m_mapId] == 0) { m_nextInstanceReset[in->m_mapId] = UNIXTIME - (UNIXTIME % TIME_DAY) - ((sWorld.GMTTimeZone + 1) * TIME_HOUR) + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); CharacterDatabase.Execute("DELETE FROM server_settings WHERE setting_id LIKE 'next_instance_reset_%u';", in->m_mapId); CharacterDatabase.Execute("INSERT INTO server_settings VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } if(m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME) { do { time_t tmp = m_nextInstanceReset[in->m_mapId]; if(tmp + (TIME_MINUTE * 15) < UNIXTIME) m_nextInstanceReset[in->m_mapId] = tmp + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); } while(m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME); CharacterDatabase.Execute("DELETE FROM server_settings WHERE setting_id LIKE 'next_instance_reset_%u';", in->m_mapId); CharacterDatabase.Execute("INSERT INTO server_settings VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } in->m_expiration = m_nextInstanceReset[in->m_mapId]; } else { in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } } plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert(InstanceMap::value_type(in->m_instanceId, in)); // Try to add instance ID to player plr->SetPersistentInstanceId(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
void CBattlegroundManager::HandleArenaJoin(WorldSession * m_session, uint32 BattlegroundType, uint8 as_group, uint8 rated_match) { uint32 pguid = m_session->GetPlayer()->GetLowGUID(); uint32 lgroup = GetLevelGrouping(m_session->GetPlayer()->getLevel()); if(as_group && m_session->GetPlayer()->GetGroup() == NULL) return; Group * pGroup = m_session->GetPlayer()->GetGroup(); if(as_group) { if(pGroup->GetSubGroupCount() != 1) { m_session->SystemMessage("Sorry, raid groups joining battlegrounds are currently unsupported."); return; } if(pGroup->GetLeader() != m_session->GetPlayer()->m_playerInfo) { m_session->SystemMessage("You must be the party leader to add a group to an arena."); return; } GroupMembersSet::iterator itx; if(!rated_match) { /* add all players normally.. bleh ;P */ pGroup->Lock(); for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if((*itx)->m_loggedInPlayer && !(*itx)->m_loggedInPlayer->m_bgIsQueued && !(*itx)->m_loggedInPlayer->m_bg) HandleArenaJoin((*itx)->m_loggedInPlayer->GetSession(), BattlegroundType, 0, 0); } pGroup->Unlock(); return; } else { /* make sure all players are 70 */ uint32 maxplayers; uint32 arenateamtype; switch(BattlegroundType) { case BATTLEGROUND_ARENA_2V2: arenateamtype=0; maxplayers=2; break; case BATTLEGROUND_ARENA_3V3: arenateamtype=1; maxplayers=3; break; case BATTLEGROUND_ARENA_5V5: arenateamtype=2; maxplayers=5; break; default: arenateamtype=0; maxplayers=2; break; } uint32 team_id = 0; pGroup->Lock(); for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if( maxplayers == 0 ) { m_session->SystemMessage("You have too many players in your party to join this type of arena."); pGroup->Unlock(); return; } if((*itx)->lastLevel < 70) { m_session->SystemMessage("Sorry, some of your party members are not level 70."); pGroup->Unlock(); return; } if((*itx)->m_loggedInPlayer) { ArenaTeam * t = (*itx)->m_loggedInPlayer->m_arenaTeams[arenateamtype]; if( t != NULL ) { if ( team_id == 0 ) team_id = t->m_id; if ( team_id != t->m_id ) { m_session->SystemMessage("Sorry, not all your party members are in same arena team."); pGroup->Unlock(); return; } } else { m_session->SystemMessage("Sorry, not all your party members are in same arena team."); pGroup->Unlock(); return; } if( (*itx)->m_loggedInPlayer->m_bgIsQueued ) BattlegroundManager.RemovePlayerFromQueues((*itx)->m_loggedInPlayer); /* if((*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bgIsQueued) { m_session->SystemMessage("One or more of your party members are already queued or inside a battleground."); pGroup->Unlock(); return; } */ --maxplayers; } } if( maxplayers > 0 ) { m_session->SystemMessage("Sorry, you have too few valid arena members in your group."); pGroup->Unlock(); return; } WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(6); // all arenas for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if((*itx)->m_loggedInPlayer) { SendBattlefieldStatus((*itx)->m_loggedInPlayer, 1, BattlegroundType, 0 , 0, 0,1); (*itx)->m_loggedInPlayer->m_bgIsQueued = true; (*itx)->m_loggedInPlayer->m_bgQueueInstanceId = 0; (*itx)->m_loggedInPlayer->m_bgQueueType = BattlegroundType; (*itx)->m_loggedInPlayer->GetSession()->SendPacket(&data); (*itx)->m_loggedInPlayer->m_bgEntryPointX=(*itx)->m_loggedInPlayer->GetPositionX(); (*itx)->m_loggedInPlayer->m_bgEntryPointY=(*itx)->m_loggedInPlayer->GetPositionY(); (*itx)->m_loggedInPlayer->m_bgEntryPointZ=(*itx)->m_loggedInPlayer->GetPositionZ(); (*itx)->m_loggedInPlayer->m_bgEntryPointMap=(*itx)->m_loggedInPlayer->GetMapId(); } } pGroup->Unlock(); m_queueLock.Acquire(); m_queuedGroups[BattlegroundType].push_back(pGroup->GetID()); m_queueLock.Release(); Log.Success("BattlegroundMgr", "Group %u is now in battleground queue for arena type %u", pGroup->GetID(), BattlegroundType); /* send the battleground status packet */ return; } } /* Queue him! */ m_queueLock.Acquire(); m_queuedPlayers[BattlegroundType][lgroup].push_back(pguid); Log.Success("BattlegroundMgr", "Player %u is now in battleground queue for {Arena %u}", m_session->GetPlayer()->GetLowGUID(), BattlegroundType ); /* send the battleground status packet */ SendBattlefieldStatus(m_session->GetPlayer(), 1, BattlegroundType, 0 , 0, 0,0); m_session->GetPlayer()->m_bgIsQueued = true; m_session->GetPlayer()->m_bgQueueInstanceId = 0; m_session->GetPlayer()->m_bgQueueType = BattlegroundType; /* Set battleground entry point */ m_session->GetPlayer()->m_bgEntryPointX = m_session->GetPlayer()->GetPositionX(); m_session->GetPlayer()->m_bgEntryPointY = m_session->GetPlayer()->GetPositionY(); m_session->GetPlayer()->m_bgEntryPointZ = m_session->GetPlayer()->GetPositionZ(); m_session->GetPlayer()->m_bgEntryPointMap = m_session->GetPlayer()->GetMapId(); m_session->GetPlayer()->m_bgEntryPointInstance = m_session->GetPlayer()->GetInstanceID(); m_queueLock.Release(); }
void CBattlegroundManager::EventQueueUpdate() { deque<Player*> tempPlayerVec[2]; uint32 i,j,k; Player * plr; CBattleground * bg; list<uint32>::iterator it3, it4; //vector<Player*>::iterator it6; map<uint32, CBattleground*>::iterator iitr; Arena * arena; int32 team; m_queueLock.Acquire(); m_instanceLock.Acquire(); for(i = 0; i < BATTLEGROUND_NUM_TYPES; ++i) { for(j = 0; j < MAX_LEVEL_GROUP; ++j) { if(!m_queuedPlayers[i][j].size()) continue; tempPlayerVec[0].clear(); tempPlayerVec[1].clear(); for(it3 = m_queuedPlayers[i][j].begin(); it3 != m_queuedPlayers[i][j].end();) { it4 = it3++; plr = objmgr.GetPlayer(*it4); if(!plr || GetLevelGrouping(plr->getLevel()) != j) { m_queuedPlayers[i][j].erase(it4); continue; } // queued to a specific instance id? if(plr->m_bgQueueInstanceId != 0) { iitr = m_instances[i].find(plr->m_bgQueueInstanceId); if(iitr == m_instances[i].end()) { // queue no longer valid plr->GetSession()->SystemMessage("Your queue on battleground instance id %u is no longer valid. Reason: Instance Deleted.", plr->m_bgQueueInstanceId); plr->m_bgIsQueued = false; plr->m_bgQueueType = 0; plr->m_bgQueueInstanceId = 0; m_queuedPlayers[i][j].erase(it4); } // can we join? bg = iitr->second; if(bg->CanPlayerJoin(plr)) { bg->AddPlayer(plr, plr->GetTeam()); m_queuedPlayers[i][j].erase(it4); } } else { if(IS_ARENA(i)) tempPlayerVec[0].push_back(plr); else tempPlayerVec[plr->GetTeam()].push_back(plr); } } // try to join existing instances for(iitr = m_instances[i].begin(); iitr != m_instances[i].end(); ++iitr) { if( iitr->second->HasEnded() || iitr->second->GetLevelGroup() != j) continue; if(IS_ARENA(i)) { arena = ((Arena*)iitr->second); if(arena->Rated()) continue; team = arena->GetFreeTeam(); while(team >= 0 && tempPlayerVec[0].size()) { plr = *tempPlayerVec[0].begin(); tempPlayerVec[0].pop_front(); plr->m_bgTeam=team; arena->AddPlayer(plr, team); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); team = arena->GetFreeTeam(); } } else { bg = iitr->second; for(k = 0; k < 2; ++k) { while(tempPlayerVec[k].size() && bg->HasFreeSlots(k)) { plr = *tempPlayerVec[k].begin(); tempPlayerVec[k].pop_front(); bg->AddPlayer(plr, plr->GetTeam()); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } } if(IS_ARENA(i)) { // enough players to start a round? if(tempPlayerVec[0].size() < BGMinimumPlayers[i]) continue; if(CanCreateInstance(i,j)) { arena = ((Arena*)CreateInstance(i, j)); team = arena->GetFreeTeam(); while(!arena->IsFull() && tempPlayerVec[0].size() && team >= 0) { plr = *tempPlayerVec[0].begin(); tempPlayerVec[0].pop_front(); plr->m_bgTeam=team; arena->AddPlayer(plr, team); team = arena->GetFreeTeam(); // remove from the main queue (painful!) ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } else { #ifdef ONLY_ONE_PERSON_REQUIRED_TO_JOIN_DEBUG if(tempPlayerVec[0].size() >= 1 || tempPlayerVec[1].size() >= 1) #else if(tempPlayerVec[0].size() >= BGMinimumPlayers[i] && tempPlayerVec[1].size() >= BGMinimumPlayers[i]) #endif { if(CanCreateInstance(i,j)) { bg = CreateInstance(i,j); if( bg == NULL ) { // creation failed for(k = 0; k < 2; ++k) { while(tempPlayerVec[k].size()) { plr = *tempPlayerVec[k].begin(); tempPlayerVec[k].pop_front(); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } else { // push as many as possible in for(k = 0; k < 2; ++k) { while(tempPlayerVec[k].size() && bg->HasFreeSlots(k)) { plr = *tempPlayerVec[k].begin(); tempPlayerVec[k].pop_front(); plr->m_bgTeam=k; bg->AddPlayer(plr, k); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } } } } } } /* Handle paired arena team joining */ list<uint32>::iterator itz; list<uint32>::iterator itp; for(i = BATTLEGROUND_ARENA_2V2; i < BATTLEGROUND_ARENA_5V5+1; ++i) { // We need at least this many :( if(m_queuedGroups[i].size() < 2) continue; list<uint32> removegroups; for(itz = m_queuedGroups[i].begin(); itz != m_queuedGroups[i].end(); itz++) { Group * pGroup = objmgr.GetGroupById(*itz); if(!pGroup || !pGroup->m_isqueued || !pGroup->GetLeader() || pGroup->GetLeader()->arenaTeam[i - 4] == NULL) continue; uint32 maxRange = pGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange; pGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange += 100; vector<uint32> inRangeGroups; uint32 rating = pGroup->GetLeader()->arenaTeam[i - 4]->m_stat_rating; for(itp = m_queuedGroups[i].begin(); itp != m_queuedGroups[i].end();) { Group * tGrp = objmgr.GetGroupById(*itp); if(!tGrp || !tGrp->m_isqueued || !tGrp->GetLeader() || tGrp->GetLeader()->arenaTeam[i - 4] == NULL) { itp = m_queuedGroups[i].erase(itp); continue; } ++itp; if( pGroup == tGrp ) continue; uint32 tRating = tGrp->GetLeader()->arenaTeam[i - 4]->m_stat_rating; int32 diff = (int32)tRating - (int32)rating; if(diff < 0) diff = -diff; if(diff > (int32)maxRange) continue; //Log.Notice("Debug", "EventQueueUpdate added 1 in range arena"); inRangeGroups.push_back(tGrp->GetID()); } // K, we have a giant list of groups that we could group with, hopefully! // or not, we can't go on :( if(!inRangeGroups.size()) continue; // But if we're here, we can :D uint32 r = 0; if( inRangeGroups.size() > 1 ) r = RandomUInt((uint32)inRangeGroups.size() - 1); Group * pairGroup = objmgr.GetGroupById(inRangeGroups[r]); if(!pairGroup) continue; // Now, let's create this rated Arena Match :) //Log.Notice("Debug", "EventQueueUpdate creating arena"); Arena * arena = (Arena*)CreateInstance(i, LEVEL_GROUP_70); ArenaTeam *pTeamPair[2]; if(arena) { //Log.Notice("Debug", "EventQueueUpdate arena created"); removegroups.push_back(pGroup->GetID()); removegroups.push_back(pairGroup->GetID()); pGroup->m_isqueued = false; pairGroup->m_isqueued = false; arena->rated_match = true; if( pGroup->GetLeader()->arenaTeam[i - 4] != NULL ) { arena->m_ratedTeams[0] = pGroup->GetLeader()->arenaTeam[i - 4]->m_id; pTeamPair[0] = pGroup->GetLeader()->arenaTeam[i - 4]; } else pTeamPair[0] = NULL; if( pairGroup->GetLeader()->arenaTeam[i - 4] != NULL ) { arena->m_ratedTeams[1] = pairGroup->GetLeader()->arenaTeam[i - 4]->m_id; pTeamPair[1] = pairGroup->GetLeader()->arenaTeam[i - 4]; } else pTeamPair[1] = NULL; pGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange = 100; pairGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange = 100; GroupMembersSet::iterator gitr; pGroup->Lock(); for(gitr = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); gitr != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); gitr++) { PlayerInfo * pi = (*gitr); if(!pi->m_loggedInPlayer) continue; //Log.Notice("Debug", "EventQueueUpdate player lewp"); pi->m_loggedInPlayer->m_bgTeam = 0; if(arena->HasFreeSlots(0)) { arena->AddPlayer(pi->m_loggedInPlayer, 0); arena->m_RatedPlayers[0].insert(pi); if( pTeamPair[0] != NULL ) { ArenaTeamMember * atm = pTeamPair[0]->GetMember(pi); if(atm) { atm->Played_ThisSeason++; atm->Played_ThisWeek++; } //Log.Notice("Debug", "EventQueueUpdate added player %s", pi->m_loggedInPlayer->GetName()); } } } pGroup->Unlock(); pairGroup->Lock(); for(gitr = pairGroup->GetSubGroup(0)->GetGroupMembersBegin(); gitr != pairGroup->GetSubGroup(0)->GetGroupMembersEnd(); gitr++) { PlayerInfo * pi = (*gitr); if(!pi->m_loggedInPlayer || pi->arenaTeam[i-4] == NULL) continue; pi->m_loggedInPlayer->m_bgTeam = 1; if(arena->HasFreeSlots(1)) { arena->AddPlayer(pi->m_loggedInPlayer, 1); arena->m_RatedPlayers[1].insert(pi); if( pTeamPair[1] != NULL ) { ArenaTeamMember * atm = pTeamPair[1]->GetMember(pi); if(atm) { atm->Played_ThisSeason++; atm->Played_ThisWeek++; } } } } pairGroup->Unlock(); } } for(itz = removegroups.begin(); itz != removegroups.end(); itz++) { m_queuedGroups[i].remove(*itz); } } m_queueLock.Release(); m_instanceLock.Release(); }
bool WorldCreator::CheckInstanceForObject(Object *obj, MapInfo *pMapinfo) { WorldPacket data(4); Player *_player = NULL; if(obj->GetTypeId() == TYPEID_PLAYER) { _player = static_cast<Player*>(obj); } if(pMapinfo && _player) { switch(pMapinfo->type) { case INSTANCE_NONRAID: case INSTANCE_RAID: case INSTANCE_MULTIMODE: { //instance creation detection types //case 1, player is inside a group aka not soloing //onoes: leader can be inside a instance already and make a group or its a fresh group, noone inside if(_player->InGroup()) //group created, join leader instance. { Group *pGroup = _player->GetGroup(); if(pGroup) { //check if instance already exists(player solo created instance and made group after) MapMgr *pInstance = sWorldCreator.GetInstanceByGroup(pGroup, _player, pMapinfo); if(pInstance) { //INSTANCE_OK if(pInstance->IsCombatInProgress()) { WorldPacket msg; msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE); msg << uint32(0) << "Encounter in progress." << uint8(0) << uint8(0); _player->GetSession()->SendPacket(&msg); return false; } if(pInstance->GetPlayerCount() >= pMapinfo->playerlimit) { data.Initialize(SMSG_TRANSFER_ABORTED); data << uint32(INSTANCE_ABORT_FULL); _player->GetSession()->SendPacket(&data); return false; } _player->SetInstanceID(pInstance->GetInstanceID()); } else { //group leader didnt made any instance yet, create instance for this group. uint32 id = sWorldCreator.CreateInstance(pGroup, pGroup->GetLeader(), pMapinfo->mapid); // again, NULL might not be 0 //if(id != NULL) if(id != 0) { //INSTANCE CREATED _player->SetInstanceID(id); } else { data.Initialize(SMSG_TRANSFER_ABORTED); data << uint32(INSTANCE_ABORT_ERROR); _player->GetSession()->SendPacket(&data); return false; } } } else { data.Initialize(SMSG_TRANSFER_ABORTED); data << uint32(INSTANCE_ABORT_ERROR); _player->GetSession()->SendPacket(&data); return false; } } else { MapMgr *pInstance = sWorldCreator.GetInstanceByCreator(_player, pMapinfo); if(pInstance) { //INSTANCE_OK if(pInstance->IsCombatInProgress()) { WorldPacket msg; msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE); msg << uint32(0) << "Encounter in progress." << uint8(0) << uint8(0); _player->GetSession()->SendPacket(&msg); return false; } if(pInstance->GetPlayerCount() >= pMapinfo->playerlimit) { data.Initialize(SMSG_TRANSFER_ABORTED); data << uint32(INSTANCE_ABORT_FULL); _player->GetSession()->SendPacket(&data); return false; } _player->SetInstanceID(pInstance->GetInstanceID()); } else { uint32 id2 = sWorldCreator.CreateInstance(NULL, _player, pMapinfo->mapid); //if(id2 != NULL) if(id2 != 0) { _player->SetInstanceID(id2); } else { data.Initialize(SMSG_TRANSFER_ABORTED); data << uint32(INSTANCE_ABORT_ERROR); _player->GetSession()->SendPacket(&data); return false; } } } }break; } } return true; }
void CBattlegroundManager::HandleArenaJoin(WorldSession* m_session, uint32 BattlegroundType, uint8 as_group, uint8 rated_match) { uint32 pguid = m_session->GetPlayer()->GetLowGUID(); uint32 lgroup = GetLevelGrouping(m_session->GetPlayer()->getLevel()); if (as_group && m_session->GetPlayer()->GetGroup() == NULL) return; Group* pGroup = m_session->GetPlayer()->GetGroup(); if (as_group) { if (pGroup->GetSubGroupCount() != 1) { m_session->SystemMessage(m_session->LocalizedWorldSrv(55)); return; } if (pGroup->GetLeader() != m_session->GetPlayer()->getPlayerInfo()) { m_session->SystemMessage(m_session->LocalizedWorldSrv(56)); return; } GroupMembersSet::iterator itx; if (!rated_match) { /* add all players normally.. bleh ;P */ pGroup->Lock(); for (itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if ((*itx)->m_loggedInPlayer && !(*itx)->m_loggedInPlayer->m_bgIsQueued && !(*itx)->m_loggedInPlayer->m_bg) HandleArenaJoin((*itx)->m_loggedInPlayer->GetSession(), BattlegroundType, 0, 0); } pGroup->Unlock(); return; } else { /* make sure all players are 70 */ uint32 maxplayers; uint32 type = BattlegroundType - BATTLEGROUND_ARENA_2V2; switch (BattlegroundType) { case BATTLEGROUND_ARENA_3V3: maxplayers = 3; break; case BATTLEGROUND_ARENA_5V5: maxplayers = 5; break; case BATTLEGROUND_ARENA_2V2: default: maxplayers = 2; break; } if (pGroup->GetLeader()->m_loggedInPlayer && pGroup->GetLeader()->m_loggedInPlayer->m_arenaTeams[type] == NULL) { m_session->SendNotInArenaTeamPacket(uint8(maxplayers)); return; } pGroup->Lock(); for (itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if (maxplayers == 0) { m_session->SystemMessage(m_session->LocalizedWorldSrv(58)); pGroup->Unlock(); return; } if ((*itx)->lastLevel < PLAYER_ARENA_MIN_LEVEL) { m_session->SystemMessage(m_session->LocalizedWorldSrv(59)); pGroup->Unlock(); return; } if ((*itx)->m_loggedInPlayer) { if ((*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bgIsQueued) { m_session->SystemMessage(m_session->LocalizedWorldSrv(60)); pGroup->Unlock(); return; }; if ((*itx)->m_loggedInPlayer->m_arenaTeams[type] != pGroup->GetLeader()->m_loggedInPlayer->m_arenaTeams[type]) { m_session->SystemMessage(m_session->LocalizedWorldSrv(61)); pGroup->Unlock(); return; } --maxplayers; } } WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(6); // all arenas for (itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if ((*itx)->m_loggedInPlayer) { SendBattlefieldStatus((*itx)->m_loggedInPlayer, BGSTATUS_INQUEUE, BattlegroundType, 0, 0, 0, 1); (*itx)->m_loggedInPlayer->m_bgIsQueued = true; (*itx)->m_loggedInPlayer->m_bgQueueInstanceId = 0; (*itx)->m_loggedInPlayer->m_bgQueueType = BattlegroundType; (*itx)->m_loggedInPlayer->GetSession()->SendPacket(&data); (*itx)->m_loggedInPlayer->m_bgEntryPointX = (*itx)->m_loggedInPlayer->GetPositionX(); (*itx)->m_loggedInPlayer->m_bgEntryPointY = (*itx)->m_loggedInPlayer->GetPositionY(); (*itx)->m_loggedInPlayer->m_bgEntryPointZ = (*itx)->m_loggedInPlayer->GetPositionZ(); (*itx)->m_loggedInPlayer->m_bgEntryPointMap = (*itx)->m_loggedInPlayer->GetMapId(); } } pGroup->Unlock(); m_queueLock.Acquire(); m_queuedGroups[BattlegroundType].push_back(pGroup->GetID()); m_queueLock.Release(); Log.Notice("BattlegroundMgr", "Group %u is now in battleground queue for arena type %u", pGroup->GetID(), BattlegroundType); /* send the battleground status packet */ return; } } /* Queue him! */ m_queueLock.Acquire(); m_queuedPlayers[BattlegroundType][lgroup].push_back(pguid); Log.Notice("BattlegroundMgr", "Player %u is now in battleground queue for {Arena %u}", m_session->GetPlayer()->GetLowGUID(), BattlegroundType); /* send the battleground status packet */ SendBattlefieldStatus(m_session->GetPlayer(), BGSTATUS_INQUEUE, BattlegroundType, 0, 0, 0, 0); m_session->GetPlayer()->m_bgIsQueued = true; m_session->GetPlayer()->m_bgQueueInstanceId = 0; m_session->GetPlayer()->m_bgQueueType = BattlegroundType; /* Set battleground entry point */ m_session->GetPlayer()->m_bgEntryPointX = m_session->GetPlayer()->GetPositionX(); m_session->GetPlayer()->m_bgEntryPointY = m_session->GetPlayer()->GetPositionY(); m_session->GetPlayer()->m_bgEntryPointZ = m_session->GetPlayer()->GetPositionZ(); m_session->GetPlayer()->m_bgEntryPointMap = m_session->GetPlayer()->GetMapId(); m_session->GetPlayer()->m_bgEntryPointInstance = m_session->GetPlayer()->GetInstanceID(); m_queueLock.Release(); }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player * plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup; InstanceMap * instancemap; Instance * in; if (inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if (inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if (inf->type == INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; pGroup = plr->GetGroup(); // players without groups cannot enter raids and heroic instances if (pGroup == NULL && (inf->type == INSTANCE_RAID || (inf->type == INSTANCE_MULTIMODE && plr->iInstanceType >= MODE_HEROIC)) && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // players without raid groups cannot enter raid instances if (pGroup != NULL && pGroup->GetGroupType() != GROUP_TYPE_RAID && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if (plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; if (instancemap == NULL) { if (instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; if (instanceid != 0) { itr = instancemap->find(instanceid); if (itr != instancemap->end()) { in = itr->second; if (!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... m_mapLock.Release(); sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if (pGroup) in->m_creatorGroup = pGroup->GetID(); m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else { in = NULL; if (pGroup != NULL) { if ((inf->type == INSTANCE_MULTIMODE && pGroup->m_difficulty >= MODE_HEROIC) || inf->type == INSTANCE_RAID) { if (plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty) == 0) { if (pGroup->m_instanceIds[mapid][pGroup->m_difficulty] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][pGroup->m_difficulty]); } else if (sWorld.instance_TakeGroupLeaderID) { PlayerInfo *pLeaderInfo = pGroup->GetLeader(); if (pLeaderInfo) { pLeaderInfo->savedInstanceIdsLock.Acquire(); PlayerInstanceMap::iterator itrLeader = pLeaderInfo->savedInstanceIds[pGroup->m_difficulty].find(mapid); if (itrLeader != pLeaderInfo->savedInstanceIds[pGroup->m_difficulty].end()) { in = sInstanceMgr.GetInstanceByIds(mapid, (*itrLeader).second); } pLeaderInfo->savedInstanceIdsLock.Release(); } } } if (in == NULL && plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty) != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty)); } } else { if (pGroup->m_instanceIds[mapid][pGroup->m_difficulty] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][pGroup->m_difficulty]); } } } if (in == NULL) { // search the instance and see if we have one here. for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (in->m_difficulty == plr->iInstanceType && PlayerOwnsInstance(in, plr)) break; in = NULL; } } if (in != NULL) { m_mapLock.Release(); // check the player count and in combat status. if (in->m_mapMgr) { if (in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if (in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } if (!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if (pGroup) in->m_creatorGroup = pGroup->GetID(); plr->SetInstanceID(in->m_instanceId); // found our instance, allow him in. return INSTANCE_OK; } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_difficulty = pGroup ? pGroup->m_difficulty : plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapInfo = inf; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_isBattleground = false; in->m_persistent = IS_PERSISTENT_INSTANCE(in) && objmgr.m_InstanceBossInfoMap[mapid] == NULL; in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; if (sWorld.instance_SlidingExpiration) { if (inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) in->m_expiration = UNIXTIME + TIME_DAY; else in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } else { if (inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) { in->m_expiration = UNIXTIME - (UNIXTIME % TIME_DAY) + ((UNIXTIME % TIME_DAY) > (sWorld.instance_DailyHeroicInstanceResetHour * TIME_HOUR) ? 82800 : -3600) + ((sWorld.instance_DailyHeroicInstanceResetHour - sWorld.GMTTimeZone) * TIME_HOUR); } else if (IS_PERSISTENT_INSTANCE(in)) { if (m_nextInstanceReset[in->m_mapId] == 0) { m_nextInstanceReset[in->m_mapId] = UNIXTIME - (UNIXTIME % TIME_DAY) - ((sWorld.GMTTimeZone + 1) * TIME_HOUR) + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); CharacterDatabase.Execute("REPLACE INTO `server_settings` (`setting_id`, `setting_value`) VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } if (m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME) { do { time_t tmp = m_nextInstanceReset[in->m_mapId]; if (tmp + (TIME_MINUTE * 15) < UNIXTIME) m_nextInstanceReset[in->m_mapId] = tmp + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); } while (m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME); CharacterDatabase.Execute("REPLACE INTO `server_settings` (`setting_id`, `setting_value`) VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } in->m_expiration = m_nextInstanceReset[in->m_mapId]; } else { in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } } plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert(InstanceMap::value_type(in->m_instanceId, in)); // Try to add instance ID to player plr->SetPersistentInstanceId(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }