void Mutate(MovementGenerator m, MovementSlot _slot) { int slot = (int)_slot; MovementGenerator curr = Impl[slot]; if (curr != null) { Impl[slot] = null; // in case a new one is generated in this slot during directdelete if (_top == slot && Convert.ToBoolean(_cleanFlag & MMCleanFlag.UPDATE)) { DelayedDelete(curr); } else { DirectDelete(curr); } } else if (_top < slot) { _top = slot; } Impl[slot] = m; if (_top > slot) { _needInit[slot] = true; } else { _needInit[slot] = false; m.Initialize(_owner); } }
void HandleMoveWorldportAck() { Player player = GetPlayer(); // ignore unexpected far teleports if (!player.IsBeingTeleportedFar()) { return; } bool seamlessTeleport = player.IsBeingTeleportedSeamlessly(); player.SetSemaphoreTeleportFar(false); // get the teleport destination WorldLocation loc = player.GetTeleportDest(); // possible errors in the coordinate validity check if (!GridDefines.IsValidMapCoord(loc)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapRecord mapEntry = CliDB.MapStorage.LookupByKey(loc.GetMapId()); InstanceTemplate mInstance = Global.ObjectMgr.GetInstanceTemplate(loc.GetMapId()); // reset instance validity, except if going to an instance inside an instance if (!player.m_InstanceValid && mInstance == null) { player.m_InstanceValid = true; } Map oldMap = player.GetMap(); Map newMap = Global.MapMgr.CreateMap(loc.GetMapId(), player); if (player.IsInWorld) { 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(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 == null || newMap.CannotEnter(player) != 0) { Log.outError(LogFilter.Network, $"Map {loc.GetMapId()} could not be created for {(newMap ? newMap.GetMapName() : "Unknown")} ({player.GetGUID()}), porting player to homebind"); player.TeleportTo(player.GetHomebind()); return; } float z = loc.GetPositionZ() + player.GetHoverOffset(); player.Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); player.SetFallInformation(0, player.GetPositionZ()); player.ResetMap(); player.SetMap(newMap); ResumeToken resumeToken = new(); resumeToken.SequenceIndex = player.m_movementCounter; resumeToken.Reason = seamlessTeleport ? 2 : 1u; SendPacket(resumeToken); if (!seamlessTeleport) { player.SendInitialPacketsBeforeAddToMap(); } if (!player.GetMap().AddPlayerToMap(player, !seamlessTeleport)) { 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!"); player.ResetMap(); player.SetMap(oldMap); player.TeleportTo(player.GetHomebind()); 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()) { // cleanup setting if outdated if (!mapEntry.IsBattlegroundOrArena()) { // We're not in BG player.SetBattlegroundId(0, BattlegroundTypeId.None); // reset destination bg team player.SetBGTeam(0); } // join to bg case else { Battleground bg = player.GetBattleground(); if (bg) { if (player.IsInvitedForBattlegroundInstance(player.GetBattlegroundId())) { bg.AddPlayer(player); } } } } if (!seamlessTeleport) { player.SendInitialPacketsAfterAddToMap(); } else { player.UpdateVisibilityForPlayer(); Garrison garrison = player.GetGarrison(); if (garrison != null) { garrison.SendRemoteInfo(); } } // flight fast teleport case if (player.IsInFlight()) { if (!player.InBattleground()) { if (!seamlessTeleport) { // short preparations to continue flight MovementGenerator movementGenerator = player.GetMotionMaster().GetCurrentMovementGenerator(); movementGenerator.Initialize(player); } return; } // Battlegroundstate prepare, stop flight 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 if (mapEntry.IsDungeon() && !player.IsAlive()) { if (player.GetCorpseLocation().GetMapId() == mapEntry.Id) { player.ResurrectPlayer(0.5f, false); player.SpawnCorpseBones(); } } if (mInstance != null) { // check if this instance has a reset time and send it to player if so Difficulty diff = newMap.GetDifficultyID(); MapDifficultyRecord mapDiff = Global.DB2Mgr.GetMapDifficultyData(mapEntry.Id, diff); if (mapDiff != null) { if (mapDiff.GetRaidDuration() != 0) { long timeReset = Global.InstanceSaveMgr.GetResetTimeFor(mapEntry.Id, diff); if (timeReset != 0) { uint timeleft = (uint)(timeReset - GameTime.GetGameTime()); player.SendInstanceResetWarning(mapEntry.Id, diff, timeleft, true); } } } // check if instance is valid if (!player.CheckInstanceValidity(false)) { player.m_InstanceValid = false; } } // update zone immediately, otherwise leave channel will cause crash in mtmap player.GetZoneAndAreaId(out uint newzone, out uint newarea); player.UpdateZone(newzone, newarea); // honorless target if (player.pvpInfo.IsHostile) { player.CastSpell(player, 2479, true); } // in friendly area else if (player.IsPvP() && !player.HasPlayerFlag(PlayerFlags.InPVP)) { player.UpdatePvP(false, false); } // resummon pet player.ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport player.ProcessDelayedOperations(); }