void InstanceMgr::BuildSavedInstancesForPlayer(Player * plr) { WorldPacket data(4); Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; if (!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) { m_mapLock.Acquire(); for (i = 0; i < NUM_MAPS; ++i) { if (m_instances[i] != NULL) { instancemap = m_instances[i]; for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (PlayerOwnsInstance(in, plr) && !IS_PERSISTENT_INSTANCE(in)) { m_mapLock.Release(); data.SetOpcode(SMSG_UPDATE_LAST_INSTANCE); data << uint32(in->m_mapId); plr->GetSession()->SendPacket(&data); data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP); data << uint32(0x01); plr->GetSession()->SendPacket(&data); return; } } } } m_mapLock.Release(); } data.SetOpcode(SMSG_UPDATE_INSTANCE_OWNERSHIP); data << uint32(0x00); plr->GetSession()->SendPacket(&data); }
bool ChatHandler::HandleResetInstanceCommand(const char* args, WorldSession* m_session) { uint32 instanceId; int argc = 1; char* playername = NULL; char* guidString = (char*)args; // Parse arguments char* space = (char*)strchr(args, ' '); if (space) { *space = '\0'; playername = space + 1; argc = 2; } instanceId = atoi(guidString); if (!instanceId) { RedSystemMessage(m_session, "You must specify an instance id."); return true; } Player* plr; if (argc == 1) plr = getSelectedChar(m_session, true); else plr = objmgr.GetPlayer((const char*)playername, false);; if (!plr) { RedSystemMessage(m_session, "Player not found"); return true; } Instance* instance = sInstanceMgr.GetInstanceByIds(NUM_MAPS, instanceId); if (instance == NULL) { RedSystemMessage(m_session, "There's no instance with id %u.", instanceId); return true; } if (IS_PERSISTENT_INSTANCE(instance)) { if (m_session->CanUseCommand('z')) { bool foundSomething = false; plr->getPlayerInfo()->savedInstanceIdsLock.Acquire(); for (uint32 difficulty = 0; difficulty < NUM_INSTANCE_MODES; difficulty++) { PlayerInstanceMap::iterator itr = plr->getPlayerInfo()->savedInstanceIds[difficulty].find(instance->m_mapId); if (itr == plr->getPlayerInfo()->savedInstanceIds[difficulty].end() || (*itr).second != instance->m_instanceId) continue; plr->SetPersistentInstanceId(instance->m_mapId, difficulty, 0); SystemMessage(m_session, "Instance with id %u (%s) is persistent and will only be revoked from player.", instanceId, GetDifficultyString(static_cast<uint8>(difficulty))); foundSomething = true; } plr->getPlayerInfo()->savedInstanceIdsLock.Release(); if (!foundSomething) RedSystemMessage(m_session, "Player is not assigned to persistent instance with id %u.", instanceId); return true; } else { RedSystemMessage(m_session, "Instance with id %u is persistent and can only be removed from player by admins.", instanceId); return true; } } if (instance->m_mapMgr && instance->m_mapMgr->HasPlayers()) { RedSystemMessage(m_session, "Failed to reset non-persistent instance with id %u, due to player still inside.", instanceId); return true; } if (instance->m_creatorGroup) { Group* group = plr->GetGroup(); if (group == NULL || instance->m_creatorGroup != group->GetID()) { RedSystemMessage(m_session, "Player %s is not a member of the group assigned to the non-persistent instance with id %u.", plr->GetName(), instanceId); return true; } } else if (instance->m_creatorGuid == 0 || instance->m_creatorGuid != plr->GetLowGUID()) { RedSystemMessage(m_session, "Player %s is not assigned to instance with id %u.", plr->GetName(), instanceId); return true; } // tell player the instance was reset WorldPacket data(SMSG_INSTANCE_RESET, 4); data << instance->m_mapId; plr->GetSession()->SendPacket(&data); // shut down instance sInstanceMgr.DeleteBattlegroundInstance(instance->m_mapId, instance->m_instanceId); // RedSystemMessage(m_session, "Resetting single non-persistent instances is not available yet."); sGMLog.writefromsession(m_session, "used reset instance command on %s, instance %u,", plr->GetName(), instanceId); return true; }
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 MapCell::LoadObjects(CellSpawns * sp) { //we still have mobs loaded on cell. There is no point of loading them again if (_loaded == true) return; _loaded = true; Instance * pInstance = _mapmgr->pInstance; InstanceBossInfoMap *bossInfoMap = objmgr.m_InstanceBossInfoMap[_mapmgr->GetMapId()]; if (sp->CreatureSpawns.size())//got creatures { for (CreatureSpawnList::iterator i = sp->CreatureSpawns.begin(); i != sp->CreatureSpawns.end(); i++) { uint32 respawnTimeOverride = 0; if (pInstance) { if (bossInfoMap != NULL && IS_PERSISTENT_INSTANCE(pInstance)) { bool skip = false; for (std::set<uint32>::iterator killedNpc = pInstance->m_killedNpcs.begin(); killedNpc != pInstance->m_killedNpcs.end(); ++killedNpc) { // Do not spawn the killed boss. if ((*killedNpc) == (*i)->entry) { skip = true; break; } // Do not spawn the killed boss' trash. InstanceBossInfoMap::const_iterator bossInfo = bossInfoMap->find((*killedNpc)); if (bossInfo != bossInfoMap->end() && bossInfo->second->trash.find((*i)->id) != bossInfo->second->trash.end()) { skip = true; break; } } if (skip) continue; for (InstanceBossInfoMap::iterator bossInfo = bossInfoMap->begin(); bossInfo != bossInfoMap->end(); ++bossInfo) { if (pInstance->m_killedNpcs.find(bossInfo->second->creatureid) == pInstance->m_killedNpcs.end() && bossInfo->second->trash.find((*i)->id) != bossInfo->second->trash.end()) { respawnTimeOverride = bossInfo->second->trashRespawnOverride; } } } else { // No boss information available ... fallback ... if (pInstance->m_killedNpcs.find((*i)->id) != pInstance->m_killedNpcs.end()) continue; } } Creature * c = _mapmgr->CreateCreature((*i)->entry); c->SetMapId(_mapmgr->GetMapId()); c->SetInstanceID(_mapmgr->GetInstanceID()); c->m_loadedFromDB = true; if (respawnTimeOverride > 0) c->m_respawnTimeOverride = respawnTimeOverride; if (c->Load(*i, _mapmgr->iInstanceMode, _mapmgr->GetMapInfo()) && c->CanAddToWorld()) { c->PushToWorld(_mapmgr); } else delete c;//missing proto or smth of that kind } } if (sp->GOSpawns.size())//got GOs { for (GOSpawnList::iterator i = sp->GOSpawns.begin(); i != sp->GOSpawns.end(); i++) { GameObject * go = _mapmgr->CreateGameObject((*i)->entry); go->SetInstanceID(_mapmgr->GetInstanceID()); if (go->Load(*i)) { //uint32 state = go->GetUInt32Value(GAMEOBJECT_STATE); // FIXME - burlex /* if(pInstance && pInstance->FindObject((*i)->stateNpcLink)) { go->SetUInt32Value(GAMEOBJECT_STATE, (state ? 0 : 1)); }*/ go->m_loadedFromDB = true; go->PushToWorld(_mapmgr); } else delete go;//missing proto or smth of that kind } } }
bool ChatHandler::HandleResetInstanceCommand(const char* args, WorldSession *m_session) { uint32 instanceId = (args ? atoi(args) : 0); if(instanceId == 0) return false; Player * plr = getSelectedChar(m_session, true); if(!plr) return true; Instance *instance = sInstanceMgr.GetInstanceByIds(NUM_MAPS, instanceId); if(instance == NULL) { RedSystemMessage(m_session, "There's no instance with id %u.", instanceId); return true; } if(IS_PERSISTENT_INSTANCE(instance)) { if(m_session->CanUseCommand('z')) { bool foundSomething = false; plr->m_playerInfo->savedInstanceIdsLock.Acquire(); for(int difficulty=0; difficulty<NUM_INSTANCE_MODES; difficulty++) { PlayerInstanceMap::iterator itr = plr->m_playerInfo->savedInstanceIds[difficulty].find(instance->m_mapId); if(itr == plr->m_playerInfo->savedInstanceIds[difficulty].end() || (*itr).second != instance->m_instanceId) continue; plr->SetPersistentInstanceId(instance->m_mapId, difficulty, 0); SystemMessage(m_session, "Instance with id %u (%s) is persistent and will only be revoked from player.", instanceId, GetDifficultyString(difficulty)); foundSomething = true; } plr->m_playerInfo->savedInstanceIdsLock.Release(); if(!foundSomething) RedSystemMessage(m_session, "Player is not assigned to persistent instance with id %u.", instanceId); return true; } else { RedSystemMessage(m_session, "Instance with id %u is persistent and can only be removed from player by admins.", instanceId); return true; } } if(instance->m_mapMgr && instance->m_mapMgr->HasPlayers()) { RedSystemMessage(m_session, "Failed to reset non-persistent instance with id %u, due to player still inside.", instanceId); return true; } if(instance->m_creatorGroup) { Group *group = plr->GetGroup(); if(group == NULL || instance->m_creatorGroup != group->GetID()) { RedSystemMessage(m_session, "Player %s is not a member of the group assigned to the non-persistent instance with id %u.", plr->GetName(), instanceId); return true; } } else if(instance->m_creatorGuid == 0 || instance->m_creatorGuid != plr->GetLowGUID()) { RedSystemMessage(m_session, "Player %s is not assigned to instance with id %u.", plr->GetName(), instanceId); return true; } //TODO: Reset that instance...^^ RedSystemMessage(m_session, "Resetting single non-persistent instances is not available yet."); sGMLog.writefromsession(m_session, "used reset instance command on %s, instance %u,", plr->GetName(), instanceId); return true; }
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; }