Esempio n. 1
0
        private static bool Check(
            Map map,
            IPoint3D p,
            List <Item> items,
            int x,
            int y,
            int startTop,
            int startZ,
            bool canSwim,
            bool cantWalk,
            out int newZ)
        {
            newZ = 0;

            StaticTile[] tiles        = map.Tiles.GetStaticTiles(x, y, true);
            LandTile     landTile     = map.Tiles.GetLandTile(x, y);
            LandData     landData     = TileData.LandTable[landTile.ID & TileData.MaxLandValue];
            bool         landBlocks   = (landData.Flags & TileFlag.Impassable) != 0;
            bool         considerLand = !landTile.Ignored;

            if (landBlocks && canSwim && (landData.Flags & TileFlag.Wet) != 0)
            {
                //Impassable, Can Swim, and Is water.  Don't block it.
                landBlocks = false;
            }
            else if (cantWalk && (landData.Flags & TileFlag.Wet) == 0)
            {
                //Can't walk and it's not water
                landBlocks = true;
            }

            int landZ = 0, landCenter = 0, landTop = 0;

            map.GetAverageZ(x, y, ref landZ, ref landCenter, ref landTop);

            bool moveIsOk = false;

            int stepTop  = startTop + StepHeight;
            int checkTop = startZ + PersonHeight;

            Mobile m = p as Mobile;

            bool ignoreDoors = MovementImpl.AlwaysIgnoreDoors(p) || m == null || !m.Alive || m.IsDeadBondedPet || m.Body.IsGhost ||
                               m.Body.BodyID == 987;
            bool ignoreSpellFields = m is PlayerMobile && map.MapID != 0;

            int      itemZ, itemTop, ourZ, ourTop, testTop;
            ItemData itemData;
            TileFlag flags;

            #region Tiles
            foreach (StaticTile tile in tiles)
            {
                itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
                flags    = itemData.Flags;

                #region SA
                if (m != null && m.Flying && (Insensitive.Equals(itemData.Name, "hover over") || (flags & TileFlag.HoverOver) != 0))
                {
                    newZ = tile.Z;
                    return(true);
                }

                // Stygian Dragon
                if (m != null && m.Body == 826 && map != null && map.MapID == 5)
                {
                    if (x >= 307 && x <= 354 && y >= 126 && y <= 192)
                    {
                        if (tile.Z > newZ)
                        {
                            newZ = tile.Z;
                        }

                        moveIsOk = true;
                    }
                    else if (x >= 42 && x <= 89)
                    {
                        if ((y >= 333 && y <= 399) || (y >= 531 && y <= 597) || (y >= 739 && y <= 805))
                        {
                            if (tile.Z > newZ)
                            {
                                newZ = tile.Z;
                            }

                            moveIsOk = true;
                        }
                    }
                }
                #endregion

                if ((flags & ImpassableSurface) != TileFlag.Surface && (!canSwim || (flags & TileFlag.Wet) == 0))
                {
                    continue;
                }

                if (cantWalk && (flags & TileFlag.Wet) == 0)
                {
                    continue;
                }

                itemZ   = tile.Z;
                itemTop = itemZ;
                ourZ    = itemZ + itemData.CalcHeight;
                ourTop  = ourZ + PersonHeight;
                testTop = checkTop;

                if (moveIsOk)
                {
                    int cmp = Math.Abs(ourZ - p.Z) - Math.Abs(newZ - p.Z);

                    if (cmp > 0 || (cmp == 0 && ourZ > newZ))
                    {
                        continue;
                    }
                }

                if (ourTop > testTop)
                {
                    testTop = ourTop;
                }

                if (!itemData.Bridge)
                {
                    itemTop += itemData.Height;
                }

                if (stepTop < itemTop)
                {
                    continue;
                }

                int landCheck = itemZ;

                if (itemData.Height >= StepHeight)
                {
                    landCheck += StepHeight;
                }
                else
                {
                    landCheck += itemData.Height;
                }

                if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ)
                {
                    continue;
                }

                if (!IsOk(m, ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items))
                {
                    continue;
                }

                newZ     = ourZ;
                moveIsOk = true;
            }
            #endregion

            #region Items
            foreach (Item item in items)
            {
                itemData = item.ItemData;
                flags    = itemData.Flags;

                #region SA
                if (m != null && m.Flying && (Insensitive.Equals(itemData.Name, "hover over") || (flags & TileFlag.HoverOver) != 0))
                {
                    newZ = item.Z;
                    return(true);
                }
                #endregion

                if (item.Movable)
                {
                    continue;
                }

                if ((flags & ImpassableSurface) != TileFlag.Surface && ((m != null && !m.CanSwim) || (flags & TileFlag.Wet) == 0))
                {
                    continue;
                }

                if (cantWalk && (flags & TileFlag.Wet) == 0)
                {
                    continue;
                }

                itemZ   = item.Z;
                itemTop = itemZ;
                ourZ    = itemZ + itemData.CalcHeight;
                ourTop  = ourZ + PersonHeight;
                testTop = checkTop;

                if (moveIsOk)
                {
                    int cmp = Math.Abs(ourZ - p.Z) - Math.Abs(newZ - p.Z);

                    if (cmp > 0 || (cmp == 0 && ourZ > newZ))
                    {
                        continue;
                    }
                }

                if (ourTop > testTop)
                {
                    testTop = ourTop;
                }

                if (!itemData.Bridge)
                {
                    itemTop += itemData.Height;
                }

                if (stepTop < itemTop)
                {
                    continue;
                }

                int landCheck = itemZ;

                if (itemData.Height >= StepHeight)
                {
                    landCheck += StepHeight;
                }
                else
                {
                    landCheck += itemData.Height;
                }

                if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ)
                {
                    continue;
                }

                if (!IsOk(m, ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items))
                {
                    continue;
                }

                newZ     = ourZ;
                moveIsOk = true;
            }
            #endregion

            if (!considerLand || landBlocks || stepTop < landZ)
            {
                return(moveIsOk);
            }

            ourZ    = landCenter;
            ourTop  = ourZ + PersonHeight;
            testTop = checkTop;

            if (ourTop > testTop)
            {
                testTop = ourTop;
            }

            bool shouldCheck = true;

            if (moveIsOk)
            {
                int cmp = Math.Abs(ourZ - p.Z) - Math.Abs(newZ - p.Z);

                if (cmp > 0 || (cmp == 0 && ourZ > newZ))
                {
                    shouldCheck = false;
                }
            }

            if (!shouldCheck || !IsOk(m, ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items))
            {
                return(moveIsOk);
            }

            newZ     = ourZ;
            moveIsOk = true;

            return(moveIsOk);
        }
Esempio n. 2
0
        public bool CheckMovement(IPoint3D p, Map map, Point3D loc, Direction d, out int newZ)
        {
            if (!Enabled && _Successor != null)
            {
                return(_Successor.CheckMovement(p, map, loc, d, out newZ));
            }

            if (map == null || map == Map.Internal)
            {
                newZ = 0;
                return(false);
            }

            int xStart = loc.X;
            int yStart = loc.Y;

            int xForward = xStart, yForward = yStart;
            int xRight = xStart, yRight = yStart;
            int xLeft = xStart, yLeft = yStart;

            bool checkDiagonals = ((int)d & 0x1) == 0x1;

            Offset(d, ref xForward, ref yForward);
            Offset((Direction)(((int)d - 1) & 0x7), ref xLeft, ref yLeft);
            Offset((Direction)(((int)d + 1) & 0x7), ref xRight, ref yRight);

            if (xForward < 0 || yForward < 0 || xForward >= map.Width || yForward >= map.Height)
            {
                newZ = 0;
                return(false);
            }

            int startZ, startTop;

            IEnumerable <Item> itemsStart, itemsForward, itemsLeft, itemsRight;

            bool     ignoreMovableImpassables = MovementImpl.IgnoresMovableImpassables(p);
            TileFlag reqFlags = ImpassableSurface;

            if (p is Mobile && ((Mobile)p).CanSwim)
            {
                reqFlags |= TileFlag.Wet;
            }

            if (checkDiagonals)
            {
                Sector sStart   = map.GetSector(xStart, yStart);
                Sector sForward = map.GetSector(xForward, yForward);
                Sector sLeft    = map.GetSector(xLeft, yLeft);
                Sector sRight   = map.GetSector(xRight, yRight);

                itemsStart   = sStart.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xStart, yStart));
                itemsForward = sForward.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xForward, yForward));
                itemsLeft    = sLeft.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xLeft, yLeft));
                itemsRight   = sRight.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xRight, yRight));
            }
            else
            {
                Sector sStart   = map.GetSector(xStart, yStart);
                Sector sForward = map.GetSector(xForward, yForward);

                itemsStart   = sStart.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xStart, yStart));
                itemsForward = sForward.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xForward, yForward));
                itemsLeft    = Enumerable.Empty <Item>();
                itemsRight   = Enumerable.Empty <Item>();
            }

            GetStartZ(p, map, loc, itemsStart, out startZ, out startTop);

            List <Item> list = null;

            MovementPool.AcquireMoveCache(ref list, itemsForward);
            Mobile m = p as Mobile;

            bool moveIsOk = Check(map, p, list, xForward, yForward, startTop, startZ, m != null && m.CanSwim, m != null && m.CantWalk, out newZ);

            if (m != null && moveIsOk && checkDiagonals)
            {
                int hold;

                if (m.Player && m.AccessLevel < AccessLevel.GameMaster)
                {
                    MovementPool.AcquireMoveCache(ref list, itemsLeft);

                    if (!Check(map, m, list, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out hold))
                    {
                        moveIsOk = false;
                    }
                    else
                    {
                        MovementPool.AcquireMoveCache(ref list, itemsRight);

                        if (!Check(map, m, list, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out hold))
                        {
                            moveIsOk = false;
                        }
                    }
                }
                else
                {
                    MovementPool.AcquireMoveCache(ref list, itemsLeft);

                    if (!Check(map, m, list, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out hold))
                    {
                        MovementPool.AcquireMoveCache(ref list, itemsRight);

                        if (!Check(map, m, list, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out hold))
                        {
                            moveIsOk = false;
                        }
                    }
                }
            }

            MovementPool.ClearMoveCache(ref list, true);

            if (!moveIsOk)
            {
                newZ = startZ;
            }

            return(moveIsOk);
        }