mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-27 20:32:21 +01:00
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.
This commit is contained in:
@@ -97,12 +97,12 @@ Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const
|
||||
return map;
|
||||
}
|
||||
|
||||
Map* MapManager::CreateMap(uint32 id, Player* player)
|
||||
Map* MapManager::CreateMap(uint32 id, Player* player, uint32 loginInstanceId)
|
||||
{
|
||||
Map* m = CreateBaseMap(id);
|
||||
|
||||
if (m && m->Instanceable())
|
||||
m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, player);
|
||||
m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, player, loginInstanceId);
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -119,48 +119,36 @@ Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const
|
||||
return ((MapInstanced*)map)->FindInstanceMap(instanceId);
|
||||
}
|
||||
|
||||
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
|
||||
Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck)
|
||||
{
|
||||
MapEntry const* entry = sMapStore.LookupEntry(mapid);
|
||||
if (!entry)
|
||||
return false;
|
||||
return Map::CANNOT_ENTER_NO_ENTRY;
|
||||
|
||||
if (!entry->IsDungeon())
|
||||
return true;
|
||||
return Map::CAN_ENTER;
|
||||
|
||||
InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapid);
|
||||
if (!instance)
|
||||
return false;
|
||||
return Map::CANNOT_ENTER_UNINSTANCED_DUNGEON;
|
||||
|
||||
Difficulty targetDifficulty, requestedDifficulty;
|
||||
targetDifficulty = requestedDifficulty = player->GetDifficulty(entry->IsRaid());
|
||||
// Get the highest available difficulty if current setting is higher than the instance allows
|
||||
MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(entry->MapID, targetDifficulty);
|
||||
if (!mapDiff)
|
||||
{
|
||||
player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, requestedDifficulty);
|
||||
return false;
|
||||
}
|
||||
return Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE;
|
||||
|
||||
//Bypass checks for GMs
|
||||
if (player->IsGameMaster())
|
||||
return true;
|
||||
return Map::CAN_ENTER;
|
||||
|
||||
char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
|
||||
|
||||
Group* group = player->GetGroup();
|
||||
if (entry->IsRaid())
|
||||
{
|
||||
// can only enter in a raid group
|
||||
if (entry->IsRaid()) // can only enter in a raid group
|
||||
if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID))
|
||||
{
|
||||
// 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(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName);
|
||||
TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return Map::CANNOT_ENTER_NOT_IN_RAID;
|
||||
|
||||
if (!player->IsAlive())
|
||||
{
|
||||
@@ -178,12 +166,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
|
||||
} while (corpseMap);
|
||||
|
||||
if (!corpseMap)
|
||||
{
|
||||
WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName);
|
||||
return false;
|
||||
}
|
||||
return Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE;
|
||||
|
||||
TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName);
|
||||
}
|
||||
@@ -192,23 +175,13 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
|
||||
}
|
||||
|
||||
//Get instance where player's group is bound & its map
|
||||
if (group)
|
||||
if (!loginCheck && group)
|
||||
{
|
||||
InstanceGroupBind* boundInstance = group->GetBoundInstance(entry);
|
||||
if (boundInstance && boundInstance->save)
|
||||
if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId()))
|
||||
if (!loginCheck && !boundMap->CanEnter(player))
|
||||
return false;
|
||||
/*
|
||||
This check has to be moved to InstanceMap::CanEnter()
|
||||
// Player permanently bounded to different instance than groups one
|
||||
InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficulty(entry->IsRaid()));
|
||||
if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save &&
|
||||
boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId())
|
||||
{
|
||||
/// @todo send some kind of error message to the player
|
||||
return false;
|
||||
}*/
|
||||
if (Map::EnterState denyReason = boundMap->CannotEnter(player))
|
||||
return denyReason;
|
||||
}
|
||||
|
||||
// players are only allowed to enter 5 instances per hour
|
||||
@@ -220,14 +193,14 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
|
||||
|
||||
// instanceId can never be 0 - will not be found
|
||||
if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead())
|
||||
{
|
||||
player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES);
|
||||
return false;
|
||||
}
|
||||
return Map::CANNOT_ENTER_TOO_MANY_INSTANCES;
|
||||
}
|
||||
|
||||
//Other requirements
|
||||
return player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true);
|
||||
if (player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true))
|
||||
return Map::CAN_ENTER;
|
||||
else
|
||||
return Map::CANNOT_ENTER_UNSPECIFIED_REASON;
|
||||
}
|
||||
|
||||
void MapManager::Update(uint32 diff)
|
||||
|
||||
Reference in New Issue
Block a user