aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/CharacterHandler.cpp2
-rw-r--r--src/game/Group.cpp9
-rw-r--r--src/game/MapManager.cpp4
-rw-r--r--src/game/MapManager.h2
-rw-r--r--src/game/MiscHandler.cpp21
-rw-r--r--src/game/ObjectMgr.cpp21
-rw-r--r--src/game/Player.cpp27
-rw-r--r--src/game/Player.h1
8 files changed, 71 insertions, 16 deletions
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; }