mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 19:37:02 +00:00
[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:
parent
824aa5429e
commit
f432438665
11 changed files with 120 additions and 193 deletions
|
|
@ -51,7 +51,6 @@ class MANGOS_DLL_SPEC InstanceData
|
||||||
// Called every map update
|
// Called every map update
|
||||||
virtual void Update(uint32 /*diff*/) {}
|
virtual void Update(uint32 /*diff*/) {}
|
||||||
|
|
||||||
// Used by the map's CanEnter function.
|
|
||||||
// This is to prevent players from entering during boss encounters.
|
// This is to prevent players from entering during boss encounters.
|
||||||
virtual bool IsEncounterInProgress() const { return false; };
|
virtual bool IsEncounterInProgress() const { return false; };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1252,37 +1252,6 @@ void DungeonMap::InitVisibilityDistance()
|
||||||
m_VisibleDistance = World::GetMaxVisibleDistanceInInstances();
|
m_VisibleDistance = World::GetMaxVisibleDistanceInInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Do map specific checks to see if the player can enter
|
|
||||||
*/
|
|
||||||
bool DungeonMap::CanEnter(Player* player)
|
|
||||||
{
|
|
||||||
if (player->GetMapRef().getTarget() == this)
|
|
||||||
{
|
|
||||||
sLog.outError("DungeonMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
|
|
||||||
MANGOS_ASSERT(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cannot enter if the instance is full (player cap), GMs don't count
|
|
||||||
uint32 maxPlayers = GetMaxPlayers();
|
|
||||||
if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers)
|
|
||||||
{
|
|
||||||
DETAIL_LOG("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
|
|
||||||
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cannot enter while an encounter in the instance is in progress
|
|
||||||
if (!player->isGameMaster() && GetInstanceData() && GetInstanceData()->IsEncounterInProgress() && player->GetMapId() != GetId())
|
|
||||||
{
|
|
||||||
player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Map::CanEnter(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do map specific checks and add the player to the map if successful.
|
Do map specific checks and add the player to the map if successful.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1557,19 +1526,14 @@ void BattleGroundMap::InitVisibilityDistance()
|
||||||
|
|
||||||
bool BattleGroundMap::CanEnter(Player* player)
|
bool BattleGroundMap::CanEnter(Player* player)
|
||||||
{
|
{
|
||||||
if (player->GetMapRef().getTarget() == this)
|
if (!Map::CanEnter(player))
|
||||||
{
|
|
||||||
sLog.outError("BGMap::CanEnter - player %u already in map!", player->GetGUIDLow());
|
|
||||||
MANGOS_ASSERT(false);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (player->GetBattleGroundId() != GetInstanceId())
|
if (player->GetBattleGroundId() != GetInstanceId())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// player number limit is checked in bgmgr, no need to do it here
|
// player number limit is checked in bgmgr, no need to do it here
|
||||||
|
return true;
|
||||||
return Map::CanEnter(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BattleGroundMap::Add(Player* player)
|
bool BattleGroundMap::Add(Player* player)
|
||||||
|
|
@ -1611,6 +1575,18 @@ void BattleGroundMap::UnloadAll(bool pForce)
|
||||||
Map::UnloadAll(pForce);
|
Map::UnloadAll(pForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Map::CanEnter(Player* player)
|
||||||
|
{
|
||||||
|
if (player->GetMapRef().getTarget() == this)
|
||||||
|
{
|
||||||
|
sLog.outError("Map::CanEnter -%s already in map!", player->GetGuidStr().c_str());
|
||||||
|
MANGOS_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Put scripts in the execution queue
|
/// Put scripts in the execution queue
|
||||||
bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target)
|
bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
|
||||||
bool CheckGridIntegrity(Creature* c, bool moved) const;
|
bool CheckGridIntegrity(Creature* c, bool moved) const;
|
||||||
|
|
||||||
uint32 GetInstanceId() const { return i_InstanceId; }
|
uint32 GetInstanceId() const { return i_InstanceId; }
|
||||||
virtual bool CanEnter(Player* /*player*/) { return true; }
|
virtual bool CanEnter(Player* player);
|
||||||
const char* GetMapName() const;
|
const char* GetMapName() const;
|
||||||
|
|
||||||
// have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap
|
// have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap
|
||||||
|
|
@ -384,7 +384,6 @@ class MANGOS_DLL_SPEC DungeonMap : public Map
|
||||||
bool Reset(InstanceResetMethod method);
|
bool Reset(InstanceResetMethod method);
|
||||||
void PermBindAllPlayers(Player* player);
|
void PermBindAllPlayers(Player* player);
|
||||||
void UnloadAll(bool pForce) override;
|
void UnloadAll(bool pForce) override;
|
||||||
bool CanEnter(Player* player) override;
|
|
||||||
void SendResetWarnings(uint32 timeLeft) const;
|
void SendResetWarnings(uint32 timeLeft) const;
|
||||||
void SetResetSchedule(bool on);
|
void SetResetSchedule(bool on);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,62 +149,6 @@ Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
checks that do not require a map to be created
|
|
||||||
will send transfer error messages on fail
|
|
||||||
*/
|
|
||||||
bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
|
|
||||||
{
|
|
||||||
const MapEntry* entry = sMapStore.LookupEntry(mapid);
|
|
||||||
if (!entry)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
|
|
||||||
|
|
||||||
if (entry->IsDungeon())
|
|
||||||
{
|
|
||||||
if (entry->IsRaid())
|
|
||||||
{
|
|
||||||
// GMs can avoid raid limitations
|
|
||||||
if (!player->isGameMaster() && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_RAID))
|
|
||||||
{
|
|
||||||
// can only enter in a raid group
|
|
||||||
Group* group = player->GetGroup();
|
|
||||||
if (!group || !group->isRaidGroup())
|
|
||||||
{
|
|
||||||
// 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("You must be in a raid group to enter %s instance", mapName);
|
|
||||||
DEBUG_LOG("MAP: Player '%s' must be in a raid group to enter instance of '%s'", player->GetName(), mapName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The player has a heroic mode and tries to enter into instance which has no a heroic mode
|
|
||||||
MapDifficultyEntry const* mapDiff = GetMapDifficultyData(entry->MapID, player->GetDifficulty(entry->map_type == MAP_RAID));
|
|
||||||
if (!mapDiff)
|
|
||||||
{
|
|
||||||
bool isRegularTargetMap = player->GetDifficulty(entry->IsRaid()) == REGULAR_DIFFICULTY;
|
|
||||||
|
|
||||||
// Send aborted message
|
|
||||||
// FIX ME: what about absent normal/heroic mode with specific players limit...
|
|
||||||
player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, isRegularTargetMap ? DUNGEON_DIFFICULTY_NORMAL : DUNGEON_DIFFICULTY_HEROIC);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move this to a map dependent location
|
|
||||||
/*if(i_data && i_data->IsEncounterInProgress())
|
|
||||||
{
|
|
||||||
DEBUG_LOG("MAP: Player '%s' can't enter instance '%s' while an encounter is in progress.", player->GetName(), GetMapName());
|
|
||||||
player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT);
|
|
||||||
return(false);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId)
|
void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId)
|
||||||
{
|
{
|
||||||
Guard _guard(*this);
|
Guard _guard(*this);
|
||||||
|
|
@ -223,8 +167,7 @@ void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void MapManager::Update(uint32 diff)
|
||||||
MapManager::Update(uint32 diff)
|
|
||||||
{
|
{
|
||||||
i_timer.Update(diff);
|
i_timer.Update(diff);
|
||||||
if (!i_timer.Passed())
|
if (!i_timer.Passed())
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,6 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
|
||||||
typedef std::map<uint32, TransportSet> TransportMap;
|
typedef std::map<uint32, TransportSet> TransportMap;
|
||||||
TransportMap m_TransportsByMap;
|
TransportMap m_TransportsByMap;
|
||||||
|
|
||||||
bool CanPlayerEnter(uint32 mapid, Player* player);
|
|
||||||
void InitializeVisibilityDistanceInfo();
|
void InitializeVisibilityDistanceInfo();
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
|
|
|
||||||
|
|
@ -799,60 +799,8 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data)
|
||||||
player->SpawnCorpseBones();
|
player->SpawnCorpseBones();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check trigger requirements
|
// teleport player (trigger requirement will be checked on TeleportTo)
|
||||||
uint32 miscRequirement = 0;
|
player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT, at);
|
||||||
AreaLockStatus lockStatus = player->GetAreaTriggerLockStatus(at, player->GetDifficulty(targetMapEntry->IsRaid()), miscRequirement);
|
|
||||||
switch (lockStatus)
|
|
||||||
{
|
|
||||||
case AREA_LOCKSTATUS_OK:
|
|
||||||
player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_TOO_LOW_LEVEL:
|
|
||||||
SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED), miscRequirement);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_ZONE_IN_COMBAT:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ZONE_IN_COMBAT);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_INSTANCE_IS_FULL:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAX_PLAYERS);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_QUEST_NOT_COMPLETED:
|
|
||||||
if (at->target_mapId == 269) // Exception for Black Morass
|
|
||||||
{
|
|
||||||
SendAreaTriggerMessage(GetMangosString(LANG_TELEREQ_QUEST_BLACK_MORASS));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (targetMapEntry->IsContinent()) // do not report anything for quest areatrigge
|
|
||||||
{
|
|
||||||
DEBUG_LOG("HandleAreaTriggerOpcode: LockAreaStatus %u, do not teleport, no message sent (trigger %u)", lockStatus, Trigger_ID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// No break here!
|
|
||||||
case AREA_LOCKSTATUS_MISSING_ITEM:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, player->GetDifficulty(targetMapEntry->IsRaid()));
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_MISSING_DIFFICULTY:
|
|
||||||
{
|
|
||||||
Difficulty difficulty = player->GetDifficulty(targetMapEntry->IsRaid());
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, difficulty > RAID_DIFFICULTY_10MAN_HEROIC ? RAID_DIFFICULTY_10MAN_HEROIC : difficulty);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AREA_LOCKSTATUS_INSUFFICIENT_EXPANSION:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_INSUF_EXPAN_LVL, miscRequirement);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_NOT_ALLOWED:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAP_NOT_ALLOWED);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_RAID_LOCKED:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_NEED_GROUP);
|
|
||||||
break;
|
|
||||||
case AREA_LOCKSTATUS_UNKNOWN_ERROR:
|
|
||||||
player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ERROR);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sLog.outError("HandleAreaTriggerOpcode: unhandled LockAreaStatus %u, when %s attempts to use area-trigger %u", lockStatus, player->GetGuidStr().c_str(), Trigger_ID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleUpdateAccountData(WorldPacket& recv_data)
|
void WorldSession::HandleUpdateAccountData(WorldPacket& recv_data)
|
||||||
|
|
|
||||||
|
|
@ -1687,7 +1687,7 @@ void Player::SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO)
|
||||||
SendDirectMessage(&data);
|
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);
|
orientation = NormalizeOrientation(orientation);
|
||||||
|
|
||||||
|
|
@ -1707,24 +1707,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||||
if (!InBattleGround() && mEntry->IsBattleGroundOrArena())
|
if (!InBattleGround() && mEntry->IsBattleGroundOrArena())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// client without expansion support
|
if (Group* grp = GetGroup()) // TODO: Verify that this is correct place
|
||||||
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())
|
|
||||||
grp->SetPlayerMap(GetObjectGuid(), mapid);
|
grp->SetPlayerMap(GetObjectGuid(), mapid);
|
||||||
|
|
||||||
// if we were on a transport, leave
|
// 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);
|
m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
|
||||||
DisableSpline();
|
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
|
// lets reset far teleport flag if it wasn't reset during chained teleports
|
||||||
SetSemaphoreTeleportFar(false);
|
SetSemaphoreTeleportFar(false);
|
||||||
// setup delayed teleport flag
|
// 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 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
|
// 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
|
uint32 miscRequirement = 0;
|
||||||
if (!sMapMgr.CanPlayerEnter(mapid, this))
|
AreaLockStatus lockStatus = GetAreaTriggerLockStatus(at ? at : sObjectMgr.GetMapEntranceTrigger(mapid), GetDifficulty(mEntry->IsRaid()), miscRequirement);
|
||||||
|
if (lockStatus != AREA_LOCKSTATUS_OK)
|
||||||
|
{
|
||||||
|
SendTransferAbortedByLockStatus(mEntry, lockStatus, miscRequirement);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If the map is not created, assume it is possible to enter it.
|
// If the map is not created, assume it is possible to enter it.
|
||||||
// It will be created in the WorldPortAck.
|
// It will be created in the WorldPortAck.
|
||||||
DungeonPersistentState* state = GetBoundInstanceSaveForSelfOrGroup(mapid);
|
DungeonPersistentState* state = GetBoundInstanceSaveForSelfOrGroup(mapid);
|
||||||
Map* map = sMapMgr.FindMap(mapid, state ? state->GetInstanceId() : 0);
|
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
|
// lets reset near teleport flag if it wasn't reset during chained teleports
|
||||||
SetSemaphoreTeleportNear(false);
|
SetSemaphoreTeleportNear(false);
|
||||||
|
|
@ -1925,7 +1924,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||||
SendSavedInstances();
|
SendSavedInstances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // !map->CanEnter(this)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -20181,14 +20180,66 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
|
||||||
pet->ResetAuraUpdateMask();
|
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);
|
MANGOS_ASSERT(mapEntry);
|
||||||
data << uint32(mapid);
|
|
||||||
data << uint8(reason); // transfer abort reason
|
|
||||||
data << uint8(arg);
|
|
||||||
|
|
||||||
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)
|
void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time)
|
||||||
|
|
@ -23626,8 +23677,3 @@ AreaLockStatus Player::GetAreaTriggerLockStatus(AreaTrigger const* at, Difficult
|
||||||
|
|
||||||
return AREA_LOCKSTATUS_OK;
|
return AREA_LOCKSTATUS_OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
AreaLockStatus Player::GetAreaLockStatus(uint32 mapId, Difficulty difficulty, uint32& miscRequirement)
|
|
||||||
{
|
|
||||||
return GetAreaTriggerLockStatus(sObjectMgr.GetMapEntranceTrigger(mapId), difficulty, miscRequirement);
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -1057,7 +1057,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void RemoveFromWorld() override;
|
void RemoveFromWorld() override;
|
||||||
|
|
||||||
void SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO);
|
void SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO);
|
||||||
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0);
|
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0, AreaTrigger const* at = NULL);
|
||||||
|
|
||||||
bool TeleportTo(WorldLocation const& loc, uint32 options = 0)
|
bool TeleportTo(WorldLocation const& loc, uint32 options = 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1089,7 +1089,6 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
|
|
||||||
void SendInitialPacketsBeforeAddToMap();
|
void SendInitialPacketsBeforeAddToMap();
|
||||||
void SendInitialPacketsAfterAddToMap();
|
void SendInitialPacketsAfterAddToMap();
|
||||||
void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0);
|
|
||||||
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
|
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
|
||||||
|
|
||||||
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
|
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
|
||||||
|
|
@ -2318,8 +2317,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
static void ConvertInstancesToGroup(Player* player, Group* group = NULL, ObjectGuid player_guid = ObjectGuid());
|
static void ConvertInstancesToGroup(Player* player, Group* group = NULL, ObjectGuid player_guid = ObjectGuid());
|
||||||
DungeonPersistentState* GetBoundInstanceSaveForSelfOrGroup(uint32 mapid);
|
DungeonPersistentState* GetBoundInstanceSaveForSelfOrGroup(uint32 mapid);
|
||||||
|
|
||||||
AreaLockStatus GetAreaLockStatus(uint32 mapId, Difficulty difficulty, uint32& miscRequirement);
|
|
||||||
AreaLockStatus GetAreaTriggerLockStatus(AreaTrigger const* at, Difficulty difficulty, uint32& miscRequirement);
|
AreaLockStatus GetAreaTriggerLockStatus(AreaTrigger const* at, Difficulty difficulty, uint32& miscRequirement);
|
||||||
|
void SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockStatus lockStatus, uint32 miscRequirement = 0);
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
/*** GROUP SYSTEM ***/
|
/*** GROUP SYSTEM ***/
|
||||||
|
|
|
||||||
|
|
@ -805,6 +805,23 @@ void WorldSession::LoadTutorialsData()
|
||||||
m_tutorialState = TUTORIALDATA_UNCHANGED;
|
m_tutorialState = TUTORIALDATA_UNCHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send chat information about aborted transfer (mostly used by Player::SendTransferAbortedByLockstatus())
|
||||||
|
void WorldSession::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg)
|
||||||
|
{
|
||||||
|
WorldPacket data(SMSG_TRANSFER_ABORTED, 4 + 2);
|
||||||
|
data << uint32(mapid);
|
||||||
|
data << uint8(reason); // transfer abort reason
|
||||||
|
switch (reason)
|
||||||
|
{
|
||||||
|
case TRANSFER_ABORT_INSUF_EXPAN_LVL:
|
||||||
|
case TRANSFER_ABORT_DIFFICULTY:
|
||||||
|
case TRANSFER_ABORT_UNIQUE_MESSAGE:
|
||||||
|
data << uint8(arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SendPacket(&data);
|
||||||
|
}
|
||||||
|
|
||||||
void WorldSession::SendTutorialsData()
|
void WorldSession::SendTutorialsData()
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_TUTORIAL_FLAGS, 4 * 8);
|
WorldPacket data(SMSG_TUTORIAL_FLAGS, 4 * 8);
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@ class MANGOS_DLL_SPEC WorldSession
|
||||||
void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res);
|
void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res);
|
||||||
void SendGroupInvite(Player* player, bool alreadyInGroup = false);
|
void SendGroupInvite(Player* player, bool alreadyInGroup = false);
|
||||||
void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3);
|
void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0);
|
||||||
void SendSetPhaseShift(uint32 phaseMask, uint16 mapId = 0);
|
void SendSetPhaseShift(uint32 phaseMask, uint16 mapId = 0);
|
||||||
void SendQueryTimeResponse();
|
void SendQueryTimeResponse();
|
||||||
void SendRedirectClient(std::string& ip, uint16 port);
|
void SendRedirectClient(std::string& ip, uint16 port);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "12206"
|
#define REVISION_NR "12207"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue