mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-29 05:11:55 +01:00
Core/Player: Delay resurrection on release for unreachable maps until teleport has completed. Closes #21481.
This commit is contained in:
@@ -43,14 +43,15 @@ void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recvData*/)
|
||||
|
||||
void WorldSession::HandleMoveWorldportAck()
|
||||
{
|
||||
Player* player = GetPlayer();
|
||||
// ignore unexpected far teleports
|
||||
if (!GetPlayer()->IsBeingTeleportedFar())
|
||||
if (!player->IsBeingTeleportedFar())
|
||||
return;
|
||||
|
||||
GetPlayer()->SetSemaphoreTeleportFar(false);
|
||||
player->SetSemaphoreTeleportFar(false);
|
||||
|
||||
// get the teleport destination
|
||||
WorldLocation const& loc = GetPlayer()->GetTeleportDest();
|
||||
WorldLocation const& loc = player->GetTeleportDest();
|
||||
|
||||
// possible errors in the coordinate validity check
|
||||
if (!MapManager::IsValidMapCoord(loc))
|
||||
@@ -64,90 +65,93 @@ void WorldSession::HandleMoveWorldportAck()
|
||||
InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId());
|
||||
|
||||
// reset instance validity, except if going to an instance inside an instance
|
||||
if (GetPlayer()->m_InstanceValid == false && !mInstance)
|
||||
GetPlayer()->m_InstanceValid = true;
|
||||
if (player->m_InstanceValid == false && !mInstance)
|
||||
player->m_InstanceValid = true;
|
||||
|
||||
Map* oldMap = GetPlayer()->GetMap();
|
||||
Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer());
|
||||
Map* oldMap = player->GetMap();
|
||||
Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), player);
|
||||
|
||||
if (GetPlayer()->IsInWorld())
|
||||
if (player->IsInWorld())
|
||||
{
|
||||
TC_LOG_ERROR("network", "%s %s is still in world when teleported from map %s (%u) to new map %s (%u)", GetPlayer()->GetGUID().ToString().c_str(), GetPlayer()->GetName().c_str(), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId());
|
||||
oldMap->RemovePlayerFromMap(GetPlayer(), false);
|
||||
TC_LOG_ERROR("network", "%s %s is still in world when teleported from map %s (%u) to new map %s (%u)", player->GetGUID().ToString().c_str(), player->GetName().c_str(), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId());
|
||||
oldMap->RemovePlayerFromMap(player, false);
|
||||
}
|
||||
|
||||
// relocate the player to the teleport destination
|
||||
// the CannotEnter checks are done in TeleporTo but conditions may change
|
||||
// while the player is in transit, for example the map may get full
|
||||
if (!newMap || newMap->CannotEnter(GetPlayer()))
|
||||
if (!newMap || newMap->CannotEnter(player))
|
||||
{
|
||||
TC_LOG_ERROR("network", "Map %d (%s) could not be created for player %d (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", GetPlayer()->GetGUID().GetCounter(), GetPlayer()->GetName().c_str());
|
||||
GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
|
||||
TC_LOG_ERROR("network", "Map %d (%s) could not be created for player %d (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", player->GetGUID().GetCounter(), player->GetName().c_str());
|
||||
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
|
||||
return;
|
||||
}
|
||||
|
||||
float z = loc.GetPositionZ() + GetPlayer()->GetHoverOffset();
|
||||
GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
|
||||
GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
|
||||
float z = loc.GetPositionZ() + player->GetHoverOffset();
|
||||
player->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
|
||||
player->SetFallInformation(0, player->GetPositionZ());
|
||||
|
||||
GetPlayer()->ResetMap();
|
||||
GetPlayer()->SetMap(newMap);
|
||||
player->ResetMap();
|
||||
player->SetMap(newMap);
|
||||
|
||||
GetPlayer()->SendInitialPacketsBeforeAddToMap();
|
||||
if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer()))
|
||||
player->SendInitialPacketsBeforeAddToMap();
|
||||
if (!player->GetMap()->AddPlayerToMap(player))
|
||||
{
|
||||
TC_LOG_ERROR("network", "WORLD: failed to teleport player %s (%d) to map %d (%s) because of unknown reason!",
|
||||
GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
|
||||
GetPlayer()->ResetMap();
|
||||
GetPlayer()->SetMap(oldMap);
|
||||
GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
|
||||
player->GetName().c_str(), player->GetGUID().GetCounter(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
|
||||
player->ResetMap();
|
||||
player->SetMap(oldMap);
|
||||
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
|
||||
return;
|
||||
}
|
||||
|
||||
// battleground state prepare (in case join to BG), at relogin/tele player not invited
|
||||
// only add to bg group and object, if the player was invited (else he entered through command)
|
||||
if (_player->InBattleground())
|
||||
if (player->InBattleground())
|
||||
{
|
||||
// cleanup setting if outdated
|
||||
if (!mEntry->IsBattlegroundOrArena())
|
||||
{
|
||||
// We're not in BG
|
||||
_player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE);
|
||||
player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE);
|
||||
// reset destination bg team
|
||||
_player->SetBGTeam(0);
|
||||
player->SetBGTeam(0);
|
||||
}
|
||||
// join to bg case
|
||||
else if (Battleground* bg = _player->GetBattleground())
|
||||
else if (Battleground* bg = player->GetBattleground())
|
||||
{
|
||||
if (_player->IsInvitedForBattlegroundInstance(_player->GetBattlegroundId()))
|
||||
bg->AddPlayer(_player);
|
||||
if (player->IsInvitedForBattlegroundInstance(player->GetBattlegroundId()))
|
||||
bg->AddPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
GetPlayer()->SendInitialPacketsAfterAddToMap();
|
||||
player->SendInitialPacketsAfterAddToMap();
|
||||
|
||||
// flight fast teleport case
|
||||
if (GetPlayer()->IsInFlight())
|
||||
if (player->IsInFlight())
|
||||
{
|
||||
if (!_player->InBattleground())
|
||||
if (!player->InBattleground())
|
||||
{
|
||||
// short preparations to continue flight
|
||||
MovementGenerator* movementGenerator = GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator();
|
||||
movementGenerator->Initialize(GetPlayer());
|
||||
MovementGenerator* movementGenerator = player->GetMotionMaster()->GetCurrentMovementGenerator();
|
||||
movementGenerator->Initialize(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// battleground state prepare, stop flight
|
||||
GetPlayer()->FinishTaxiFlight();
|
||||
player->FinishTaxiFlight();
|
||||
}
|
||||
|
||||
if (!player->IsAlive() && player->GetTeleportOptions() & TELE_REVIVE_AT_TELEPORT)
|
||||
player->ResurrectPlayer(0.5f);
|
||||
|
||||
// resurrect character at enter into instance where his corpse exist after add to map
|
||||
if (mEntry->IsDungeon() && !GetPlayer()->IsAlive())
|
||||
if (mEntry->IsDungeon() && !player->IsAlive())
|
||||
{
|
||||
if (GetPlayer()->GetCorpseLocation().GetMapId() == mEntry->MapID)
|
||||
if (player->GetCorpseLocation().GetMapId() == mEntry->MapID)
|
||||
{
|
||||
GetPlayer()->ResurrectPlayer(0.5f, false);
|
||||
GetPlayer()->SpawnCorpseBones();
|
||||
player->ResurrectPlayer(0.5f);
|
||||
player->SpawnCorpseBones();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +159,7 @@ void WorldSession::HandleMoveWorldportAck()
|
||||
if (mInstance)
|
||||
{
|
||||
// check if this instance has a reset time and send it to player if so
|
||||
Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid());
|
||||
Difficulty diff = player->GetDifficulty(mEntry->IsRaid());
|
||||
if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff))
|
||||
{
|
||||
if (mapDiff->resetTime)
|
||||
@@ -163,14 +167,14 @@ void WorldSession::HandleMoveWorldportAck()
|
||||
if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff))
|
||||
{
|
||||
uint32 timeleft = uint32(timeReset - GameTime::GetGameTime());
|
||||
GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft, true);
|
||||
player->SendInstanceResetWarning(mEntry->MapID, diff, timeleft, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if instance is valid
|
||||
if (!GetPlayer()->CheckInstanceValidity(false))
|
||||
GetPlayer()->m_InstanceValid = false;
|
||||
if (!player->CheckInstanceValidity(false))
|
||||
player->m_InstanceValid = false;
|
||||
|
||||
// instance mounting is handled in InstanceTemplate
|
||||
allowMount = mInstance->AllowMount;
|
||||
@@ -178,26 +182,26 @@ void WorldSession::HandleMoveWorldportAck()
|
||||
|
||||
// mount allow check
|
||||
if (!allowMount)
|
||||
_player->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
player->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
|
||||
// update zone immediately, otherwise leave channel will cause crash in mtmap
|
||||
uint32 newzone, newarea;
|
||||
GetPlayer()->GetZoneAndAreaId(newzone, newarea);
|
||||
GetPlayer()->UpdateZone(newzone, newarea);
|
||||
player->GetZoneAndAreaId(newzone, newarea);
|
||||
player->UpdateZone(newzone, newarea);
|
||||
|
||||
// honorless target
|
||||
if (GetPlayer()->pvpInfo.IsHostile)
|
||||
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
|
||||
if (player->pvpInfo.IsHostile)
|
||||
player->CastSpell(player, 2479, true);
|
||||
|
||||
// in friendly area
|
||||
else if (GetPlayer()->IsPvP() && !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
|
||||
GetPlayer()->UpdatePvP(false, false);
|
||||
else if (player->IsPvP() && !player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
|
||||
player->UpdatePvP(false, false);
|
||||
|
||||
// resummon pet
|
||||
GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
|
||||
player->ResummonPetTemporaryUnSummonedIfAny();
|
||||
|
||||
//lets process all delayed operations on successful teleport
|
||||
GetPlayer()->ProcessDelayedOperations();
|
||||
player->ProcessDelayedOperations();
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
|
||||
|
||||
Reference in New Issue
Block a user