diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2015-12-31 19:51:07 +0100 |
|---|---|---|
| committer | Treeston <treeston.mmoc@gmail.com> | 2015-12-31 19:51:07 +0100 |
| commit | eb3dc8a4f064d89b78248a511bcf67f805ea3314 (patch) | |
| tree | b22127216ef2ecb748ff817d0f293748bb263938 /src/server/game/Entities | |
| parent | 082eeda7fef26928090d42d1632e0dce1dfe5ab0 (diff) | |
| parent | 43fa7d48a5650c71f74098f3398cf5aca89c3837 (diff) | |
Merge pull request #16110 from Treeston/3.3.5-instancerevive
Game/Maps: Clean up instance zone-in handling
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 103 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 2 |
2 files changed, 80 insertions, 25 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ceab7d06c96..df30a581d40 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1913,7 +1913,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 (!sMapMgr->CanPlayerEnter(mapid, this, false)) + if (sMapMgr->PlayerCannotEnter(mapid, this, false)) return false; //I think this always returns true. Correct me if I am wrong. @@ -17096,7 +17096,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) // NOW player must have valid map // load the player's map here if it's not already loaded - Map* map = sMapMgr->CreateMap(mapId, this); + Map* map = sMapMgr->CreateMap(mapId, this, instanceId); AreaTrigger const* areaTrigger = NULL; bool check = false; @@ -17107,8 +17107,28 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) } else if (map->IsDungeon()) // if map is dungeon... { - if (!((InstanceMap*)map)->CanEnter(this) || !CheckInstanceLoginValid(map)) // ... and can't enter map, then look for entry point. + if (Map::EnterState denyReason = ((InstanceMap*)map)->CannotEnter(this)) // ... and can't enter map, then look for entry point. { + switch (denyReason) + { + case Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_DIFFICULTY, map->GetDifficulty()); + break; + case Map::CANNOT_ENTER_INSTANCE_BIND_MISMATCH: + ChatHandler(GetSession()).PSendSysMessage(GetSession()->GetTrinityString(LANG_INSTANCE_BIND_MISMATCH), map->GetMapName()); + break; + case Map::CANNOT_ENTER_TOO_MANY_INSTANCES: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_TOO_MANY_INSTANCES); + break; + case Map::CANNOT_ENTER_MAX_PLAYERS: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_MAX_PLAYERS); + break; + case Map::CANNOT_ENTER_ZONE_IN_COMBAT: + SendTransferAborted(map->GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); + break; + default: + break; + } areaTrigger = sObjectMgr->GetGoBackTrigger(mapId); check = true; } @@ -17155,6 +17175,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) SetMap(map); StoreRaidMapDifficulty(); + // now that map position is determined, check instance validity + if (!CheckInstanceValidity(true) && !IsInstanceLoginGameMasterException()) + m_InstanceValid = false; + // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] // this must help in case next save after mass player load after server startup m_nextSave = urand(m_nextSave/2, m_nextSave*3/2); @@ -18667,37 +18691,68 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report return true; } -bool Player::CheckInstanceLoginValid(Map* map) +bool Player::IsInstanceLoginGameMasterException() const { - if (!map->IsDungeon() || IsGameMaster()) - return true; - - if (map->IsRaid()) + if (CanBeGameMaster()) { - // cannot be in raid instance without a group - if (!GetGroup()) - return IsInstanceLoginGameMasterException(); + ChatHandler(GetSession()).SendSysMessage(LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION); + return true; } else - { - // cannot be in normal instance without a group and more players than 1 in instance - if (!GetGroup() && map->GetPlayersCountExceptGMs() > 1) - return IsInstanceLoginGameMasterException(); - } - - // do checks for satisfy accessreqs, instance full, encounter in progress (raid), perm bind group != perm bind player - return sMapMgr->CanPlayerEnter(map->GetId(), this, true) || IsInstanceLoginGameMasterException(); + return false; } -bool Player::IsInstanceLoginGameMasterException() const +bool Player::CheckInstanceValidity(bool /*isLogin*/) { - if (CanBeGameMaster()) - { - ChatHandler(GetSession()).SendSysMessage(LANG_INSTANCE_LOGIN_GAMEMASTER_EXCEPTION); + // game masters' instances are always valid + if (IsGameMaster()) return true; + + // non-instances are always valid + Map* map = GetMap(); + if (!map || !map->IsDungeon()) + return true; + + // raid instances require the player to be in a raid group to be valid + if (map->IsRaid() && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)) + if (!GetGroup() || !GetGroup()->isRaidGroup()) + return false; + + if (Group* group = GetGroup()) + { + // check if player's group is bound to this instance + InstanceGroupBind* bind = group->GetBoundInstance(map->GetDifficulty(), map->GetId()); + if (!bind || !bind->save || bind->save->GetInstanceId() != map->GetInstanceId()) + return false; + + Map::PlayerList const& players = map->GetPlayers(); + if (!players.isEmpty()) + for (Map::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it) + { + if (Player* otherPlayer = it->GetSource()) + { + if (otherPlayer->IsGameMaster()) + continue; + if (!otherPlayer->m_InstanceValid) // ignore players that currently have a homebind timer active + continue; + if (group != otherPlayer->GetGroup()) + return false; + } + } } else - return false; + { + // instance is invalid if we are not grouped and there are other players + if (map->GetPlayersCountExceptGMs() > 1) + return false; + + // check if the player is bound to this instance + InstancePlayerBind* bind = GetBoundInstance(map->GetId(), map->GetDifficulty()); + if (!bind || !bind->save || bind->save->GetInstanceId() != map->GetInstanceId()) + return false; + } + + return true; } bool Player::CheckInstanceCount(uint32 instanceId) const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 26944de9770..685c8115074 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2118,7 +2118,7 @@ class Player : public Unit, public GridObject<Player> void SendSavedInstances(); static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader); bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false); - bool CheckInstanceLoginValid(Map* map); + bool CheckInstanceValidity(bool /*isLogin*/); bool CheckInstanceCount(uint32 instanceId) const; void AddInstanceEnterTime(uint32 instanceId, time_t enterTime); |
