[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

@ -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; };

View file

@ -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)
{ {

View file

@ -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);

View file

@ -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())

View file

@ -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 */

View file

@ -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)

View file

@ -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);
};

View file

@ -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 ***/

View file

@ -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);

View file

@ -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);

View file

@ -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__