InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty) { // load/create a map TRINITY_GUARD(ACE_Thread_Mutex, Lock); // make sure we have a valid map id const MapEntry* entry = sMapStore.LookupEntry(GetId()); if (!entry) { sLog->outError("CreateInstance: no entry for map %d", GetId()); ASSERT(false); } const InstanceTemplate* iTemplate = sObjectMgr->GetInstanceTemplate(GetId()); if (!iTemplate) { sLog->outError("CreateInstance: no instance template for map %d", GetId()); ASSERT(false); } // some instances only have one difficulty GetDownscaledMapDifficultyData(GetId(), difficulty); sLog->outDebug(LOG_FILTER_MAPS, "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); ASSERT(map->IsDungeon()); bool load_data = save != NULL; map->CreateInstanceData(load_data); m_InstancedMaps[InstanceId] = map; return map; }
void InstanceSaveManager::ForceGlobalReset(uint32 mapId, Difficulty difficulty) { if (!GetDownscaledMapDifficultyData(mapId, difficulty)) return; // remove currently scheduled reset times ScheduleReset(false, 0, InstResetEvent(1, mapId, difficulty, 0)); ScheduleReset(false, 0, InstResetEvent(4, mapId, difficulty, 0)); // force global reset on the instance _ResetOrWarnAll(mapId, difficulty, false, GameTime::GetGameTime()); }
InstancePlayerBind* InstanceSaveManager::PlayerGetBoundInstance(uint32 guidLow, uint32 mapid, Difficulty difficulty) { Difficulty difficulty_fixed = (mapid == 631 || mapid == 724 ? Difficulty(difficulty%2) : difficulty); MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(mapid, difficulty_fixed); if (!mapDiff) return NULL; BoundInstancesMapWrapper* w = NULL; PlayerBindStorage::const_iterator itr = playerBindStorage.find(guidLow); if (itr != playerBindStorage.end()) w = itr->second; else return NULL; BoundInstancesMap::iterator itr2 = w->m[difficulty_fixed].find(mapid); if (itr2 != w->m[difficulty_fixed].end()) return &itr2->second; else return NULL; }
InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty) { // load/create a map TRINITY_GUARD(ACE_Thread_Mutex, Lock); // make sure we have a valid map id const MapEntry* entry = sMapStore.LookupEntry(GetId()); if (!entry) { sLog->outError("CreateInstance: no entry for map %d", GetId()); ASSERT(false); } const InstanceTemplate* iTemplate = sObjectMgr->GetInstanceTemplate(GetId()); if (!iTemplate) { sLog->outError("CreateInstance: no instance template for map %d", GetId()); ASSERT(false); } // some instances only have one difficulty GetDownscaledMapDifficultyData(GetId(), difficulty); ;//sLog->outDebug(LOG_FILTER_MAPS, "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); InstanceMap* map = new InstanceMap(GetId(), InstanceId, difficulty, this); ASSERT(map->IsDungeon()); map->LoadRespawnTimes(); if (save) map->CreateInstanceScript(true, save->GetInstanceData(), save->GetCompletedEncounterMask()); else map->CreateInstanceScript(false, "", 0); if (!save) // this is for sure a dungeon (assert above), no need to check here sInstanceSaveMgr->AddInstanceSave(GetId(), InstanceId, difficulty); m_InstancedMaps[InstanceId] = map; return map; }
InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty) { // load/create a map std::lock_guard<std::mutex> lock(_mapLock); // make sure we have a valid map id const MapEntry* entry = sMapStore.LookupEntry(GetId()); if (!entry) { TC_LOG_ERROR("maps", "CreateInstance: no entry for map %d", GetId()); ABORT(); } const InstanceTemplate* iTemplate = sObjectMgr->GetInstanceTemplate(GetId()); if (!iTemplate) { TC_LOG_ERROR("maps", "CreateInstance: no instance template for map %d", GetId()); ABORT(); } // some instances only have one difficulty GetDownscaledMapDifficultyData(GetId(), difficulty); TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); ASSERT(map->IsDungeon()); map->LoadRespawnTimes(); map->LoadCorpseData(); bool load_data = save != NULL; map->CreateInstanceData(load_data); m_InstancedMaps[InstanceId] = map; return map; }
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) { MapEntry const* entry = sMapStore.LookupEntry(mapid); if (!entry) return false; if (!entry->IsDungeon()) return true; InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapid); if (!instance) return false; Difficulty targetDifficulty = player->GetDifficulty(entry->IsRaid()); //The player has a heroic mode and tries to enter into instance which has no a heroic mode MapDifficulty const* mapDiff = GetMapDifficultyData(entry->MapID, targetDifficulty); if (!mapDiff) { // Send aborted message for dungeons if (entry->IsNonRaidDungeon()) { player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, player->GetDungeonDifficulty()); return false; } else // attempt to downscale mapDiff = GetDownscaledMapDifficultyData(entry->MapID, targetDifficulty); } // FIXME: mapDiff is never used //Bypass checks for GMs if (player->IsGameMaster()) return true; char const* mapName = entry->name; Group* group = player->GetGroup(); if (entry->IsRaid()) { // can only enter in a raid group if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) { // probably there must be special opcode, because client has this string constant in GlobalStrings.lua /// @todo this is not a good place to send the message player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName); return false; } } if (!player->IsAlive()) { if (Corpse* corpse = player->GetCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint32 corpseMap = corpse->GetMapId(); do { if (corpseMap == mapid) break; InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap); corpseMap = corpseInstance ? corpseInstance->Parent : 0; } while (corpseMap); if (!corpseMap) { WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE); player->GetSession()->SendPacket(&data); TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName); return false; } TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName); player->ResurrectPlayer(0.5f, false); player->SpawnCorpseBones(); } else TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str()); } //Get instance where player's group is bound & its map if (group) { InstanceGroupBind* boundInstance = group->GetBoundInstance(entry); if (boundInstance && boundInstance->save) if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId())) if (!loginCheck && !boundMap->CanEnter(player)) return false; /* This check has to be moved to InstanceMap::CanEnter() // Player permanently bounded to different instance than groups one InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficulty(entry->IsRaid())); if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) { /// @todo send some kind of error message to the player return false; }*/ } // players are only allowed to enter 5 instances per hour if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup()))) { uint32 instanceIdToCheck = 0; if (InstanceSave* save = player->GetInstanceSave(mapid, entry->IsRaid())) instanceIdToCheck = save->GetInstanceId(); // instanceId can never be 0 - will not be found if (!player->CheckInstanceCount(instanceIdToCheck) && !player->IsDead()) { player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES); return false; } } //Other requirements return player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true); }
bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) { ASSERT(type < MAX_DISABLE_TYPES); if (m_DisableMap[type].empty()) return false; DisableTypeMap::iterator itr = m_DisableMap[type].find(entry); if (itr == m_DisableMap[type].end()) // not disabled return false; switch (type) { case DISABLE_TYPE_SPELL: { uint8 spellFlags = itr->second.flags; if (unit) { if ((spellFlags & SPELL_DISABLE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || (unit->GetTypeId() == TYPEID_UNIT && ((unit->ToCreature()->isPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE))) { if (spellFlags & SPELL_DISABLE_MAP) { std::set<uint32> const& mapIds = itr->second.params[0]; if (mapIds.find(unit->GetMapId()) != mapIds.end()) return true; // Spell is disabled on current map if (!(spellFlags & SPELL_DISABLE_AREA)) return false; // Spell is disabled on another map, but not this one, return false // Spell is disabled in an area, but not explicitly our current mapId. Continue processing. } if (spellFlags & SPELL_DISABLE_AREA) { std::set<uint32> const& areaIds = itr->second.params[1]; if (areaIds.find(unit->GetAreaId()) != areaIds.end()) return true; // Spell is disabled in this area return false; // Spell is disabled in another area, but not this one, return false } else return true; // Spell disabled for all maps } return false; } else if (spellFlags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast return true; else if (flags & SPELL_DISABLE_LOS) return spellFlags & SPELL_DISABLE_LOS; break; } case DISABLE_TYPE_MAP: if (Player const* player = unit->ToPlayer()) { MapEntry const* mapEntry = sMapStore.LookupEntry(entry); if (mapEntry->IsDungeon()) { uint8 disabledModes = itr->second.flags; Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid()); GetDownscaledMapDifficultyData(entry, targetDifficulty); switch (targetDifficulty) { case DUNGEON_DIFFICULTY_NORMAL: return disabledModes & DUNGEON_STATUSFLAG_NORMAL; case DUNGEON_DIFFICULTY_HEROIC: return disabledModes & DUNGEON_STATUSFLAG_HEROIC; case RAID_DIFFICULTY_10MAN_HEROIC: return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC; case RAID_DIFFICULTY_25MAN_HEROIC: return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC; } } else if (mapEntry->map_type == MAP_COMMON) return true; } return false; case DISABLE_TYPE_QUEST: if (!unit) return true; if (Player const* player = unit->ToPlayer()) if (player->isGameMaster()) return false; return true; case DISABLE_TYPE_BATTLEGROUND: case DISABLE_TYPE_OUTDOORPVP: case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: case DISABLE_TYPE_MMAP: return true; case DISABLE_TYPE_VMAP: return flags & itr->second.flags; } return false; }
Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck) { MapEntry const* entry = sMapStore.LookupEntry(mapid); if (!entry) return Map::CANNOT_ENTER_NO_ENTRY; if (!entry->IsDungeon()) return Map::CAN_ENTER; InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapid); if (!instance) return Map::CANNOT_ENTER_UNINSTANCED_DUNGEON; Difficulty targetDifficulty, requestedDifficulty; targetDifficulty = requestedDifficulty = player->GetDifficulty(entry->IsRaid()); // Get the highest available difficulty if current setting is higher than the instance allows MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(entry->MapID, targetDifficulty); if (!mapDiff) return Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE; //Bypass checks for GMs if (player->IsGameMaster()) return Map::CAN_ENTER; char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; Group* group = player->GetGroup(); if (entry->IsRaid()) // can only enter in a raid group if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) return Map::CANNOT_ENTER_NOT_IN_RAID; if (!player->IsAlive()) { if (player->HasCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint32 corpseMap = player->GetCorpseLocation().GetMapId(); do { if (corpseMap == mapid) break; InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap); corpseMap = corpseInstance ? corpseInstance->Parent : 0; } while (corpseMap); if (!corpseMap) return Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE; TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName); } else TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str()); } //Get instance where player's group is bound & its map if (!loginCheck && group) { InstanceGroupBind* boundInstance = group->GetBoundInstance(entry); if (boundInstance && boundInstance->save) if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId())) if (Map::EnterState denyReason = boundMap->CannotEnter(player)) return denyReason; } // players are only allowed to enter 5 instances per hour if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup()))) { uint32 instanceIdToCheck = 0; if (InstanceSave* save = player->GetInstanceSave(mapid, entry->IsRaid())) instanceIdToCheck = save->GetInstanceId(); // instanceId can never be 0 - will not be found if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead()) return Map::CANNOT_ENTER_TOO_MANY_INSTANCES; } //Other requirements if (player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true)) return Map::CAN_ENTER; else return Map::CANNOT_ENTER_UNSPECIFIED_REASON; }
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) { const MapEntry *entry = sMapStore.LookupEntry(mapid); if (!entry) return false; if (!entry->IsDungeon()) return true; InstanceTemplate const* instance = sObjectMgr.GetInstanceTemplate(mapid); if (!instance) return false; Difficulty targetDifficulty = player->GetDifficulty(entry->IsRaid()); //The player has a heroic mode and tries to enter into instance which has no a heroic mode MapDifficulty const* mapDiff = GetMapDifficultyData(entry->MapID, targetDifficulty); if (!mapDiff) { // Send aborted message for dungeons if (entry->IsNonRaidDungeon()) { player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, player->GetDungeonDifficulty()); return false; } else // attempt to downscale mapDiff = GetDownscaledMapDifficultyData(entry->MapID, targetDifficulty); } //Bypass checks for GMs if (player->isGameMaster()) return true; const char *mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; Group* pGroup = player->GetGroup(); if (entry->IsRaid()) { // can only enter in a raid group if ((!pGroup || !pGroup->isRaidGroup()) && !sWorld.getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) { // probably there must be special opcode, because client has this string constant in GlobalStrings.lua // TODO: this is not a good place to send the message player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); sLog.outDebug("MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName(), mapName); return false; } } if (!player->isAlive()) { if (Corpse *corpse = player->GetCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint32 instance_map = corpse->GetMapId(); do { if (instance_map == mapid) break; InstanceTemplate const* instance = sObjectMgr.GetInstanceTemplate(instance_map); instance_map = instance ? instance->parent : 0; } while (instance_map); if (!instance_map) { WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE); player->GetSession()->SendPacket(&data); sLog.outDebug("MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName(), mapName); return false; } sLog.outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName(), mapName); } else sLog.outDebug("Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName()); } //Get instance where player's group is bound & its map if (pGroup) { InstanceGroupBind* boundedInstance = pGroup->GetBoundInstance(entry); if (boundedInstance && boundedInstance->save) if (Map *boundedMap = sMapMgr.FindMap(mapid,boundedInstance->save->GetInstanceId())) if (!loginCheck && !boundedMap->CanEnter(player)) return false; /* This check has to be moved to InstanceMap::CanEnter() // Player permanently bounded to different instance than groups one InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficulty(entry->IsRaid())); if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) { //TODO: send some kind of error message to the player return false; }*/ } //Other requirements return player->Satisfy(sObjectMgr.GetAccessRequirement(mapid, targetDifficulty), mapid, true); }
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) { MapEntry const* entry = sMapStore.LookupEntry(mapid); if (!entry) return false; if (!entry->IsDungeon()) return true; InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapid); if (!instance) return false; Difficulty targetDifficulty, requestedDifficulty; targetDifficulty = requestedDifficulty = player->GetDifficulty(entry->IsRaid()); // Get the highest available difficulty if current setting is higher than the instance allows MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(entry->MapID, targetDifficulty); if (!mapDiff) { player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, requestedDifficulty); return false; } //Bypass checks for GMs if (player->IsGameMaster()) return true; char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; Group* group = player->GetGroup(); if (entry->IsRaid()) { // can only enter in a raid group if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) { // probably there must be special opcode, because client has this string constant in GlobalStrings.lua // TODO: this is not a good place to send the message player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); ;//sLog->outDebug(LOG_FILTER_MAPS, "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName); return false; } } // xinef: dont allow LFG Group to enter other instance that is selected if (group) if (group->isLFGGroup()) if (!sLFGMgr->inLfgDungeonMap(group->GetGUID(), mapid, targetDifficulty)) { player->SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED); return false; } if (!player->IsAlive()) { if (Corpse* corpse = player->GetCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint32 corpseMap = corpse->GetMapId(); do { if (corpseMap == mapid) break; InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap); corpseMap = corpseInstance ? corpseInstance->Parent : 0; } while (corpseMap); if (!corpseMap) { WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE, 0); player->GetSession()->SendPacket(&data); ;//sLog->outDebug(LOG_FILTER_MAPS, "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName); return false; } ;//sLog->outDebug(LOG_FILTER_MAPS, "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName); player->ResurrectPlayer(0.5f, false); player->SpawnCorpseBones(); } else ;//sLog->outDebug(LOG_FILTER_MAPS, "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str()); } // if map exists - check for being full, etc. if (!loginCheck) // for login this is done by the calling function { uint32 destInstId = sInstanceSaveMgr->PlayerGetDestinationInstanceId(player, mapid, targetDifficulty); if (destInstId) if (Map* boundMap = sMapMgr->FindMap(mapid, destInstId)) if (!boundMap->CanEnter(player, loginCheck)) return false; } // players are only allowed to enter 5 instances per hour if (entry->IsDungeon() && (!group || !group->isLFGGroup() || !group->IsLfgRandomInstance())) { uint32 instaceIdToCheck = 0; if (InstanceSave* save = sInstanceSaveMgr->PlayerGetInstanceSave(player->GetGUIDLow(), mapid, player->GetDifficulty(entry->IsRaid()))) instaceIdToCheck = save->GetInstanceId(); // instaceIdToCheck can be 0 if save not found - means no bind so the instance is new if (!player->CheckInstanceCount(instaceIdToCheck) && !player->isDead()) { player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES); return false; } } //Other requirements return player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true); }
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) { MapEntry const* entry = sMapStore.LookupEntry(mapid); if (!entry) return false; if (!entry->IsDungeon()) return true; InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapid); if (!instance) return false; Difficulty targetDifficulty, requestedDifficulty; targetDifficulty = requestedDifficulty = player->GetDifficultyID(entry); // Get the highest available difficulty if current setting is higher than the instance allows MapDifficultyEntry const* mapDiff = GetDownscaledMapDifficultyData(entry->ID, targetDifficulty); if (!mapDiff) { player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, requestedDifficulty); return false; } //Bypass checks for GMs if (player->IsGameMaster()) return true; char const* mapName = entry->MapName_lang; Group* group = player->GetGroup(); if (entry->IsRaid()) { // can only enter in a raid group if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) { /// @todo this is not a good place to send the message WorldPacket data(SMSG_RAID_GROUP_ONLY); data << uint32(0) << uint32(2); player->GetSession()->SendPacket(&data); TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName); return false; } } if (!player->IsAlive()) { if (Corpse* corpse = player->GetCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint32 corpseMap = corpse->GetMapId(); do { if (corpseMap == mapid) break; InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap); corpseMap = corpseInstance ? corpseInstance->Parent : 0; } while (corpseMap); if (!corpseMap) { WorldPackets::Misc::AreaTriggerNoCorpse packet; player->GetSession()->SendPacket(packet.Write()); TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName); return false; } TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName); player->ResurrectPlayer(0.5f, false); player->SpawnCorpseBones(); } else TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str()); } //Get instance where player's group is bound & its map if (group) { InstanceGroupBind* boundInstance = group->GetBoundInstance(entry); if (boundInstance && boundInstance->save) if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId())) if (!loginCheck && !boundMap->CanEnter(player)) return false; /* This check has to be moved to InstanceMap::CanEnter() // Player permanently bounded to different instance than groups one InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficultyID(entry)); if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) { /// @todo send some kind of error message to the player return false; }*/ } // players are only allowed to enter 5 instances per hour if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup()))) { uint32 instanceIdToCheck = 0; if (InstanceSave* save = player->GetInstanceSave(mapid)) instanceIdToCheck = save->GetInstanceId(); // instanceId can never be 0 - will not be found if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead()) { player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES); return false; } } //Other requirements return player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true); }
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) { MapEntry const* entry = sMapStore.LookupEntry(mapid); if (!entry) return false; if (!entry->IsDungeon()) return true; InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(mapid); if (!instance) return false; Difficulty targetDifficulty = player->GetDifficulty(entry->IsRaid()); //The player has a heroic mode and tries to enter into instance which has no a heroic mode MapDifficulty const* mapDiff = GetMapDifficultyData(entry->MapID, targetDifficulty); if (!mapDiff) { // Send aborted message for dungeons if (entry->IsNonRaidDungeon()) { player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, player->GetDungeonDifficulty()); return false; } else // attempt to downscale mapDiff = GetDownscaledMapDifficultyData(entry->MapID, targetDifficulty); } //Bypass checks for GMs if (player->isGameMaster()) return true; char const* mapName = entry->name; Group* group = player->GetGroup(); if (entry->IsRaid()) { // can only enter in a raid group if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) { // probably there must be special opcode, because client has this string constant in GlobalStrings.lua // TODO: this is not a good place to send the message player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); sLog->outDebug("MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName(), mapName); return false; } } if (!player->isAlive()) { if (Corpse* corpse = player->GetCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse uint32 corpseMap = corpse->GetMapId(); do { if (corpseMap == mapid) break; InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(corpseMap); corpseMap = instance ? instance->parent : 0; } while (corpseMap); if (!corpseMap) { WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE); player->GetSession()->SendPacket(&data); sLog->outDebug("MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName(), mapName); return false; } sLog->outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName(), mapName); } else sLog->outDebug("Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName()); } // players are only allowed to enter 5 instances per hour if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup()))) { uint32 instaceIdToCheck = 0; if (InstanceSave* save = player->GetInstanceSave(mapid, entry->IsRaid())) instaceIdToCheck = save->GetInstanceId(); // instanceId can never be 0 - will not be found if (!player->CheckInstanceCount(instaceIdToCheck)) { player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES); return false; } } //Other requirements return player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true); }
bool DisableMgr::IsDisabledFor(DisableType type, uint32 entry, Unit const* pUnit) { ASSERT(type < MAX_DISABLE_TYPES); if (m_DisableMap[type].empty()) return false; DisableTypeMap::iterator itr = m_DisableMap[type].find(entry); if (itr == m_DisableMap[type].end()) // not disabled return false; switch (type) { case DISABLE_TYPE_SPELL: { uint8 flags = itr->second; if (pUnit) { if (flags & SPELL_DISABLE_PLAYER && pUnit->GetTypeId() == TYPEID_PLAYER) return true; else if (pUnit->GetTypeId() == TYPEID_UNIT) { if (pUnit->ToCreature()->isPet()) { if (flags & SPELL_DISABLE_PET) return true; } else if (flags & SPELL_DISABLE_CREATURE) return true; } return false; } else if (flags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast return true; } case DISABLE_TYPE_MAP: if (Player const* pPlayer = pUnit->ToPlayer()) { MapEntry const* mapEntry = sMapStore.LookupEntry(entry); if (mapEntry->IsDungeon()) { uint8 disabledModes = itr->second; Difficulty targetDifficulty = pPlayer->GetDifficulty(mapEntry->IsRaid()); GetDownscaledMapDifficultyData(entry, targetDifficulty); switch(targetDifficulty) { case DUNGEON_DIFFICULTY_NORMAL: return disabledModes & DUNGEON_STATUSFLAG_NORMAL; case DUNGEON_DIFFICULTY_HEROIC: return disabledModes & DUNGEON_STATUSFLAG_HEROIC; case RAID_DIFFICULTY_10MAN_HEROIC: return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC; case RAID_DIFFICULTY_25MAN_HEROIC: return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC; } } else if (mapEntry->map_type == MAP_COMMON) return true; } return false; case DISABLE_TYPE_QUEST: if (!pUnit) return true; if (Player const* pPlayer = pUnit->ToPlayer()) if (pPlayer->isGameMaster()) return false; return true; case DISABLE_TYPE_BATTLEGROUND: case DISABLE_TYPE_OUTDOORPVP: case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: return true; } return false; }