diff options
author | treeston <treeston.mmoc@gmail.com> | 2015-12-27 18:03:03 +0100 |
---|---|---|
committer | treeston <treeston.mmoc@gmail.com> | 2015-12-31 01:02:07 +0100 |
commit | 43fa7d48a5650c71f74098f3398cf5aca89c3837 (patch) | |
tree | a6d808e4b447f9df2b1f1cfe0a19483d64fe87d5 /src/server/game/Maps/Map.cpp | |
parent | 812809a977e2ba2a53e55c3dfc74bbed9dd59b7a (diff) |
Game/Maps: Clean up instance handling.
- Rename Map::CanEnter to Map::CannotEnter. Return value changed from boolean (true means player can enter) to enum Map::EnterState (CAN_ENTER=0 means player can enter, any other value is a reason for deny).
- Move hack-y player error messages from within Map::CanEnter to the function calling CanEnter as appropriate (primarily WorldSession::HandleAreaTriggerOpcode).
- Modify WorldSession::HandleAreaTriggerOpcode to properly revive the player upon touching the portal leading to the instance they died in even if they are currently unable to zone in. Fixes and closes #15758.
- Modify Player::LoadFromDB to properly spawn players in the instance they logged off in if possible. Fixes and closes #15561.
- Modify permanent save behavior to be blizzlike: Players can always enter an instance they are saved to (assuming there are no map constraints against it), but get a homebind timer if the instance is already in use.
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r-- | src/server/game/Maps/Map.cpp | 60 |
1 files changed, 18 insertions, 42 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 6fbef752228..67abf4af682 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2947,62 +2947,38 @@ void InstanceMap::InitVisibilityDistance() /* Do map specific checks to see if the player can enter */ -bool InstanceMap::CanEnter(Player* player) +Map::EnterState InstanceMap::CannotEnter(Player* player) { if (player->GetMapRef().getTarget() == this) { - TC_LOG_ERROR("maps", "InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUID().GetCounter(), GetId(), GetInstanceId(), GetSpawnMode()); + TC_LOG_ERROR("maps", "InstanceMap::CannotEnter - player %s(%u) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUID().GetCounter(), GetId(), GetInstanceId(), GetSpawnMode()); ABORT(); - return false; + return CANNOT_ENTER_ALREADY_IN_MAP; } // allow GM's to enter if (player->IsGameMaster()) - return Map::CanEnter(player); + return Map::CannotEnter(player); // cannot enter if the instance is full (player cap), GMs don't count uint32 maxPlayers = GetMaxPlayers(); if (GetPlayersCountExceptGMs() >= maxPlayers) { TC_LOG_WARN("maps", "MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName().c_str()); - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; + return CANNOT_ENTER_MAX_PLAYERS; } - // cannot enter while an encounter is in progress - // allow if just loading + // cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted) if (!player->IsLoading() && IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress()) - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); - return false; - } + return CANNOT_ENTER_ZONE_IN_COMBAT; - // cannot enter if instance is in use by another party/soloer that have a - // permanent save in the same instance id + // cannot enter if player is permanent saved to a different instance id + if (InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficulty())) + if (playerBind->perm && playerBind->save) + if (playerBind->save->GetInstanceId() != GetInstanceId()) + return CANNOT_ENTER_INSTANCE_BIND_MISMATCH; - PlayerList const &playerList = GetPlayers(); - - if (!playerList.isEmpty()) - for (PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i) - if (Player* iPlayer = i->GetSource()) - { - if (iPlayer->IsGameMaster()) // bypass GMs - continue; - if (!player->GetGroup()) // player has not group and there is someone inside, deny entry - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; - } - // player inside instance has no group or his groups is different to entering player's one, deny entry - if (!iPlayer->GetGroup() || iPlayer->GetGroup() != player->GetGroup()) - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; - } - break; - } - - return Map::CanEnter(player); + return Map::CannotEnter(player); } /* @@ -3339,21 +3315,21 @@ void BattlegroundMap::InitVisibilityDistance() m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas(); } -bool BattlegroundMap::CanEnter(Player* player) +Map::EnterState BattlegroundMap::CannotEnter(Player* player) { if (player->GetMapRef().getTarget() == this) { - TC_LOG_ERROR("maps", "BGMap::CanEnter - player %u is already in map!", player->GetGUID().GetCounter()); + TC_LOG_ERROR("maps", "BGMap::CannotEnter - player %u is already in map!", player->GetGUID().GetCounter()); ABORT(); - return false; + return CANNOT_ENTER_ALREADY_IN_MAP; } if (player->GetBattlegroundId() != GetInstanceId()) - return false; + return CANNOT_ENTER_INSTANCE_BIND_MISMATCH; // player number limit is checked in bgmgr, no need to do it here - return Map::CanEnter(player); + return Map::CannotEnter(player); } bool BattlegroundMap::AddPlayerToMap(Player* player) |