Created
September 7, 2012 15:30
-
-
Save cyberium/3667184 to your computer and use it in GitHub Desktop.
Rework map prerequisite check
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/game/Map.cpp b/src/game/Map.cpp | |
index dc7e790..5f2f80b 100644 | |
--- a/src/game/Map.cpp | |
+++ b/src/game/Map.cpp | |
@@ -1249,29 +1249,6 @@ void DungeonMap::InitVisibilityDistance() | |
*/ | |
bool DungeonMap::CanEnter(Player* player) | |
{ | |
- if (player->GetMapRef().getTarget() == this) | |
- { | |
- sLog.outError("DungeonMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode()); | |
- MANGOS_ASSERT(false); | |
- return false; | |
- } | |
- | |
- // cannot enter if the instance is full (player cap), GMs don't count | |
- uint32 maxPlayers = GetMaxPlayers(); | |
- if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers) | |
- { | |
- DETAIL_LOG("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName()); | |
- player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); | |
- return false; | |
- } | |
- | |
- // cannot enter while an encounter in the instance is in progress | |
- if (!player->isGameMaster() && GetInstanceData() && GetInstanceData()->IsEncounterInProgress() && player->GetMapId() != GetId()) | |
- { | |
- player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); | |
- return false; | |
- } | |
- | |
return Map::CanEnter(player); | |
} | |
@@ -1549,13 +1526,6 @@ void BattleGroundMap::InitVisibilityDistance() | |
bool BattleGroundMap::CanEnter(Player* player) | |
{ | |
- if (player->GetMapRef().getTarget() == this) | |
- { | |
- sLog.outError("BGMap::CanEnter - player %u already in map!", player->GetGUIDLow()); | |
- MANGOS_ASSERT(false); | |
- return false; | |
- } | |
- | |
if (player->GetBattleGroundId() != GetInstanceId()) | |
return false; | |
@@ -1603,6 +1573,18 @@ void BattleGroundMap::UnloadAll(bool pForce) | |
Map::UnloadAll(pForce); | |
} | |
+bool Map::CanEnter(Player* player) | |
+{ | |
+ if (player->GetMapRef().getTarget() == this) | |
+ { | |
+ sLog.outError("Map::CanEnter - player %u already in map!", player->GetGUIDLow()); | |
+ MANGOS_ASSERT(false); | |
+ return false; | |
+ } | |
+ | |
+ return true; | |
+} | |
+ | |
/// Put scripts in the execution queue | |
bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target) | |
{ | |
diff --git a/src/game/Map.h b/src/game/Map.h | |
index 4e908a4..4761fd0 100644 | |
--- a/src/game/Map.h | |
+++ b/src/game/Map.h | |
@@ -171,7 +171,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType> | |
bool CheckGridIntegrity(Creature* c, bool moved) const; | |
uint32 GetInstanceId() const { return i_InstanceId; } | |
- virtual bool CanEnter(Player* /*player*/) { return true; } | |
+ virtual bool CanEnter(Player* /*player*/); | |
const char* GetMapName() const; | |
// have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap | |
diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp | |
index 81e6814..bb6159d 100644 | |
--- a/src/game/MapManager.cpp | |
+++ b/src/game/MapManager.cpp | |
@@ -149,62 +149,6 @@ Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const | |
return iter->second; | |
} | |
-/* | |
- checks that do not require a map to be created | |
- will send transfer error messages on fail | |
-*/ | |
-bool MapManager::CanPlayerEnter(uint32 mapid, Player* player) | |
-{ | |
- const MapEntry* entry = sMapStore.LookupEntry(mapid); | |
- if (!entry) | |
- return false; | |
- | |
- const char* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; | |
- | |
- if (entry->IsDungeon()) | |
- { | |
- if (entry->IsRaid()) | |
- { | |
- // GMs can avoid raid limitations | |
- if (!player->isGameMaster() && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_RAID)) | |
- { | |
- // can only enter in a raid group | |
- Group* group = player->GetGroup(); | |
- if (!group || !group->isRaidGroup()) | |
- { | |
- // 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("You must be in a raid group to enter %s instance", mapName); | |
- DEBUG_LOG("MAP: Player '%s' must be in a raid group to enter instance of '%s'", player->GetName(), mapName); | |
- return false; | |
- } | |
- } | |
- } | |
- | |
- // The player has a heroic mode and tries to enter into instance which has no a heroic mode | |
- MapDifficultyEntry const* mapDiff = GetMapDifficultyData(entry->MapID, player->GetDifficulty(entry->map_type == MAP_RAID)); | |
- if (!mapDiff) | |
- { | |
- bool isRegularTargetMap = player->GetDifficulty(entry->IsRaid()) == REGULAR_DIFFICULTY; | |
- | |
- // Send aborted message | |
- // FIX ME: what about absent normal/heroic mode with specific players limit... | |
- player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, isRegularTargetMap ? DUNGEON_DIFFICULTY_NORMAL : DUNGEON_DIFFICULTY_HEROIC); | |
- return false; | |
- } | |
- | |
- // TODO: move this to a map dependent location | |
- /*if(i_data && i_data->IsEncounterInProgress()) | |
- { | |
- DEBUG_LOG("MAP: Player '%s' can't enter instance '%s' while an encounter is in progress.", player->GetName(), GetMapName()); | |
- player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); | |
- return(false); | |
- }*/ | |
- } | |
- | |
- return true; | |
-} | |
- | |
void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId) | |
{ | |
Guard _guard(*this); | |
@@ -223,8 +167,7 @@ void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId) | |
} | |
} | |
-void | |
-MapManager::Update(uint32 diff) | |
+void MapManager::Update(uint32 diff) | |
{ | |
i_timer.Update(diff); | |
if (!i_timer.Passed()) | |
diff --git a/src/game/MapManager.h b/src/game/MapManager.h | |
index 2fede2d..f9edc63 100644 | |
--- a/src/game/MapManager.h | |
+++ b/src/game/MapManager.h | |
@@ -139,7 +139,6 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS:: | |
typedef std::map<uint32, TransportSet> TransportMap; | |
TransportMap m_TransportsByMap; | |
- bool CanPlayerEnter(uint32 mapid, Player* player); | |
void InitializeVisibilityDistanceInfo(); | |
/* statistics */ | |
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp | |
index feb0091..2fb4b86 100644 | |
--- a/src/game/MiscHandler.cpp | |
+++ b/src/game/MiscHandler.cpp | |
@@ -801,60 +801,8 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) | |
player->SpawnCorpseBones(); | |
} | |
- // check trigger requirements | |
- uint32 miscRequirement = 0; | |
- AreaLockStatus lockStatus = player->GetAreaTriggerLockStatus(at, player->GetDifficulty(targetMapEntry->IsRaid()), miscRequirement); | |
- switch (lockStatus) | |
- { | |
- case AREA_LOCKSTATUS_OK: | |
- player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT); | |
- break; | |
- case AREA_LOCKSTATUS_TOO_LOW_LEVEL: | |
- SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED), miscRequirement); | |
- break; | |
- case AREA_LOCKSTATUS_ZONE_IN_COMBAT: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ZONE_IN_COMBAT); | |
- break; | |
- case AREA_LOCKSTATUS_INSTANCE_IS_FULL: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAX_PLAYERS); | |
- break; | |
- case AREA_LOCKSTATUS_QUEST_NOT_COMPLETED: | |
- if (at->target_mapId == 269) // Exception for Black Morass | |
- { | |
- SendAreaTriggerMessage(GetMangosString(LANG_TELEREQ_QUEST_BLACK_MORASS)); | |
- break; | |
- } | |
- else if (targetMapEntry->IsContinent()) // do not report anything for quest areatrigge | |
- { | |
- DEBUG_LOG("HandleAreaTriggerOpcode: LockAreaStatus %u, do not teleport, no message sent (trigger %u)", lockStatus, Trigger_ID); | |
- break; | |
- } | |
- // No break here! | |
- case AREA_LOCKSTATUS_MISSING_ITEM: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, player->GetDifficulty(targetMapEntry->IsRaid())); | |
- break; | |
- case AREA_LOCKSTATUS_MISSING_DIFFICULTY: | |
- { | |
- Difficulty difficulty = player->GetDifficulty(targetMapEntry->IsRaid()); | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, difficulty > RAID_DIFFICULTY_10MAN_HEROIC ? RAID_DIFFICULTY_10MAN_HEROIC : difficulty); | |
- break; | |
- } | |
- case AREA_LOCKSTATUS_INSUFFICIENT_EXPANSION: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_INSUF_EXPAN_LVL, miscRequirement); | |
- break; | |
- case AREA_LOCKSTATUS_NOT_ALLOWED: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAP_NOT_ALLOWED); | |
- break; | |
- case AREA_LOCKSTATUS_RAID_LOCKED: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_NEED_GROUP); | |
- break; | |
- case AREA_LOCKSTATUS_UNKNOWN_ERROR: | |
- player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ERROR); | |
- break; | |
- default: | |
- sLog.outError("HandleAreaTriggerOpcode: unhandled LockAreaStatus %u, when %s attempts to use area-trigger %u", lockStatus, player->GetGuidStr().c_str(), Trigger_ID); | |
- break; | |
- } | |
+ // teleport player (trigger requirement will be checked on TeleportTo) | |
+ player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT); | |
} | |
void WorldSession::HandleUpdateAccountData(WorldPacket& recv_data) | |
diff --git a/src/game/Player.cpp b/src/game/Player.cpp | |
index 3e8b4cb..9d89f17 100644 | |
--- a/src/game/Player.cpp | |
+++ b/src/game/Player.cpp | |
@@ -1641,23 +1641,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati | |
if (!InBattleGround() && mEntry->IsBattleGroundOrArena()) | |
return false; | |
- // client without expansion support | |
- if (GetSession()->Expansion() < mEntry->Expansion()) | |
- { | |
- DEBUG_LOG("Player %s using client without required expansion tried teleport to non accessible map %u", GetName(), mapid); | |
- | |
- if (GetTransport()) | |
- RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) | |
- | |
- SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion()); | |
- | |
- return false; // normal client can't teleport to this map... | |
- } | |
- else | |
- { | |
- DEBUG_LOG("Player %s is being teleported to map %u", GetName(), mapid); | |
- } | |
- | |
if (Group* grp = GetGroup()) | |
grp->SetPlayerMap(GetObjectGuid(), mapid); | |
@@ -1728,9 +1711,13 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati | |
// check if we can enter before stopping combat / removing pet / totems / interrupting spells | |
// 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 (!sMapMgr.CanPlayerEnter(mapid, this)) | |
+ uint32 miscRequirement = 0; | |
+ AreaLockStatus lockStatus = GetAreaLockStatus(mapid, this->GetDifficulty(mEntry->IsRaid()), miscRequirement); | |
+ if (lockStatus != AREA_LOCKSTATUS_OK) | |
+ { | |
+ SendTransferAbortedByLockStatus(mEntry, lockStatus, miscRequirement); | |
return false; | |
+ } | |
// If the map is not created, assume it is possible to enter it. | |
// It will be created in the WorldPortAck. | |
@@ -20416,20 +20403,70 @@ void Player::SendUpdateToOutOfRangeGroupMembers() | |
pet->ResetAuraUpdateMask(); | |
} | |
-void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) | |
+void Player::SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockStatus lockStatus, uint32 miscRequirement) | |
{ | |
- WorldPacket data(SMSG_TRANSFER_ABORTED, 4 + 2); | |
- data << uint32(mapid); | |
- data << uint8(reason); // transfer abort reason | |
- switch (reason) | |
+ if (!mapEntry) | |
+ return; | |
+ | |
+ switch (lockStatus) | |
{ | |
- case TRANSFER_ABORT_INSUF_EXPAN_LVL: | |
- case TRANSFER_ABORT_DIFFICULTY: | |
- case TRANSFER_ABORT_UNIQUE_MESSAGE: | |
- data << uint8(arg); | |
+ case AREA_LOCKSTATUS_TOO_LOW_LEVEL: | |
+ GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_MINREQUIRED), miscRequirement); | |
+ break; | |
+ case AREA_LOCKSTATUS_ZONE_IN_COMBAT: | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_ZONE_IN_COMBAT); | |
+ break; | |
+ case AREA_LOCKSTATUS_INSTANCE_IS_FULL: | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_MAX_PLAYERS); | |
+ break; | |
+ case AREA_LOCKSTATUS_QUEST_NOT_COMPLETED: | |
+ if (mapEntry->MapID == 269) // Exception for Black Morass | |
+ { | |
+ GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_TELEREQ_QUEST_BLACK_MORASS)); | |
break; | |
+ } | |
+ else if (mapEntry->IsContinent()) // do not report anything for quest areatrigge | |
+ { | |
+ DEBUG_LOG("SendTransferAbortedByLockStatus: LockAreaStatus %u, do not teleport, no message sent (mapId %u)", lockStatus, mapEntry->MapID); | |
+ break; | |
+ } | |
+ // No break here! | |
+ case AREA_LOCKSTATUS_MISSING_ITEM: | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_DIFFICULTY, GetDifficulty(mapEntry->IsRaid())); | |
+ break; | |
+ case AREA_LOCKSTATUS_MISSING_DIFFICULTY: | |
+ { | |
+ Difficulty difficulty = GetDifficulty(mapEntry->IsRaid()); | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_DIFFICULTY, difficulty > RAID_DIFFICULTY_10MAN_HEROIC ? RAID_DIFFICULTY_10MAN_HEROIC : difficulty); | |
+ break; | |
+ } | |
+ case AREA_LOCKSTATUS_INSUFFICIENT_EXPANSION: | |
+ if (GetTransport()) | |
+ RepopAtGraveyard(); | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_INSUF_EXPAN_LVL, miscRequirement); | |
+ break; | |
+ case AREA_LOCKSTATUS_NOT_ALLOWED: | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_MAP_NOT_ALLOWED); | |
+ break; | |
+ case AREA_LOCKSTATUS_RAID_LOCKED: | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_NEED_GROUP); | |
+ break; | |
+ case AREA_LOCKSTATUS_UNKNOWN_ERROR: | |
+ GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_ERROR); | |
+ break; | |
+ default: | |
+ if (lockStatus!=AREA_LOCKSTATUS_OK) | |
+ sLog.outError("SendTransfertAbortedByLockstatus: unhandled LockAreaStatus %u, when %s attempts to enter in map %u", lockStatus, GetGuidStr().c_str(), mapEntry->MapID); | |
+ break; | |
} | |
- GetSession()->SendPacket(&data); | |
+} | |
+ | |
+void Player::SendTransferAbortedByLockStatus(uint32 mapId, AreaLockStatus lockStatus, uint32 miscRequirement) | |
+{ | |
+ MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); | |
+ if (!mapEntry) | |
+ return; | |
+ SendTransferAbortedByLockStatus(mapEntry, lockStatus, miscRequirement); | |
} | |
void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time) | |
diff --git a/src/game/Player.h b/src/game/Player.h | |
index 8bb267e..3532cd0 100644 | |
--- a/src/game/Player.h | |
+++ b/src/game/Player.h | |
@@ -1047,7 +1047,8 @@ class MANGOS_DLL_SPEC Player : public Unit | |
void SendInitialPacketsBeforeAddToMap(); | |
void SendInitialPacketsAfterAddToMap(); | |
- void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0); | |
+ void SendTransferAbortedByLockStatus(uint32 mapId, AreaLockStatus lockStatus, uint32 miscRequirement = 0); | |
+ void SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockStatus lockStatus, uint32 miscRequirement = 0); | |
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time); | |
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask); | |
diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp | |
index 610637b..b50e8ce 100644 | |
--- a/src/game/WorldSession.cpp | |
+++ b/src/game/WorldSession.cpp | |
@@ -792,6 +792,23 @@ void WorldSession::SaveTutorialsData() | |
m_tutorialState = TUTORIALDATA_UNCHANGED; | |
} | |
+// Send chat information about aborted transfer (mostly used by Player::SendTransferAbortedByLockstatus()) | |
+void WorldSession::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) | |
+{ | |
+ WorldPacket data(SMSG_TRANSFER_ABORTED, 4 + 2); | |
+ data << uint32(mapid); | |
+ data << uint8(reason); // transfer abort reason | |
+ switch (reason) | |
+ { | |
+ case TRANSFER_ABORT_INSUF_EXPAN_LVL: | |
+ case TRANSFER_ABORT_DIFFICULTY: | |
+ case TRANSFER_ABORT_UNIQUE_MESSAGE: | |
+ data << uint8(arg); | |
+ break; | |
+ } | |
+ SendPacket(&data); | |
+} | |
+ | |
void WorldSession::ReadAddonsInfo(WorldPacket& data) | |
{ | |
if (data.rpos() + 4 > data.size()) | |
diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h | |
index 96586e0..800d140 100644 | |
--- a/src/game/WorldSession.h | |
+++ b/src/game/WorldSession.h | |
@@ -251,6 +251,7 @@ class MANGOS_DLL_SPEC WorldSession | |
void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res); | |
void SendGroupInvite(Player* player, bool alreadyInGroup = false); | |
void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3); | |
+ void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0); | |
void SendSetPhaseShift(uint32 phaseShift); | |
void SendQueryTimeResponse(); | |
void SendRedirectClient(std::string& ip, uint16 port); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment