예제 #1
0
////////////////////////////////////////////////////////////////
///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.
}
예제 #2
0
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;
}
예제 #3
0
////////////////////////////////////////////////////////////////
///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.
}
예제 #4
0
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;
}
예제 #5
0
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;
}