aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2015-12-31 19:51:07 +0100
committerTreeston <treeston.mmoc@gmail.com>2015-12-31 19:51:07 +0100
commiteb3dc8a4f064d89b78248a511bcf67f805ea3314 (patch)
treeb22127216ef2ecb748ff817d0f293748bb263938 /src/server/game/Entities
parent082eeda7fef26928090d42d1632e0dce1dfe5ab0 (diff)
parent43fa7d48a5650c71f74098f3398cf5aca89c3837 (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.cpp103
-rw-r--r--src/server/game/Entities/Player/Player.h2
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);