Beispiel #1
0
        public static void WriteMovementInfo(WorldPacket data, MovementInfo movementInfo)
        {
            bool hasTransportData = !movementInfo.transport.guid.IsEmpty();
            bool hasFallDirection = movementInfo.HasMovementFlag(MovementFlag.Falling | MovementFlag.FallingFar);
            bool hasFallData      = hasFallDirection || movementInfo.jump.fallTime != 0;
            bool hasSpline        = false; // todo 6.x send this infos

            data.WritePackedGuid(movementInfo.Guid);
            data.WriteUInt32(movementInfo.Time);
            data.WriteFloat(movementInfo.Pos.GetPositionX());
            data.WriteFloat(movementInfo.Pos.GetPositionY());
            data.WriteFloat(movementInfo.Pos.GetPositionZ());
            data.WriteFloat(movementInfo.Pos.GetOrientation());
            data.WriteFloat(movementInfo.Pitch);
            data.WriteFloat(movementInfo.SplineElevation);

            uint removeMovementForcesCount = 0;

            data.WriteUInt32(removeMovementForcesCount);

            uint int168 = 0;

            data.WriteUInt32(int168);

            /*for (public uint i = 0; i < removeMovementForcesCount; ++i)
             * {
             *  _worldPacket << ObjectGuid;
             * }*/

            data.WriteBits((uint)movementInfo.GetMovementFlags(), 30);
            data.WriteBits((uint)movementInfo.GetMovementFlags2(), 18);

            data.WriteBit(hasTransportData);
            data.WriteBit(hasFallData);
            data.WriteBit(hasSpline);
            data.WriteBit(0); // HeightChangeFailed
            data.WriteBit(0); // RemoteTimeValid
            data.FlushBits();

            if (hasTransportData)
            {
                WriteTransportInfo(data, movementInfo.transport);
            }

            if (hasFallData)
            {
                data.WriteUInt32(movementInfo.jump.fallTime);
                data.WriteFloat(movementInfo.jump.zspeed);

                data.WriteBit(hasFallDirection);
                data.FlushBits();
                if (hasFallDirection)
                {
                    data.WriteFloat(movementInfo.jump.sinAngle);
                    data.WriteFloat(movementInfo.jump.cosAngle);
                    data.WriteFloat(movementInfo.jump.xyspeed);
                }
            }
        }
        void HandleMovementOpcode(ClientOpcodes opcode, MovementInfo movementInfo)
        {
            Unit   mover    = GetPlayer().m_unitMovedByMe;
            Player plrMover = mover.ToPlayer();

            if (plrMover && plrMover.IsBeingTeleported())
            {
                return;
            }

            GetPlayer().ValidateMovementInfo(movementInfo);

            if (movementInfo.Guid != mover.GetGUID())
            {
                Log.outError(LogFilter.Network, "HandleMovementOpcodes: guid error");
                return;
            }
            if (!movementInfo.Pos.IsPositionValid())
            {
                Log.outError(LogFilter.Network, "HandleMovementOpcodes: Invalid Position");
                return;
            }

            // stop some emotes at player move
            if (plrMover && (plrMover.GetEmoteState() != 0))
            {
                plrMover.SetEmoteState(Emote.OneshotNone);
            }

            //handle special cases
            if (!movementInfo.transport.guid.IsEmpty())
            {
                // We were teleported, skip packets that were broadcast before teleport
                if (movementInfo.Pos.GetExactDist2d(mover) > MapConst.SizeofGrids)
                {
                    return;
                }

                if (Math.Abs(movementInfo.transport.pos.GetPositionX()) > 75f || Math.Abs(movementInfo.transport.pos.GetPositionY()) > 75f || Math.Abs(movementInfo.transport.pos.GetPositionZ()) > 75f)
                {
                    return;
                }

                if (!GridDefines.IsValidMapCoord(movementInfo.Pos.posX + movementInfo.transport.pos.posX, movementInfo.Pos.posY + movementInfo.transport.pos.posY,
                                                 movementInfo.Pos.posZ + movementInfo.transport.pos.posZ, movementInfo.Pos.Orientation + movementInfo.transport.pos.Orientation))
                {
                    return;
                }

                if (plrMover)
                {
                    if (!plrMover.GetTransport())
                    {
                        Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid);
                        if (transport)
                        {
                            transport.AddPassenger(plrMover);
                        }
                    }
                    else if (plrMover.GetTransport().GetGUID() != movementInfo.transport.guid)
                    {
                        plrMover.GetTransport().RemovePassenger(plrMover);
                        Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid);
                        if (transport)
                        {
                            transport.AddPassenger(plrMover);
                        }
                        else
                        {
                            movementInfo.ResetTransport();
                        }
                    }
                }

                if (!mover.GetTransport() && !mover.GetVehicle())
                {
                    GameObject go = mover.GetMap().GetGameObject(movementInfo.transport.guid);
                    if (!go || go.GetGoType() != GameObjectTypes.Transport)
                    {
                        movementInfo.transport.Reset();
                    }
                }
            }
            else if (plrMover && plrMover.GetTransport())                // if we were on a transport, leave
            {
                plrMover.GetTransport().RemovePassenger(plrMover);
            }

            // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
            if (opcode == ClientOpcodes.MoveFallLand && plrMover && !plrMover.IsInFlight())
            {
                plrMover.HandleFall(movementInfo);
            }

            // interrupt parachutes upon falling or landing in water
            if (opcode == ClientOpcodes.MoveFallLand || opcode == ClientOpcodes.MoveStartSwim)
            {
                mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Landing); // Parachutes
            }
            if (plrMover && movementInfo.HasMovementFlag(MovementFlag.Swimming) != plrMover.IsInWater())
            {
                // now client not include swimming flag in case jumping under water
                plrMover.SetInWater(!plrMover.IsInWater() || plrMover.GetMap().IsUnderWater(plrMover.GetPhaseShift(), movementInfo.Pos.posX, movementInfo.Pos.posY, movementInfo.Pos.posZ));
            }

            uint mstime = GameTime.GetGameTimeMS();

            if (m_clientTimeDelay == 0)
            {
                m_clientTimeDelay = mstime - movementInfo.Time;
            }

            movementInfo.Time = movementInfo.Time + m_clientTimeDelay;

            movementInfo.Guid    = mover.GetGUID();
            mover.m_movementInfo = movementInfo;

            // Some vehicles allow the passenger to turn by himself
            Vehicle vehicle = mover.GetVehicle();

            if (vehicle)
            {
                VehicleSeatRecord seat = vehicle.GetSeatForPassenger(mover);
                if (seat != null)
                {
                    if (seat.HasSeatFlag(VehicleSeatFlags.AllowTurning))
                    {
                        if (movementInfo.Pos.GetOrientation() != mover.GetOrientation())
                        {
                            mover.SetOrientation(movementInfo.Pos.GetOrientation());
                            mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Turning);
                        }
                    }
                }
                return;
            }

            mover.UpdatePosition(movementInfo.Pos);

            MoveUpdate moveUpdate = new MoveUpdate();

            moveUpdate.Status = mover.m_movementInfo;
            mover.SendMessageToSet(moveUpdate, GetPlayer());

            if (plrMover)                                            // nothing is charmed, or player charmed
            {
                if (plrMover.IsSitState() && movementInfo.HasMovementFlag(MovementFlag.MaskMoving | MovementFlag.MaskTurning))
                {
                    plrMover.SetStandState(UnitStandStateType.Stand);
                }

                plrMover.UpdateFallInformationIfNeed(movementInfo, opcode);

                if (movementInfo.Pos.posZ < plrMover.GetMap().GetMinHeight(plrMover.GetPhaseShift(), movementInfo.Pos.GetPositionX(), movementInfo.Pos.GetPositionY()))
                {
                    if (!(plrMover.GetBattleground() && plrMover.GetBattleground().HandlePlayerUnderMap(GetPlayer())))
                    {
                        // NOTE: this is actually called many times while falling
                        // even after the player has been teleported away
                        // @todo discard movement packets after the player is rooted
                        if (plrMover.IsAlive())
                        {
                            plrMover.AddPlayerFlag(PlayerFlags.IsOutOfBounds);
                            plrMover.EnvironmentalDamage(EnviromentalDamage.FallToVoid, (uint)GetPlayer().GetMaxHealth());
                            // player can be alive if GM/etc
                            // change the death state to CORPSE to prevent the death timer from
                            // starting in the next player update
                            if (plrMover.IsAlive())
                            {
                                plrMover.KillPlayer();
                            }
                        }
                    }
                }
                else
                {
                    plrMover.RemovePlayerFlag(PlayerFlags.IsOutOfBounds);
                }

                if (opcode == ClientOpcodes.MoveJump)
                {
                    plrMover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Jump, 605); // Mind Control
                    plrMover.ProcSkillsAndAuras(null, ProcFlags.Jump, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
                }
            }
        }