diff options
| -rw-r--r-- | sql/updates/8100_world_instance_template.sql | 61 | ||||
| -rw-r--r-- | src/game/CharacterHandler.cpp | 2 | ||||
| -rw-r--r-- | src/game/Group.cpp | 9 | ||||
| -rw-r--r-- | src/game/MapManager.cpp | 4 | ||||
| -rw-r--r-- | src/game/MapManager.h | 2 | ||||
| -rw-r--r-- | src/game/MiscHandler.cpp | 21 | ||||
| -rw-r--r-- | src/game/ObjectMgr.cpp | 21 | ||||
| -rw-r--r-- | src/game/Player.cpp | 27 | ||||
| -rw-r--r-- | src/game/Player.h | 1 |
9 files changed, 132 insertions, 16 deletions
diff --git a/sql/updates/8100_world_instance_template.sql b/sql/updates/8100_world_instance_template.sql new file mode 100644 index 00000000000..5770320f99b --- /dev/null +++ b/sql/updates/8100_world_instance_template.sql @@ -0,0 +1,61 @@ +/* +AZEROTH +Shadowfang Keep Entrance, Stormwind Stockades Entrance, DeadMines Entrance, Uldaman Entrance, Gnomeregan Entrance, +Altar of Atal'Hakkar Entrance, Scarlet Monastery - Graveyard (Entrance), Blackrock Spire - Searing Gorge Instance (Inside), +Blackrock Mountain - Searing Gorge Instance?, Scholomance Entrance, Zul'Gurub Entrance, Stratholme - Eastern Plaguelands Instance, +Karazhan, Main (Entrance) +*/ +UPDATE `instance_template` SET `parent` = 0 WHERE `map` IN (33, 34, 36, 70, 90, 109, 189, 229, 230, 289, 309, 329, 532); + +/* +KALIMDOR +The Barrens - Wailing Caverns, Razorfen Kraul Entrance, Blackphantom Deeps Entrance, Razorfen Downs Entrance, +Zul'Farrak Entrance, Onyxia's Lair Entrance, Caverns Of Time, Black Morass (Entrance), Maraudon, +Ragefire Chasm - Ogrimmar Instance, Dire Maul, Ruins Of Ahn'Qiraj (Outside), Ahn'Qiraj Temple (Outside), +Battle Of Mount Hyjal, Alliance Base (Entrance), Culling of Stratholme (entrance), Caverns Of Time, Old Hillsbrad Foothills (Entrance) +*/ +UPDATE `instance_template` SET `parent` = 1 WHERE `map` IN (43, 47, 48, 129, 209, 249, 269, 349, 389, 429, 509, 531, 534, 560, 595); + +/* +OUTLAND +The Shattered Halls (Entrance), The Blood Furnace (Entrance), Hellfire Ramparts (Entrance), Magtheridon's Lair (Entrance), +The Steamvault (Entrance), The Underbog (Entrance), The Slave Pens (Entrance), Serpentshrine Cavern (Entrance), +The Eye (Entrance), The Arcatraz (Entrance), The Botanica (Entrance), The Mechanar (Entrance), +Shadow Labyrinth (Entrance), Sethekk Halls (Entrance), Mana Tombs (Entrance), Auchenai Crypts (Entrance), +Black Temple (Entrance), Gruul's Lair (Entrance), +Zul'Aman (Entrance), Sunwell Plateau (Entrance), Magisters' Terrace (Entrance), +*/ +UPDATE `instance_template` SET `parent` = 530 WHERE `map` IN (540, 542, 543, 544, 545, 546, 547, 548, 550, 552, 553, 554, 555, 556, 557, 558, 564, 565, 568, 580, 585); + +/* +NORTHREND +Chamber of Aspects, Obsidian Sanctum (entrance), Utgarde Keep (entrance), Utgarde Pinnacle (entrance), +The Nexus (entrance), The Oculus (entrance), Naxxramas (to frostwyrm lair), Violet Hold (entrance), +Gundrak (entrance north), Ulduar, Halls of Lightning (entrance), Ulduar, Halls of Stone (entrance), +Azjol-Nerub (entrance), Ahn'Kahet (entrance), Drak'Tharon Keep (entrance), The Eye of Eternity (entrance), +Vault of Archavon (Entrance), Ulduar Raid entrance, Trial of the Champion, Trial of the Crusader, +*/ +UPDATE `instance_template` SET `parent` = 571 WHERE `map` IN (615, 574, 575, 576, 578, 533, 608, 604, 602, 599, 601, 619, 600, 616, 624, 603, 650, 649); + +-- The Molten Bridge +UPDATE `instance_template` SET `parent` = 230 WHERE `map` = 409; + +-- Blackwing Lair - Blackrock Mountain - Eastern Kingdoms +UPDATE `instance_template` SET `parent` = 229 WHERE `map` = 469; + + +/* +NOT ASSIGNED, SET TO DBC VALUE +*/ + +/* +DBC VALUE 0 +Warsong Gulch, Alterac Valley, Arathi Basin, Eye of the Storm, Nagrand Arena, Blades Edge Arena, Ruins of Lordaeron, +Isle of Conquest, Strand of the Ancients +*/ +UPDATE `instance_template` SET `parent` = 0 WHERE `map` IN (489, 529, 566, 559, 562, 572, 628, 607); +/* +DBC VALUE 4294967295 +Alterac Valley +*/ +UPDATE `instance_template` SET `parent` = 4294967295 WHERE `map` IN (30); diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index feb85d567d2..6fa89113494 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -708,7 +708,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) } } - if (!pCurrChar->GetMap()->Add(pCurrChar)) + if (!pCurrChar->GetMap()->Add(pCurrChar) || !pCurrChar->CheckInstanceLoginValid()) { AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); if (at) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index 1bc542ec08a..3b45c48cb26 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1796,14 +1796,7 @@ void Group::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload) void Group::_homebindIfInstance(Player *player) { if (player && !player->isGameMaster() && sMapStore.LookupEntry(player->GetMapId())->IsDungeon()) - { - // leaving the group in an instance, the homebind timer is started - // unless the player is permanently saved to the instance - InstanceSave *save = sInstanceSaveManager.GetInstanceSave(player->GetInstanceId()); - InstancePlayerBind *playerBind = save ? player->GetBoundInstance(save->GetMapId(), save->GetDifficulty()) : NULL; - if (!playerBind || !playerBind->perm) - player->m_InstanceValid = false; - } + player->m_InstanceValid = false; } void Group::BroadcastGroupUpdate(void) diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 49aba69a8c1..75a7697279b 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -157,7 +157,7 @@ Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const return ((MapInstanced*)map)->FindMap(instanceId); } -bool MapManager::CanPlayerEnter(uint32 mapid, Player* player) +bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) { const MapEntry *entry = sMapStore.LookupEntry(mapid); if (!entry) @@ -263,7 +263,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player) int8 maxPlayers = mapDiff ? mapDiff->maxPlayers : 0; if (maxPlayers != -1) //-1: unlimited access { - if (boundedMap->GetPlayersCountExceptGMs() >= maxPlayers) + if (loginCheck ? boundedMap->GetPlayersCountExceptGMs() > maxPlayers : boundedMap->GetPlayersCountExceptGMs() >= maxPlayers) { sLog.outDebug("MAP: Player '%s' can't enter instance '%s' because it's full.", player->GetName(), mapName); player->SendTransferAborted(mapid, TRANSFER_ABORT_MAX_PLAYERS); diff --git a/src/game/MapManager.h b/src/game/MapManager.h index 5656fdd986c..d94f9fced0e 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -118,7 +118,7 @@ class MapManager : public Trinity::Singleton<MapManager, Trinity::ClassLevelLock typedef std::map<uint32, TransportSet> TransportMap; TransportMap m_TransportsByMap; - bool CanPlayerEnter(uint32 mapid, Player* player); + bool CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck = false); void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y); uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } void InitMaxInstanceId(); diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 46c822fcbf0..5cc3d6f3e35 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -48,6 +48,8 @@ #include "CreatureAI.h" #include "DBCEnums.h" #include "ScriptMgr.h" +#include "MapManager.h" +#include "InstanceData.h" void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) { @@ -915,6 +917,25 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) if (!GetPlayer()->Satisfy(objmgr.GetAccessRequirement(at->access_id), at->target_mapId, true)) return; + // check if player can enter instance : instance not full, and raid instance not in encounter fight + if (Map * newMap = MapManager::Instance().CreateMap(at->target_mapId, GetPlayer(), 0)) + { + if (newMap && newMap->IsDungeon() && ((InstanceMap*)newMap)->GetInstanceData() && ((InstanceMap*)newMap)->GetMapDifficulty()) + { + if (newMap->GetPlayersCountExceptGMs() >= ((InstanceMap*)newMap)->GetMapDifficulty()->maxPlayers) + { + GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAX_PLAYERS); + return; + } + + if (newMap->IsRaid() && ((InstanceMap*)newMap)->GetInstanceData()->IsEncounterInProgress()) + { + GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ZONE_IN_COMBAT); + return; + } + } + } + GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 349dd342b7a..6db783eb610 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -5899,15 +5899,30 @@ void ObjectMgr::LoadAccessRequirements() } /* - * Searches for the areatrigger which teleports players out of the given map + * Searches for the areatrigger which teleports players out of the given map with instance_template.parent field support */ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const { + bool useParentDbValue = false; + uint32 parentId = 0; const MapEntry *mapEntry = sMapStore.LookupEntry(Map); - if (!mapEntry || mapEntry->entrance_map < 0) return NULL; + if (!mapEntry || mapEntry->entrance_map < 0) + return NULL; + + if (mapEntry->IsDungeon()) + { + const InstanceTemplate *iTemplate = objmgr.GetInstanceTemplate(Map); + + if (!iTemplate) + return NULL; + + parentId = iTemplate->parent; + useParentDbValue = true; + } + uint32 entrance_map = uint32(mapEntry->entrance_map); for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) - if (itr->second.target_mapId == entrance_map) + if ((!useParentDbValue && itr->second.target_mapId == entrance_map) || (useParentDbValue && itr->second.target_mapId == parentId)) { AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); if (atEntry && atEntry->mapid == Map) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 62e128f2787..5d11b8acea9 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1826,7 +1826,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // Check enter rights before map getting to avoid creating instance copy for player // this check not dependent from map instance copy and same for all instance copies of selected map - if (!MapManager::Instance().CanPlayerEnter(mapid, this)) + if (!MapManager::Instance().CanPlayerEnter(mapid, this, false)) return false; // If the map is not created, assume it is possible to enter it. @@ -17347,6 +17347,31 @@ bool Player::Satisfy(AccessRequirement const *ar, uint32 target_map, bool report return true; } +bool Player::CheckInstanceLoginValid() +{ + if (!GetMap()) + return false; + + if (!GetMap()->IsDungeon() || isGameMaster()) + return true; + + if (GetMap()->IsRaid()) + { + // cannot be in raid instance without a group + if (!GetGroup()) + return false; + } + else + { + // cannot be in normal instance without a group and more players than 1 in instance + if (!GetGroup() && GetMap()->GetPlayersCountExceptGMs() > 1) + return false; + } + + // do checks for satisfy accessreqs, instance full, encounter in progress (raid), perm bind group != perm bind player + return MapManager::Instance().CanPlayerEnter(GetMap()->GetId(), this, true); +} + bool Player::_LoadHomeBind(QueryResult_AutoPtr result) { PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); diff --git a/src/game/Player.h b/src/game/Player.h index c5537de5eed..4d1058fc43d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2266,6 +2266,7 @@ class Player : public Unit, public GridObject<Player> void SendSavedInstances(); static void ConvertInstancesToGroup(Player *player, Group *group = NULL, uint64 player_guid = 0); bool Satisfy(AccessRequirement const*, uint32 target_map, bool report = false); + bool CheckInstanceLoginValid(); // last used pet number (for BG's) uint32 GetLastPetNumber() const { return m_lastpetnumber; } |
