예제 #1
0
        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);
            }
        }
예제 #2
0
        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();
        }