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; } }
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; } }
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; } } }
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; }