[12207] Rewrite Checks required when entering a map

Expected way from now on is:
- Test if a map can be entered with Player::GetAreaTriggerLockStatus
- IF this doesn't return AREA_LOCKSTATUS_OK, and if wanted,
  send the fail-message with Player::SendTransferAbortedByLockStatus function.

Please feedback any hidden problems!

Signed-off-by: Schmoozerd <schmoozerd@scriptdev2.com>
This commit is contained in:
cyberium 2012-09-09 02:23:20 +02:00 committed by Antz
parent 824aa5429e
commit f432438665
11 changed files with 120 additions and 193 deletions

View file

@ -1687,7 +1687,7 @@ void Player::SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO)
SendDirectMessage(&data);
}
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options)
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options /*=0*/, AreaTrigger const* at /*=NULL*/)
{
orientation = NormalizeOrientation(orientation);
@ -1707,24 +1707,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!InBattleGround() && mEntry->IsBattleGroundOrArena())
return false;
// client without expansion support
if (GetSession()->Expansion() < mEntry->Expansion())
{
DEBUG_LOG("Player %s using client without required expansion tried teleport to non accessible map %u", GetName(), mapid);
if (GetTransport())
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion());
return false; // normal client can't teleport to this map...
}
else
{
DEBUG_LOG("Player %s is being teleported to map %u", GetName(), mapid);
}
if (Group* grp = GetGroup())
if (Group* grp = GetGroup()) // TODO: Verify that this is correct place
grp->SetPlayerMap(GetObjectGuid(), mapid);
// if we were on a transport, leave
@ -1746,8 +1729,20 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
DisableSpline();
if ((GetMapId() == mapid) && (!m_transport))
if ((GetMapId() == mapid) && (!m_transport)) // TODO the !m_transport might have unexpected effects when teleporting from transport to other place on same map
{
// If we are teleported by an areatrigger, check the requirements
if (at)
{
uint32 miscRequirement = 0;
AreaLockStatus lockStatus = GetAreaTriggerLockStatus(at, GetDifficulty(mEntry->IsRaid()), miscRequirement);
if (lockStatus != AREA_LOCKSTATUS_OK)
{
SendTransferAbortedByLockStatus(mEntry, lockStatus, miscRequirement);
return false;
}
}
// lets reset far teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportFar(false);
// setup delayed teleport flag
@ -1796,15 +1791,19 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// check if we can enter before stopping combat / removing pet / totems / interrupting spells
// 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))
uint32 miscRequirement = 0;
AreaLockStatus lockStatus = GetAreaTriggerLockStatus(at ? at : sObjectMgr.GetMapEntranceTrigger(mapid), GetDifficulty(mEntry->IsRaid()), miscRequirement);
if (lockStatus != AREA_LOCKSTATUS_OK)
{
SendTransferAbortedByLockStatus(mEntry, lockStatus, miscRequirement);
return false;
}
// If the map is not created, assume it is possible to enter it.
// It will be created in the WorldPortAck.
DungeonPersistentState* state = GetBoundInstanceSaveForSelfOrGroup(mapid);
Map* map = sMapMgr.FindMap(mapid, state ? state->GetInstanceId() : 0);
if (!map || map->CanEnter(this))
if (!map || map->CanEnter(this))
{
// lets reset near teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportNear(false);
@ -1925,7 +1924,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
SendSavedInstances();
}
}
else
else // !map->CanEnter(this)
return false;
}
return true;
@ -20181,14 +20180,66 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
pet->ResetAuraUpdateMask();
}
void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg)
void Player::SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockStatus lockStatus, uint32 miscRequirement)
{
WorldPacket data(SMSG_TRANSFER_ABORTED, 4 + 2);
data << uint32(mapid);
data << uint8(reason); // transfer abort reason
data << uint8(arg);
MANGOS_ASSERT(mapEntry);
GetSession()->SendPacket(&data);
DEBUG_LOG("SendTransferAbortedByLockStatus: Called for %s on map %u, LockAreaStatus %u, miscRequirement %u)", GetGuidStr().c_str(), mapEntry->MapID, lockStatus, miscRequirement);
switch (lockStatus)
{
case AREA_LOCKSTATUS_TOO_LOW_LEVEL:
GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_MINREQUIRED), miscRequirement);
break;
case AREA_LOCKSTATUS_ZONE_IN_COMBAT:
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_ZONE_IN_COMBAT);
break;
case AREA_LOCKSTATUS_INSTANCE_IS_FULL:
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_MAX_PLAYERS);
break;
case AREA_LOCKSTATUS_QUEST_NOT_COMPLETED:
if (mapEntry->MapID == 269) // Exception for Black Morass
{
GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_TELEREQ_QUEST_BLACK_MORASS));
break;
}
else if (mapEntry->IsContinent()) // do not report anything for quest areatrigge
{
DEBUG_LOG("SendTransferAbortedByLockStatus: LockAreaStatus %u, do not teleport, no message sent (mapId %u)", lockStatus, mapEntry->MapID);
break;
}
// No break here!
case AREA_LOCKSTATUS_MISSING_ITEM:
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_DIFFICULTY, GetDifficulty(mapEntry->IsRaid()));
break;
case AREA_LOCKSTATUS_MISSING_DIFFICULTY:
{
Difficulty difficulty = GetDifficulty(mapEntry->IsRaid());
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_DIFFICULTY, difficulty > RAID_DIFFICULTY_10MAN_HEROIC ? RAID_DIFFICULTY_10MAN_HEROIC : difficulty);
break;
}
case AREA_LOCKSTATUS_INSUFFICIENT_EXPANSION:
if (GetTransport())
RepopAtGraveyard();
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_INSUF_EXPAN_LVL, miscRequirement);
break;
case AREA_LOCKSTATUS_NOT_ALLOWED:
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_MAP_NOT_ALLOWED);
break;
case AREA_LOCKSTATUS_RAID_LOCKED:
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_NEED_GROUP);
break;
case AREA_LOCKSTATUS_UNKNOWN_ERROR:
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_ERROR);
break;
case AREA_LOCKSTATUS_OK:
sLog.outError("SendTransferAbortedByLockStatus: LockAreaStatus AREA_LOCKSTATUS_OK received for %s (mapId %u)", GetGuidStr().c_str(), mapEntry->MapID);
MANGOS_ASSERT(false);
break;
default:
sLog.outError("SendTransfertAbortedByLockstatus: unhandled LockAreaStatus %u, when %s attempts to enter in map %u", lockStatus, GetGuidStr().c_str(), mapEntry->MapID);
break;
}
}
void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time)
@ -23626,8 +23677,3 @@ AreaLockStatus Player::GetAreaTriggerLockStatus(AreaTrigger const* at, Difficult
return AREA_LOCKSTATUS_OK;
};
AreaLockStatus Player::GetAreaLockStatus(uint32 mapId, Difficulty difficulty, uint32& miscRequirement)
{
return GetAreaTriggerLockStatus(sObjectMgr.GetMapEntranceTrigger(mapId), difficulty, miscRequirement);
};