//////////////////////////////////////////////////////////////// ///This function handles CMSG_GROUP_ACCEPT: //////////////////////////////////////////////////////////////// void WorldSession::HandleGroupAcceptOpcode(WorldPacket & recv_data) { CHECK_INWORLD_RETURN; // we are in group already if(_player->GetGroup() != NULL) return; Player* player = objmgr.GetPlayer(_player->GetInviter()); if(!player) return; player->SetInviter(0); _player->SetInviter(0); Group* grp = player->GetGroup(); if(grp != NULL) { grp->AddMember(_player->m_playerInfo); _player->iInstanceType = grp->m_difficulty; _player->SendDungeonDifficulty(); //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); return; } // If we're this far, it means we have no existing group, and have to make one. grp = new Group(true); grp->m_difficulty = static_cast<uint8>(player->iInstanceType); grp->AddMember(player->m_playerInfo); // add the inviter first, therefore he is the leader grp->AddMember(_player->m_playerInfo); // add us. _player->iInstanceType = grp->m_difficulty; _player->SendDungeonDifficulty(); Instance* instance = sInstanceMgr.GetInstanceByIds(player->GetMapId(), player->GetInstanceID()); if(instance != NULL && instance->m_creatorGuid == player->GetLowGUID()) { grp->m_instanceIds[instance->m_mapId][instance->m_difficulty] = instance->m_instanceId; instance->m_creatorGroup = grp->GetID(); instance->m_creatorGuid = 0; instance->SaveToDB(); } //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); // Currentgroup and all that shit are set by addmember. }
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; }
//////////////////////////////////////////////////////////////// ///This function handles CMSG_GROUP_ACCEPT and deny: //////////////////////////////////////////////////////////////// void WorldSession::HandleGroupAcceptOpcode( WorldPacket & recv_data ) { if(!_player->IsInWorld()) { return; } uint8 packet_type; recv_data >> packet_type; if( packet_type == 0 ) //0x80 for group accept and 0 is for decline { HandleGroupDeclineOpcode( recv_data ); return; } Player *player = objmgr.GetPlayer(_player->GetInviter()); if ( !player ) { return; } //check if this invite is still valid if( player->GetInviter() != _player->GetLowGUID() || _player->GetInviter() != player->GetLowGUID() ) { _player->BroadcastMessage( "Group invite from player %s expired", player->GetName() ); player->BroadcastMessage( "Group invite from player %s expired", _player->GetName() ); return; } player->SetInviter(0); _player->SetInviter(0); Group *grp = player->GetGroup(); if(grp) { grp->AddMember(_player->m_playerInfo); _player->dungeon_difficulty = grp->dungeon_difficulty; _player->raid_difficulty = grp->raid_difficulty; _player->SendDungeonDifficulty(); _player->SendRaidDifficulty(); //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); return; } // If we're this far, it means we have no existing group, and have to make one. grp = new Group(true); grp->dungeon_difficulty = player->dungeon_difficulty; grp->raid_difficulty = player->raid_difficulty; grp->AddMember(player->m_playerInfo); // add the inviter first, therefore he is the leader grp->AddMember(_player->m_playerInfo); // add us. _player->dungeon_difficulty = grp->dungeon_difficulty; _player->raid_difficulty = grp->raid_difficulty; _player->SendDungeonDifficulty(); _player->SendRaidDifficulty(); Instance *instance = sInstanceMgr.GetInstanceByIds(player->GetMapId(), player->GetInstanceID()); if(instance != NULL && instance->m_creatorGuid == player->GetLowGUID()) { grp->AddSavedInstance(instance->m_mapId,instance->instance_difficulty,instance->m_instanceId); instance->m_creatorGroup = grp->GetID(); instance->m_creatorGuid = 0; instance->SaveToDB(); } //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); // Currentgroup and all that shit are set by addmember. }
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; // players without groups cannot enter raid instances (no soloing them:P) if(plr->GetGroup() == NULL && (inf->type == INSTANCE_RAID || inf->type == INSTANCE_MULTIMODE) && !plr->triggerpass_cheat) 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]; // set up our pointers (cleaner code is always good) pGroup = plr->GetGroup(); 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()) { m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else { // search the instance and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(PlayerOwnsInstance(in, plr)) { 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; } // 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_expiration =UNIXTIME + inf->cooldown; // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; in->m_difficulty = plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_mapInfo = inf; in->m_isBattleground=false; 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 ) ); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
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; }