Core/Player: Delay resurrection on release for unreachable maps until teleport has completed.

Port From (https://github.com/TrinityCore/TrinityCore/commit/e8e8e4b9d6ae72615334c5ef5f62d14a77729f55)
This commit is contained in:
hondacrx
2021-11-15 20:08:01 -05:00
parent c48696da32
commit ae1db5610d
3 changed files with 70 additions and 61 deletions
+2 -1
View File
@@ -341,7 +341,8 @@ namespace Framework.Constants
NotLeaveCombat = 0x04, NotLeaveCombat = 0x04,
NotUnSummonPet = 0x08, NotUnSummonPet = 0x08,
Spell = 0x10, Spell = 0x10,
Seamless = 0x20 ReviveAtTeleport = 0x40,
Seamless = 0x80
} }
/// Type of environmental damages /// Type of environmental damages
+8 -3
View File
@@ -1725,6 +1725,9 @@ namespace Game.Entities
UnsummonPetTemporaryIfAny(); UnsummonPetTemporaryIfAny();
} }
if (!IsAlive() && options.HasAnyFlag(TeleportToOptions.ReviveAtTeleport))
ResurrectPlayer(0.5f);
if (!options.HasAnyFlag(TeleportToOptions.NotLeaveCombat)) if (!options.HasAnyFlag(TeleportToOptions.NotLeaveCombat))
CombatStop(); CombatStop();
@@ -4522,10 +4525,11 @@ namespace Game.Entities
AreaTableRecord zone = CliDB.AreaTableStorage.LookupByKey(GetAreaId()); AreaTableRecord zone = CliDB.AreaTableStorage.LookupByKey(GetAreaId());
bool shouldResurrect = false;
// Such zones are considered unreachable as a ghost and the player must be automatically revived // Such zones are considered unreachable as a ghost and the player must be automatically revived
if ((!IsAlive() && zone != null && zone.HasFlag(AreaFlags.NeedFly)) || GetTransport() != null || GetPositionZ() < GetMap().GetMinHeight(GetPhaseShift(), GetPositionX(), GetPositionY())) if ((!IsAlive() && zone != null && zone.HasFlag(AreaFlags.NeedFly)) || GetTransport() != null || GetPositionZ() < GetMap().GetMinHeight(GetPhaseShift(), GetPositionX(), GetPositionY()))
{ {
ResurrectPlayer(0.5f); shouldResurrect = true;
SpawnCorpseBones(); SpawnCorpseBones();
} }
@@ -4551,7 +4555,7 @@ namespace Game.Entities
// and don't show spirit healer location // and don't show spirit healer location
if (ClosestGrave != null) if (ClosestGrave != null)
{ {
TeleportTo(ClosestGrave.Loc); TeleportTo(ClosestGrave.Loc, shouldResurrect ? TeleportToOptions.ReviveAtTeleport : 0);
if (IsDead()) // not send if alive, because it used in TeleportTo() if (IsDead()) // not send if alive, because it used in TeleportTo()
{ {
DeathReleaseLoc packet = new(); DeathReleaseLoc packet = new();
@@ -7024,7 +7028,8 @@ namespace Game.Entities
return pOther.GetDistance(player) <= WorldConfig.GetFloatValue(WorldCfg.MaxRecruitAFriendDistance); return pOther.GetDistance(player) <= WorldConfig.GetFloatValue(WorldCfg.MaxRecruitAFriendDistance);
} }
public bool IsBeingTeleported() { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; } public TeleportToOptions GetTeleportOptions() { return m_teleport_options; }
public bool IsBeingTeleported() { return IsBeingTeleportedNear() || IsBeingTeleportedFar(); }
public bool IsBeingTeleportedNear() { return mSemaphoreTeleport_Near; } public bool IsBeingTeleportedNear() { return mSemaphoreTeleport_Near; }
public bool IsBeingTeleportedFar() { return mSemaphoreTeleport_Far; } public bool IsBeingTeleportedFar() { return mSemaphoreTeleport_Far; }
public bool IsBeingTeleportedSeamlessly() { return IsBeingTeleportedFar() && m_teleport_options.HasAnyFlag(TeleportToOptions.Seamless); } public bool IsBeingTeleportedSeamlessly() { return IsBeingTeleportedFar() && m_teleport_options.HasAnyFlag(TeleportToOptions.Seamless); }
+60 -57
View File
@@ -220,15 +220,17 @@ namespace Game
void HandleMoveWorldportAck() void HandleMoveWorldportAck()
{ {
Player player = GetPlayer();
// ignore unexpected far teleports // ignore unexpected far teleports
if (!GetPlayer().IsBeingTeleportedFar()) if (!player.IsBeingTeleportedFar())
return; return;
bool seamlessTeleport = GetPlayer().IsBeingTeleportedSeamlessly(); bool seamlessTeleport = player.IsBeingTeleportedSeamlessly();
GetPlayer().SetSemaphoreTeleportFar(false); player.SetSemaphoreTeleportFar(false);
// get the teleport destination // get the teleport destination
WorldLocation loc = GetPlayer().GetTeleportDest(); WorldLocation loc = player.GetTeleportDest();
// possible errors in the coordinate validity check // possible errors in the coordinate validity check
if (!GridDefines.IsValidMapCoord(loc)) if (!GridDefines.IsValidMapCoord(loc))
@@ -242,112 +244,114 @@ namespace Game
InstanceTemplate mInstance = Global.ObjectMgr.GetInstanceTemplate(loc.GetMapId()); InstanceTemplate mInstance = Global.ObjectMgr.GetInstanceTemplate(loc.GetMapId());
// reset instance validity, except if going to an instance inside an instance // reset instance validity, except if going to an instance inside an instance
if (!GetPlayer().m_InstanceValid && mInstance == null) if (!player.m_InstanceValid && mInstance == null)
GetPlayer().m_InstanceValid = true; player.m_InstanceValid = true;
Map oldMap = GetPlayer().GetMap(); Map oldMap = player.GetMap();
Map newMap = Global.MapMgr.CreateMap(loc.GetMapId(), GetPlayer()); Map newMap = Global.MapMgr.CreateMap(loc.GetMapId(), player);
if (GetPlayer().IsInWorld) if (player.IsInWorld)
{ {
Log.outError(LogFilter.Network, "Player (Name {0}) is still in world when teleported from map {1} to new map {2}", GetPlayer().GetName(), oldMap.GetId(), loc.GetMapId()); Log.outError(LogFilter.Network, $"Player (Name {player.GetName()}) is still in world when teleported from map {oldMap.GetId()} to new map {loc.GetMapId()}");
oldMap.RemovePlayerFromMap(GetPlayer(), false); oldMap.RemovePlayerFromMap(player, false);
} }
// relocate the player to the teleport destination // relocate the player to the teleport destination
// the CannotEnter checks are done in TeleporTo but conditions may change // the CannotEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full // while the player is in transit, for example the map may get full
if (newMap == null || newMap.CannotEnter(GetPlayer()) != 0) if (newMap == null || newMap.CannotEnter(player) != 0)
{ {
Log.outError(LogFilter.Network, "Map {0} could not be created for {1} ({2}), porting player to homebind", loc.GetMapId(), newMap ? newMap.GetMapName() : "Unknown", GetPlayer().GetGUID().ToString()); Log.outError(LogFilter.Network, $"Map {loc.GetMapId()} could not be created for {(newMap ? newMap.GetMapName() : "Unknown")} ({player.GetGUID()}), porting player to homebind");
GetPlayer().TeleportTo(GetPlayer().GetHomebind()); player.TeleportTo(player.GetHomebind());
return; return;
} }
float z = loc.GetPositionZ() + GetPlayer().GetHoverOffset(); float z = loc.GetPositionZ() + player.GetHoverOffset();
GetPlayer().Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); player.Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
GetPlayer().SetFallInformation(0, GetPlayer().GetPositionZ()); player.SetFallInformation(0, player.GetPositionZ());
GetPlayer().ResetMap(); player.ResetMap();
GetPlayer().SetMap(newMap); player.SetMap(newMap);
ResumeToken resumeToken = new(); ResumeToken resumeToken = new();
resumeToken.SequenceIndex = _player.m_movementCounter; resumeToken.SequenceIndex = player.m_movementCounter;
resumeToken.Reason = seamlessTeleport ? 2 : 1u; resumeToken.Reason = seamlessTeleport ? 2 : 1u;
SendPacket(resumeToken); SendPacket(resumeToken);
if (!seamlessTeleport) if (!seamlessTeleport)
GetPlayer().SendInitialPacketsBeforeAddToMap(); player.SendInitialPacketsBeforeAddToMap();
if (!GetPlayer().GetMap().AddPlayerToMap(GetPlayer(), !seamlessTeleport)) if (!player.GetMap().AddPlayerToMap(player, !seamlessTeleport))
{ {
Log.outError(LogFilter.Network, "WORLD: failed to teleport player {0} ({1}) to map {2} ({3}) because of unknown reason!", Log.outError(LogFilter.Network, $"WORLD: failed to teleport player {player.GetName()} ({player.GetGUID()}) to map {loc.GetMapId()} ({(newMap ? newMap.GetMapName() : "Unknown")}) because of unknown reason!");
GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), loc.GetMapId(), newMap ? newMap.GetMapName() : "Unknown"); player.ResetMap();
GetPlayer().ResetMap(); player.SetMap(oldMap);
GetPlayer().SetMap(oldMap); player.TeleportTo(player.GetHomebind());
GetPlayer().TeleportTo(GetPlayer().GetHomebind());
return; return;
} }
// Battleground state prepare (in case join to BG), at relogin/tele player not invited // 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) // only add to bg group and object, if the player was invited (else he entered through command)
if (GetPlayer().InBattleground()) if (player.InBattleground())
{ {
// cleanup setting if outdated // cleanup setting if outdated
if (!mapEntry.IsBattlegroundOrArena()) if (!mapEntry.IsBattlegroundOrArena())
{ {
// We're not in BG // We're not in BG
GetPlayer().SetBattlegroundId(0, BattlegroundTypeId.None); player.SetBattlegroundId(0, BattlegroundTypeId.None);
// reset destination bg team // reset destination bg team
GetPlayer().SetBGTeam(0); player.SetBGTeam(0);
} }
// join to bg case // join to bg case
else else
{ {
Battleground bg = GetPlayer().GetBattleground(); Battleground bg = player.GetBattleground();
if (bg) if (bg)
{ {
if (GetPlayer().IsInvitedForBattlegroundInstance(GetPlayer().GetBattlegroundId())) if (player.IsInvitedForBattlegroundInstance(player.GetBattlegroundId()))
bg.AddPlayer(GetPlayer()); bg.AddPlayer(player);
} }
} }
} }
if (!seamlessTeleport) if (!seamlessTeleport)
GetPlayer().SendInitialPacketsAfterAddToMap(); player.SendInitialPacketsAfterAddToMap();
else else
{ {
GetPlayer().UpdateVisibilityForPlayer(); player.UpdateVisibilityForPlayer();
Garrison garrison = GetPlayer().GetGarrison(); Garrison garrison = player.GetGarrison();
if (garrison != null) if (garrison != null)
garrison.SendRemoteInfo(); garrison.SendRemoteInfo();
} }
// flight fast teleport case // flight fast teleport case
if (GetPlayer().IsInFlight()) if (player.IsInFlight())
{ {
if (!GetPlayer().InBattleground()) if (!player.InBattleground())
{ {
if (!seamlessTeleport) if (!seamlessTeleport)
{ {
// short preparations to continue flight // short preparations to continue flight
MovementGenerator movementGenerator = GetPlayer().GetMotionMaster().GetCurrentMovementGenerator(); MovementGenerator movementGenerator = player.GetMotionMaster().GetCurrentMovementGenerator();
movementGenerator.Initialize(GetPlayer()); movementGenerator.Initialize(player);
} }
return; return;
} }
// Battlegroundstate prepare, stop flight // Battlegroundstate prepare, stop flight
GetPlayer().FinishTaxiFlight(); player.FinishTaxiFlight();
} }
if (!player.IsAlive() && player.GetTeleportOptions().HasAnyFlag(TeleportToOptions.ReviveAtTeleport))
player.ResurrectPlayer(0.5f);
// resurrect character at enter into instance where his corpse exist after add to map // resurrect character at enter into instance where his corpse exist after add to map
if (mapEntry.IsDungeon() && !GetPlayer().IsAlive()) if (mapEntry.IsDungeon() && !player.IsAlive())
{ {
if (GetPlayer().GetCorpseLocation().GetMapId() == mapEntry.Id) if (player.GetCorpseLocation().GetMapId() == mapEntry.Id)
{ {
GetPlayer().ResurrectPlayer(0.5f, false); player.ResurrectPlayer(0.5f, false);
GetPlayer().SpawnCorpseBones(); player.SpawnCorpseBones();
} }
} }
@@ -364,34 +368,33 @@ namespace Game
if (timeReset != 0) if (timeReset != 0)
{ {
uint timeleft = (uint)(timeReset - GameTime.GetGameTime()); uint timeleft = (uint)(timeReset - GameTime.GetGameTime());
GetPlayer().SendInstanceResetWarning(mapEntry.Id, diff, timeleft, true); player.SendInstanceResetWarning(mapEntry.Id, diff, timeleft, true);
} }
} }
} }
// check if instance is valid // check if instance is valid
if (!GetPlayer().CheckInstanceValidity(false)) if (!player.CheckInstanceValidity(false))
GetPlayer().m_InstanceValid = false; player.m_InstanceValid = false;
} }
// update zone immediately, otherwise leave channel will cause crash in mtmap // update zone immediately, otherwise leave channel will cause crash in mtmap
uint newzone, newarea; player.GetZoneAndAreaId(out uint newzone, out uint newarea);
GetPlayer().GetZoneAndAreaId(out newzone, out newarea); player.UpdateZone(newzone, newarea);
GetPlayer().UpdateZone(newzone, newarea);
// honorless target // honorless target
if (GetPlayer().pvpInfo.IsHostile) if (player.pvpInfo.IsHostile)
GetPlayer().CastSpell(GetPlayer(), 2479, true); player.CastSpell(player, 2479, true);
// in friendly area // in friendly area
else if (GetPlayer().IsPvP() && !GetPlayer().HasPlayerFlag(PlayerFlags.InPVP)) else if (player.IsPvP() && !player.HasPlayerFlag(PlayerFlags.InPVP))
GetPlayer().UpdatePvP(false, false); player.UpdatePvP(false, false);
// resummon pet // resummon pet
GetPlayer().ResummonPetTemporaryUnSummonedIfAny(); player.ResummonPetTemporaryUnSummonedIfAny();
//lets process all delayed operations on successful teleport //lets process all delayed operations on successful teleport
GetPlayer().ProcessDelayedOperations(); player.ProcessDelayedOperations();
} }
[WorldPacketHandler(ClientOpcodes.SuspendTokenResponse, Status = SessionStatus.Transfer)] [WorldPacketHandler(ClientOpcodes.SuspendTokenResponse, Status = SessionStatus.Transfer)]