示例#1
0
void WorldSession::_HandleAreaTriggerOpcode(uint32 id)
{		
	DEBUG_LOG( "WorldSession","HandleAreaTriggerOpcode: %u", id);

	// Are we REALLY here?
	CHECK_INWORLD_RETURN;

	// Search quest log, find any exploration quests
	sQuestMgr.OnPlayerExploreArea(GetPlayer(),id);

	AreaTrigger* pAreaTrigger = AreaTriggerStorage.LookupEntry( id );

	sHookInterface.OnAreaTrigger(_player, id);
	CALL_INSTANCE_SCRIPT_EVENT( _player->GetMapMgr(), OnAreaTrigger )( _player, id );

	// if in BG handle is triggers
	if( _player->m_bg )
	{
		_player->m_bg->HookOnAreaTrigger(_player, id);
		return;
	}

	// Hook for Scripted Areatriggers
	_player->GetMapMgr()->HookOnAreaTrigger(_player, id);

	if( _player->GetSession()->CanUseCommand('z') )
	{
		if( pAreaTrigger != NULL )
			sChatHandler.BlueSystemMessage( this, "[%sSystem%s] |rEntered areatrigger: %s%u (%s).", MSG_COLOR_WHITE, MSG_COLOR_LIGHTBLUE, MSG_COLOR_SUBWHITE, id, pAreaTrigger->Name );
		else
			sChatHandler.BlueSystemMessage( this, "[%sSystem%s] |rEntered areatrigger: %s%u", MSG_COLOR_WHITE, MSG_COLOR_LIGHTBLUE, MSG_COLOR_SUBWHITE, id);
	}

	if( pAreaTrigger == NULL )
	{
		OUT_DEBUG("Missing AreaTrigger: %u", id);
		return;
	}

	switch(pAreaTrigger->Type)
	{
	case ATTYPE_INSTANCE:
		{
			if(_player->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
			{
				MapInfo * pMi = WorldMapInfoStorage.LookupEntry(pAreaTrigger->Mapid);
				MapEntry* map = dbcMap.LookupEntry(pAreaTrigger->Mapid);
				if(!pMi)
					return;

				//do we meet the map requirements?
				uint8 reason = CheckTeleportPrerequsites(pAreaTrigger, this, _player, pAreaTrigger->Mapid);
				if(reason != AREA_TRIGGER_FAILURE_OK)
				{
					const char * pReason = AreaTriggerFailureMessages[reason];
					char msg[200];
					WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 50);
					data << uint32(0);

					switch (reason)
					{
					case AREA_TRIGGER_FAILURE_LEVEL:
						{
							snprintf(msg,200,pReason,pAreaTrigger->required_level);
							data << msg;
						}break;
					case AREA_TRIGGER_FAILURE_NO_ATTUNE_I:
						{
							ItemPrototype * pItem = ItemPrototypeStorage.LookupEntry(pMi->required_item);
							snprintf(msg, 200, pReason, pItem ? pItem->Name1 : "UNKNOWN");
							data << msg;
						}break;
					case AREA_TRIGGER_FAILURE_NO_ATTUNE_Q:
						{
							Quest * pQuest = QuestStorage.LookupEntry(pMi->required_quest);
							snprintf(msg, 200, pReason, pQuest ? pQuest->title : "UNKNOWN");

							data << msg;
						}break;
					case AREA_TRIGGER_FAILURE_NO_KEY:
						{
							string temp_msg[2];
							string tmp_msg;
							for(uint32 i = 0; i < 2; ++i) 
							{
								if (pMi->heroic_key[i] && _player->GetItemInterface()->GetItemCount(pMi->heroic_key[i], false)==0)
								{
									ItemPrototype * pKey = ItemPrototypeStorage.LookupEntry(pMi->heroic_key[i]);
									if(pKey)
										temp_msg[i] += pKey->Name1;
									else
										temp_msg[i] += "UNKNOWN";
								}
							}
							tmp_msg += temp_msg[0];
							if(temp_msg[0].size() && temp_msg[1].size())
								tmp_msg += "\" and \"";
							tmp_msg += temp_msg[1];

							snprintf(msg, 200, pReason, tmp_msg.c_str());
							data << msg;
						}break;
					case AREA_TRIGGER_FAILURE_LEVEL_HEROIC:
						{
							snprintf(msg, 200, pReason, pMi->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70);
							data << msg;
						}break;
					default:
						{
							data << pReason;
						}break;
					}

					data << uint8(0);
					SendPacket(&data);
					return;
				}

				if( _player->IsMounted())
					TO_UNIT(_player)->Dismount();

				uint32 InstanceID = 0;
				// Try to find a saved instance and
				// do not handle Hyjal Inn (trigger 4319), since we need a unique mapid when generating our instance_id.

				if( id != 4319 && pMi && ( map->israid() || _player->iRaidType >= MODE_NORMAL_25MEN && pMi->type == INSTANCE_MULTIMODE ) )
				{
					//Do we have a saved instance we should use?
					Instance * in = NULL;
					in = sInstanceMgr.GetSavedInstance( pMi->mapid,_player->GetLowGUID(), _player->iRaidType );
					if( in != NULL  && in->m_instanceId )
					{
						//If we are the first to enter this instance, also set our current group id.
						if( in->m_mapMgr == NULL || (!in->m_mapMgr->HasPlayers() && _player->GetGroupID() != in->m_creatorGroup))
							in->m_creatorGroup =_player->GetGroupID();
						InstanceID = in->m_instanceId;
					}
				}

				//Save our entry point and try to teleport to our instance
				_player->SaveEntryPoint(pAreaTrigger->Mapid);
				_player->SafeTeleport(pAreaTrigger->Mapid, InstanceID, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
			}
		}break;
	case ATTYPE_QUESTTRIGGER:
		{

		}break;
	case ATTYPE_INN:
		{
			if( _player->IsMounted())
				TO_UNIT(_player)->Dismount();

			// Inn
			if (!_player->m_isResting) 
				_player->ApplyPlayerRestState(true);
		}break;
	case ATTYPE_TELEPORT:
		{
			if( _player->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
			{
				if( _player->IsMounted() )
					TO_UNIT(_player)->Dismount();

				_player->SaveEntryPoint(pAreaTrigger->Mapid);
				_player->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
			}
		}break;
	default:break;
	}
}
示例#2
0
void WorldSession::_HandleAreaTriggerOpcode(uint32 id)
{		
	sLog.outDebug("AreaTrigger: %u", id);

	WorldPacket data(80);
	AreaTrigger * pAreaTrigger = AreaTriggerStorage.LookupEntry(id);

	// Search quest log, find any exploration quests
	sQuestMgr.OnPlayerExploreArea(GetPlayer(),id);
	
	// if in BG handle is triggers
	if(GetPlayer()->m_bgInBattleground && GetPlayer()->GetCurrentBattleground() != NULL)
	{
		GetPlayer()->GetCurrentBattleground()->HandleBattlegroundAreaTrigger(GetPlayer(), id);
		return;
	}   

	if(GetPermissionCount())
	{
		sChatHandler.BlueSystemMessage(this, "[%sSystem%s] |rEntered areatrigger: %s%u.", MSG_COLOR_WHITE, MSG_COLOR_LIGHTBLUE, 
			MSG_COLOR_SUBWHITE, id);
	}

	/* if we don't have an areatrigger, create one on the stack to use for gm scripts :p */
	if(!pAreaTrigger)
	{
		AreaTrigger tmpTrigger;
		tmpTrigger.AreaTriggerID = id;

		ScriptSystem->OnActivateAreaTrigger(&tmpTrigger, _player);
		return;
	}

	/* script prerequsites */
	if(ScriptSystem->OnActivateAreaTrigger(pAreaTrigger, _player) == false)
		return;

	if(pAreaTrigger->Type == ATTYPE_BATTLEGROUND)
	{
		if(pAreaTrigger->Mapid == 489)		// hack fix
			pAreaTrigger->Mapid = 2;
		else if(pAreaTrigger->Mapid == 529)
			pAreaTrigger->Mapid = 3;
		else if(pAreaTrigger->Mapid == 30)
			pAreaTrigger->Mapid = 1;
			
		WorldPacket *pkt = sBattlegroundMgr.BuildBattlegroundListPacket(GetPlayer()->GetGUID(), _player,
			pAreaTrigger->Mapid);
		SendPacket(pkt);
		delete pkt;
		return;
	}

	bool bFailedPre = false;
	std::string failed_reason;

	if(pAreaTrigger->required_level)
	{
		if(GetPlayer()->getLevel() < pAreaTrigger->required_level)
		{
			bFailedPre = true;
			if(failed_reason.size() > 0)
				failed_reason += ", and ";
			else
				failed_reason = "You must be ";

			// mm hacky
			char lvltext[30];
			snprintf(lvltext, 30, "at least level %d", (int)pAreaTrigger->required_level);
			failed_reason += lvltext;
		}
	}
	if(bFailedPre)
	{
		failed_reason += " before you're allowed through here.";
		WorldPacket msg;
		msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
		msg << uint32(0) << failed_reason << uint8(0);
		SendPacket(&msg);
		sLog.outDebug("Player %s failed areatrigger prereq - %s", GetPlayer()->GetName(), failed_reason.c_str());
		return;
	}
	switch(pAreaTrigger->Type)
	{
	case ATTYPE_INSTANCE:
		{
			if(GetPlayer()->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
			{
				GetPlayer()->SaveEntryPoint(pAreaTrigger->Mapid);

				//death system check.
				Corpse *pCorpse = NULL;
//					CorpseData *pCorpseData = NULL;
				MapInfo *pMapinfo = NULL;

				pMapinfo = WorldMapInfoStorage.LookupEntry(pAreaTrigger->Mapid);
				if(pMapinfo && !pMapinfo->HasFlag(WMI_INSTANCE_ENABLED))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "This instance is currently unavailable." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->HasFlag(WMI_INSTANCE_XPACK_01) && !HasFlag(ACCOUNT_FLAG_XPACK_01))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_BROADCAST_MSG);
					msg << uint32(3) << "You must have The Burning Crusade Expansion to access this content." << uint8(0);
					SendPacket(&msg);
					return;
				}

                if(pMapinfo && pMapinfo->type != INSTANCE_MULTIMODE && GetPlayer()->iInstanceType == MODE_HEROIC && pMapinfo->type != INSTANCE_NULL)
                {
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "Heroic mode is not available for this instance." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->type == INSTANCE_RAID && GetPlayer()->InGroup() && GetPlayer()->GetGroup()->GetGroupType() != GROUP_TYPE_RAID)
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You need to be in a raid group to be able to enter this instance." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}
				if(pMapinfo && pMapinfo->type == INSTANCE_RAID && !GetPlayer()->InGroup())
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You need to be in a raid group to be able to enter this instance." << uint8(0) << uint8(0);
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->required_quest && !_player->HasFinishedQuest(pMapinfo->required_quest))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You do not have the required attunement to enter this instance.";
					SendPacket(&msg);
					return;
				}

				if(pMapinfo && pMapinfo->required_item && !_player->GetItemInterface()->GetItemCount(pMapinfo->required_item, true))
				{
					WorldPacket msg;
					msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
					msg << uint32(0) << "You do not have the required attunement to enter this instance.";
					SendPacket(&msg);
					return;
				}

				if(!GetPlayer()->isAlive())
				{
					pCorpse = objmgr.GetCorpseByOwner(GetPlayer()->GetGUIDLow());
					if(pCorpse)
					{
						pMapinfo = WorldMapInfoStorage.LookupEntry(pCorpse->GetMapId());
						if(pMapinfo)
						{
                            if(GetPlayer()->InGroup())
							{
								MapMgr * groupinstance = sWorldCreator.GetInstanceByGroup(GetPlayer()->GetGroup(), GetPlayer(), pMapinfo);
								if (groupinstance)
								{
									if(groupinstance->GetPlayerCount() >= pMapinfo->playerlimit)
                                    {
                                        data.Initialize(SMSG_TRANSFER_ABORTED);
								        data << uint32(INSTANCE_ABORT_FULL);
								        _player->GetSession()->SendPacket(&data);
                                        GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
                                        GetPlayer()->ResurrectPlayer();
								        return;
                                    }

                                }
							}

                            //if its a raid instance and corpse is inside and player is not in a group, ressurect
							if(pMapinfo->type != INSTANCE_NULL && pMapinfo->type != INSTANCE_PVP  && pMapinfo->type != INSTANCE_NONRAID && pMapinfo->type != INSTANCE_MULTIMODE && GetPlayer()->GetMapId() != pCorpse->GetMapId() && pCorpse->GetMapId() == pAreaTrigger->Mapid  && !GetPlayer()->InGroup())
							{
								GetPlayer()->ResurrectPlayer();
								return;
							}
                            //if its a instance and player is trying to enter when corpse is on a diferent instance, repop back
                            else if(pMapinfo->type != INSTANCE_NULL && pMapinfo->type != INSTANCE_PVP &&  pCorpse->GetMapId() != pAreaTrigger->Mapid)
							{
								GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
								return;
							}
						}
					}
					else
					{
						GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(),GetPlayer()->GetMapId());
						return;
					}
				}
				bool result = sWorldCreator.CheckInstanceForObject(static_cast<Object*>(GetPlayer()), pMapinfo);
				if(result)
				{
					GetPlayer()->SaveEntryPoint(pAreaTrigger->Mapid);
					GetPlayer()->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
				}
			}
		}break;
	case ATTYPE_QUESTTRIGGER:
		{

		}break;
	case ATTYPE_INN:
		{
			// Inn
			if (!GetPlayer()->m_isResting) GetPlayer()->ApplyPlayerRestState(true);
		}break;
	case ATTYPE_TELEPORT:
		{
			if(GetPlayer()->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
			{
				GetPlayer()->SaveEntryPoint(pAreaTrigger->Mapid);
				GetPlayer()->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
			}
		}break;
	case ATTYPE_NULL:
		{
			MapInfo *pMapinfo = NULL;
			pMapinfo = WorldMapInfoStorage.LookupEntry(pAreaTrigger->Mapid);
			if(pMapinfo && pMapinfo->HasFlag(WMI_INSTANCE_XPACK_01) && !HasFlag(ACCOUNT_FLAG_XPACK_01))
			{
				WorldPacket msg;
				msg.Initialize(SMSG_BROADCAST_MSG);
				msg << uint32(3) << "You must have The Burning Crusade Expansion to access this content." << uint8(0);
				SendPacket(&msg);
				return;
			}
		}
	default:break;
	}
}
示例#3
0
void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 4);
    uint32 id = 0;
    WorldPacket data(80);
    AreaTrigger *pAreaTrigger = NULL;
    recv_data >> id;
    sLog.outDebug("AreaTrigger: %u", id);

    pAreaTrigger = sWorld.GetAreaTrigger(id);

    // Search quest log, find any exploration quests
    sQuestMgr.OnPlayerExploreArea(GetPlayer(),id);
    
    // if in BG handle is triggers
    if(GetPlayer()->m_bgInBattleground && GetPlayer()->GetCurrentBattleground() != NULL)
    {
        GetPlayer()->GetCurrentBattleground()->HandleBattlegroundAreaTrigger(GetPlayer(), id);
        return;
    }   

    if(pAreaTrigger && pAreaTrigger->Type == ATTYPE_BATTLEGROUND)
    {
        if(pAreaTrigger->Mapid == 489)        // hack fix
            pAreaTrigger->Mapid = 2;
        else if(pAreaTrigger->Mapid == 529)
            pAreaTrigger->Mapid = 3;
        else if(pAreaTrigger->Mapid == 30)
            pAreaTrigger->Mapid = 1;
            
        WorldPacket *pkt = sBattlegroundMgr.BuildBattlegroundListPacket(GetPlayer()->GetGUID(), _player,
            pAreaTrigger->Mapid);
        SendPacket(pkt);
        delete pkt;
        return;
    }

    if(pAreaTrigger)
    {
        bool bFailedPre = false;
        std::string failed_reason;

        if(pAreaTrigger->required_level)
        {
            if(GetPlayer()->getLevel() < pAreaTrigger->required_level)
            {
                bFailedPre = true;
                if(failed_reason.size() > 0)
                    failed_reason += ", and ";
                else
                    failed_reason = "You must be ";

                // mm hacky
                char lvltext[30];
                sprintf(lvltext, "at least level %d", pAreaTrigger->required_level);
                failed_reason += lvltext;
            }
        }
        if(bFailedPre)
        {
            failed_reason += " before you're allowed through here.";
            WorldPacket msg;
            msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
            msg << uint32(0) << failed_reason << uint8(0);
            SendPacket(&msg);
            sLog.outDebug("Player %s failed areatrigger prereq - %s", GetPlayer()->GetName(), failed_reason.c_str());
            return;
        }
        switch(pAreaTrigger->Type)
        {
        case ATTYPE_INSTANCE:
            {
                if(GetPlayer()->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
                {
                    GetPlayer()->SaveEntryPoint();
                    //death system check.
                    Corpse *pCorpse = NULL;
                    CorpseData *pCorpseData = NULL;
                    MapInfo *pMapinfo = NULL;

                    pMapinfo = sWorld.GetMapInformation(pAreaTrigger->Mapid);
                    if(pMapinfo && !pMapinfo->HasFlag(WMI_INSTANCE_ENABLED))
                    {
                        WorldPacket msg;
                        msg.Initialize(SMSG_AREA_TRIGGER_MESSAGE);
                        msg << uint32(0) << "This instance is currently unavailable." << uint8(0) << uint8(0);
                        SendPacket(&msg);
                        return;
                    }

                    if(pMapinfo && pMapinfo->HasFlag(WMI_INSTANCE_XPACK_01) && !HasFlag(ACCOUNT_FLAG_XPACK_01))
                    {
                        WorldPacket msg;
                        msg.Initialize(SMSG_BROADCAST_MSG);
                        msg << uint32(3) << "You must have The Burning Crusade Expansion to access this content." << uint8(0);
                        SendPacket(&msg);
                        return;
                    }

                    if(!GetPlayer()->isAlive())
                    {
                        pCorpse = objmgr.GetCorpseByOwner(GetPlayer());
                        if(pCorpse)
                        {
                            pMapinfo = sWorld.GetMapInformation(pCorpse->GetMapId());
                            if(pMapinfo)
                            {
                                if(pMapinfo->type != INSTANCE_NULL && pMapinfo->type != INSTANCE_PVP  && pMapinfo->type != INSTANCE_NONRAID && GetPlayer()->GetMapId() != pCorpse->GetMapId() && pCorpse->GetMapId() == pAreaTrigger->Mapid  && !GetPlayer()->InGroup())
                                {
                                    GetPlayer()->ResurrectPlayer();
                                    return;
                                }
                                else if(pMapinfo->type != INSTANCE_NONRAID)
                                {
                                    GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
                                    return;
                                }
                            }
                        }
                        else
                        {
                            GetPlayer()->RepopAtGraveyard(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(),GetPlayer()->GetMapId());
                            return;
                        }
                    }
                    
                    sWorldCreator.CheckInstanceForObject(static_cast<Object*>(_player), pMapinfo);
                    _player->SaveEntryPoint();
                    _player->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
                }
            }break;
        case ATTYPE_QUESTTRIGGER:
            {

            }break;
        case ATTYPE_INN:
            {
                // Inn
                if (!GetPlayer()->m_isResting) GetPlayer()->ApplyPlayerRestState(true);
            }break;
        case ATTYPE_TELEPORT:
            {
                if(GetPlayer()->GetPlayerStatus() != TRANSFER_PENDING) //only ports if player is out of pendings
                {
                    _player->SaveEntryPoint();
                    _player->SafeTeleport(pAreaTrigger->Mapid, 0, LocationVector(pAreaTrigger->x, pAreaTrigger->y, pAreaTrigger->z, pAreaTrigger->o));
                }
            }break;
        case ATTYPE_NULL:
            {
                MapInfo *pMapinfo = NULL;
                pMapinfo = sWorld.GetMapInformation(pAreaTrigger->Mapid);
                if(pMapinfo && pMapinfo->HasFlag(WMI_INSTANCE_XPACK_01) && !HasFlag(ACCOUNT_FLAG_XPACK_01))
                {
                    WorldPacket msg;
                    msg.Initialize(SMSG_BROADCAST_MSG);
                    msg << uint32(3) << "You must have The Burning Crusade Expansion to access this content." << uint8(0);
                    SendPacket(&msg);
                    return;
                }
            }
        default:break;
        }
    }
}
示例#4
0
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid)
{
	// preteleport is where all the magic happens :P instance creation, etc.
	MapInfo * inf = LimitedMapInfoStorage.LookupEntry(mapid);
	MapEntry* map = dbcMap.LookupEntry(mapid);
	InstanceMap * instancemap;
	Instance * in = NULL;

	//is the map vaild?
	if(inf == NULL || mapid >= NUM_MAPS)
		return INSTANCE_ABORT_NOT_FOUND;

	// main continent check.
	if(inf->type == INSTANCE_NULL) // 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;

	if(map->israid()) // check that heroic mode is available if the player has requested it.
	{
		if(plr->iRaidType > 1 && inf->type != INSTANCE_MULTIMODE)
			return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE;
	}
	else if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE)
		return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE;

	//do we need addition raid/heroic checks?
	Group * pGroup = plr->GetGroup() ;
	if( !plr->triggerpass_cheat )
	{
		// players without groups cannot enter raid instances (no soloing them:P)
		if( pGroup == NULL && (map->israid() || inf->type == INSTANCE_MULTIMODE))
			return INSTANCE_ABORT_NOT_IN_RAID_GROUP;

		//and has the required level
		if( plr->getLevel() < 80)
		{
			if(!map->israid())
			{
				//otherwise we still need to be lvl 70/80 for heroic.
				if( plr->iInstanceType && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70))
					return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE;
			}
			else
				//otherwise we still need to be lvl 70/80 for heroic.
				if( plr->iRaidType > 1 && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70))
					return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE;

			//and we might need a key too.
			bool reqkey = (inf->heroic_key[0] || inf->heroic_key[1])? true : false;
			bool haskey = (plr->GetItemInterface()->GetItemCount(inf->heroic_key[0], false) || plr->GetItemInterface()->GetItemCount(inf->heroic_key[1], false))? true : false;
			if(reqkey && !haskey)
				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.
	// next we check if there is a saved instance belonging to him.
	// otherwise, we can create them a new one.

	m_mapLock.Acquire();

	//find all instances for our map
	instancemap = m_instances[mapid];
	if(instancemap)
	{
		InstanceMap::iterator itr;
		// do we have a specific instance id we should enter (saved or active).
		// don't bother looking for saved instances, if we had one we found it in areatrigger.cpp
		if(instanceid != 0)
		{
			itr = instancemap->find(instanceid);
			if(itr != instancemap->end())
			{
				in = itr->second;
				//we have an instance,but can we enter it?
				uint8 owns = PlayerOwnsInstance( in, plr );
				if( owns >= OWNER_CHECK_OK )
				{
					// If the map is active and has players
					if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat)
					{
						//check if combat is in progress
						if( in->m_mapMgr->IsCombatInProgress())
						{
							m_mapLock.Release();
							return INSTANCE_ABORT_ENCOUNTER;
						}

						// check if we are full
						if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit )
						{
							m_mapLock.Release();
							return INSTANCE_ABORT_FULL;
						}
					}

					uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType;
					if(in->m_difficulty == plrdiff)
					{
						//wakeup call for saved instances
						if(!in->m_mapMgr)
							in->m_mapMgr = _CreateInstance(in);

						if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers())
						{
							if(plr->GetGroup())
								in->m_creatorGroup = plr->GetGroupID();
						}

						m_mapLock.Release();
						return INSTANCE_OK;
					}
					else
					{
						m_mapLock.Release();
						return INSTANCE_ABORT_TOO_MANY;
					}
				}
				else
					DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns);
			}
			m_mapLock.Release();
			return INSTANCE_ABORT_NOT_FOUND;
		}
		else
		{
			// search all active instances and see if we have one here.
			for(itr = instancemap->begin(); itr != instancemap->end();)
			{
				in = itr->second;
				++itr;
				//we have an instance,but do we own it?
				uint8 owns = PlayerOwnsInstance(in, plr);
				if( owns >= OWNER_CHECK_OK )
				{
					// check the player count and in combat status.
					if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat)
					{
						if( in->m_mapMgr->IsCombatInProgress())
						{
							m_mapLock.Release();
							return INSTANCE_ABORT_ENCOUNTER;
						}
						// check if we are full
						if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit )
						{
							m_mapLock.Release();
							return INSTANCE_ABORT_FULL;
						}
					}

					uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType;
					if(in->m_difficulty == plrdiff)
					{
						//wakeup call for saved instances
						if(!in->m_mapMgr)
							in->m_mapMgr = _CreateInstance(in);

						if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers())
						{
							if(plr->GetGroup())
								in->m_creatorGroup = plr->GetGroupID();
						}

						// found our instance, allow him in.
						m_mapLock.Release();
						return INSTANCE_OK;
					}
				}
				else
					DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns);
			}
		}
	}
	else
	{
		if(instanceid != 0)
		{
			// wtf, how can we have an instance_id for a mapid which doesn't even exist?
			m_mapLock.Release();
			return INSTANCE_ABORT_NOT_FOUND;
		}
		// this mapid hasn't been added yet, so we gotta create the hashmap now.
		m_instances[mapid] = new InstanceMap;
		instancemap = m_instances[mapid];
	}

	// if we're here, it means we need to create a new instance.
	bool raid = map->israid();
	in = new Instance;
	in->m_creation = UNIXTIME;
	in->m_expiration = (raid ? UNIXTIME + inf->cooldown : 0);		// expire time 0 is 10 minutes after last player leaves
	in->m_creatorGuid = plr->GetLowGUID();
	in->m_creatorGroup = (pGroup ? pGroup->GetID() : 0);
	in->m_difficulty = (raid ? plr->iRaidType : plr->iInstanceType);
	in->m_instanceId = GenerateInstanceID();
	in->m_mapId = mapid;
	in->m_mapMgr = NULLMAPMGR;		// always start off without a map manager, it is created in _CreateInstance(in)

	//crash fix; GM's without group will start up raid instances as if they where nonraids
	//this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here!
	if( plr->triggerpass_cheat && !plr->GetGroup() && raid)
	{
		const char * message = "Started this instance for development purposes only, do not invite players!!";
		sEventMgr.AddEvent( plr, &Player::_Warn, message, EVENT_UNIT_SENDMESSAGE, 5000, 1, 0);
	}

	in->m_mapInfo = inf;
	in->m_dbcMap = map;
	in->m_isBattleground = false;
	plr->SetInstanceID(in->m_instanceId);
	DEBUG_LOG("InstanceMgr", "Prepared new %s %u for player %u and group %u on map %u with difficulty %u. (%u)", raid ? "Raid" : "Instance" ,in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_difficulty, in->m_instanceId);

	// apply it in the instance map
	instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) );

	// create the actual instance (if we don't GetInstance() won't be able to access it).
	in->m_mapMgr = _CreateInstance(in);

	// instance created ok, i guess? return the ok for him to transport.
	m_mapLock.Release();
	return INSTANCE_OK;
}