Exemple #1
0
        /// <summary>
        /// Checks if the specified z-height is under an item or a ground.
        /// </summary>
        /// <param name="z">The z value to check.</param>
        /// <param name="underEntity">Returns the first roof, surface, or wall that is over the specified z.
        ///                         If no such objects exist above the specified z, then returns null.</param>
        /// <param name="underGround">Returns the ground object of this tile if the specified z is under the ground.
        ///                         Returns null otherwise.</param>
        public void IsZUnderEntityOrGround(int z, out AEntity underEntity, out AEntity underGround)
        {
            // getting the publicly exposed Entities collection will sort the entities if necessary.
            List <AEntity> entities = Entities;

            underEntity = null;
            underGround = null;

            for (int i = entities.Count - 1; i >= 0; i--)
            {
                if (entities[i].Z <= z)
                {
                    continue;
                }

                if (entities[i] is Item) // checks Item and StaticItem entities.
                {
                    UltimaData.ItemData data = ((Item)entities[i]).ItemData;
                    if (data.IsRoof || data.IsSurface || (data.IsWall && data.IsImpassable))
                    {
                        if (underEntity == null || entities[i].Z < underEntity.Z)
                        {
                            underEntity = entities[i];
                        }
                    }
                }
                else if (entities[i] is Ground && entities[i].GetView().SortZ >= z + 12)
                {
                    underGround = entities[i];
                }
            }
        }
        public MapObjectStatic(int staticTileID, int sortInfluence, Position3D position)
            : base(position)
        {
            ItemID = staticTileID;
            SortTiebreaker = sortInfluence;

            m_itemData = UltimaData.TileData.ItemData[ItemID & 0x3FFF];

            // Set threshold.
            int background = (m_itemData.IsBackground) ? 0 : 1;
            if (!m_itemData.IsBackground)
                SortThreshold++;
            if (!(m_itemData.Height == 0))
                SortThreshold++;
            if (m_itemData.IsSurface)
                SortThreshold--;

            // get no draw flag
            if (m_itemData.Name == "nodraw" || ItemID <= 0)
                m_noDraw = true;

            // set up draw variables
            m_draw_texture = UltimaData.ArtData.GetStaticTexture(ItemID);
            m_draw_width = m_draw_texture.Width;
            m_draw_height = m_draw_texture.Height;
            m_draw_X = (m_draw_width >> 1) - 22;
            m_draw_Y = (int)(Z * 4) + m_draw_height - 44;
            m_draw_hue = Vector2.Zero;
            m_pickType = PickTypes.PickStatics;
            m_draw_flip = false;
        }
        private static bool IsOk(bool ignoreDoors, int ourZ, int ourTop, StaticItem[] tiles, List <Item> items)
        {
            for (int i = 0; i < tiles.Length; ++i)
            {
                StaticItem check = tiles[i];

                if ((check.ItemData.Flags & ImpassableSurface) != 0) // Impassable || Surface
                {
                    int checkZ   = (int)check.Z;
                    int checkTop = checkZ + check.ItemData.CalcHeight;

                    if (checkTop > ourZ && ourTop > checkZ)
                    {
                        return(false);
                    }
                }
            }

            for (int i = 0; i < items.Count; ++i)
            {
                Item item   = items[i];
                int  itemID = item.ItemID & 0x3FFF;
                UltimaData.ItemData itemData = UltimaData.TileData.ItemData[itemID];
                TileFlag            flags    = itemData.Flags;

                if ((flags & ImpassableSurface) != 0) // Impassable || Surface
                {
                    if (ignoreDoors && ((flags & TileFlag.Door) != 0 || itemID == 0x692 || itemID == 0x846 || itemID == 0x873 || (itemID >= 0x6F5 && itemID <= 0x6F6)))
                    {
                        continue;
                    }

                    int checkZ   = item.Z;
                    int checkTop = checkZ + itemData.CalcHeight;

                    if (checkTop > ourZ && ourTop > checkZ)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        private static void getStartZ(AEntity m, Map map, Position3D loc, List <Item> itemList, out int zLow, out int zTop)
        {
            int xCheck = (int)loc.X, yCheck = (int)loc.Y;

            MapTile mapTile = map.GetMapTile(xCheck, yCheck);

            if (mapTile == null)
            {
                zLow = int.MinValue;
                zTop = int.MinValue;
            }

            bool landBlocks = mapTile.Ground.LandData.IsImpassible; //(TileData.LandTable[landTile.ID & 0x3FFF].Flags & TileFlag.Impassable) != 0;

            // if (landBlocks && m.CanSwim && (TileData.LandTable[landTile.ID & 0x3FFF].Flags & TileFlag.Wet) != 0)
            //     landBlocks = false;
            // else if (m.CantWalk && (TileData.LandTable[landTile.ID & 0x3FFF].Flags & TileFlag.Wet) == 0)
            //     landBlocks = true;

            int landLow = 0, landCenter = 0, landTop = 0;

            landCenter = map.GetAverageZ(xCheck, yCheck, ref landLow, ref landTop);

            bool considerLand = !mapTile.Ground.IsIgnored;

            int  zCenter = zLow = zTop = 0;
            bool isSet   = false;

            if (considerLand && !landBlocks && loc.Z >= landCenter)
            {
                zLow    = landLow;
                zCenter = landCenter;

                if (!isSet || landTop > zTop)
                {
                    zTop = landTop;
                }

                isSet = true;
            }

            StaticItem[] staticTiles = mapTile.GetStatics().ToArray();

            for (int i = 0; i < staticTiles.Length; ++i)
            {
                StaticItem tile = staticTiles[i];

                int calcTop = ((int)tile.Z + tile.ItemData.CalcHeight);

                if ((!isSet || calcTop >= zCenter) && ((tile.ItemData.Flags & TileFlag.Surface) != 0) && loc.Z >= calcTop)
                {
                    //  || (m.CanSwim && (id.Flags & TileFlag.Wet) != 0)
                    // if (m.CantWalk && (id.Flags & TileFlag.Wet) == 0)
                    //     continue;

                    zLow    = (int)tile.Z;
                    zCenter = calcTop;

                    int top = (int)tile.Z + tile.ItemData.Height;

                    if (!isSet || top > zTop)
                    {
                        zTop = top;
                    }

                    isSet = true;
                }
            }

            for (int i = 0; i < itemList.Count; ++i)
            {
                Item item = itemList[i];

                UltimaData.ItemData id = item.ItemData;

                int calcTop = item.Z + id.CalcHeight;

                if ((!isSet || calcTop >= zCenter) && ((id.Flags & TileFlag.Surface) != 0) && loc.Z >= calcTop)
                {
                    //  || (m.CanSwim && (id.Flags & TileFlag.Wet) != 0)
                    // if (m.CantWalk && (id.Flags & TileFlag.Wet) == 0)
                    //     continue;

                    zLow    = item.Z;
                    zCenter = calcTop;

                    int top = item.Z + id.Height;

                    if (!isSet || top > zTop)
                    {
                        zTop = top;
                    }

                    isSet = true;
                }
            }

            if (!isSet)
            {
                zLow = zTop = (int)loc.Z;
            }
            else if (loc.Z > zTop)
            {
                zTop = (int)loc.Z;
            }
        }
        private static bool check(Map map, Mobile m, List <Item> items, int x, int y, int startTop, int startZ, out int newZ)
        {
            newZ = 0;

            MapTile mapTile = map.GetMapTile(x, y);

            if (mapTile == null)
            {
                return(false);
            }

            StaticItem[] tiles = mapTile.GetStatics().ToArray();

            bool landBlocks   = (mapTile.Ground.LandData.Flags & TileFlag.Impassable) != 0;
            bool considerLand = !mapTile.Ground.IsIgnored;

            //if (landBlocks && canSwim && (TileData.LandTable[landTile.ID & 0x3FFF].Flags & TileFlag.Wet) != 0)	//Impassable, Can Swim, and Is water.  Don't block it.
            //    landBlocks = false;
            // else
            // if (cantWalk && (TileData.LandTable[landTile.ID & 0x3FFF].Flags & TileFlag.Wet) == 0)	//Can't walk and it's not water
            //     landBlocks = true;

            int landLow = 0, landCenter = 0, landTop = 0;

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

            bool moveIsOk = false;

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

            bool ignoreDoors = (!m.Alive || m.BodyID == 0x3DB);

            #region Tiles
            for (int i = 0; i < tiles.Length; ++i)
            {
                StaticItem tile = tiles[i];

                if ((tile.ItemData.Flags & ImpassableSurface) == TileFlag.Surface) //  || (canSwim && (flags & TileFlag.Wet) != 0) Surface && !Impassable
                {
                    // if (cantWalk && (flags & TileFlag.Wet) == 0)
                    //     continue;

                    int itemZ   = (int)tile.Z;
                    int itemTop = itemZ;
                    int ourZ    = itemZ + tile.ItemData.CalcHeight;
                    int ourTop  = ourZ + PersonHeight;
                    int testTop = checkTop;

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

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

                    if (ourZ + PersonHeight > testTop)
                    {
                        testTop = ourZ + PersonHeight;
                    }

                    if (!tile.ItemData.IsBridge)
                    {
                        itemTop += tile.ItemData.Height;
                    }

                    if (stepTop >= itemTop)
                    {
                        int landCheck = itemZ;

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

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

                        if (IsOk(ignoreDoors, ourZ, testTop, tiles, items))
                        {
                            newZ     = ourZ;
                            moveIsOk = true;
                        }
                    }
                }
            }
            #endregion

            #region Items
            for (int i = 0; i < items.Count; ++i)
            {
                Item item = items[i];
                UltimaData.ItemData itemData = item.ItemData;
                TileFlag            flags    = itemData.Flags;

                if ((flags & ImpassableSurface) == TileFlag.Surface) // Surface && !Impassable && !Movable
                {
                    //  || (m.CanSwim && (flags & TileFlag.Wet) != 0))
                    // !item.Movable &&
                    // if (cantWalk && (flags & TileFlag.Wet) == 0)
                    //     continue;

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

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

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

                    if (ourZ + PersonHeight > testTop)
                    {
                        testTop = ourZ + PersonHeight;
                    }

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

                    if (stepTop >= itemTop)
                    {
                        int landCheck = itemZ;

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

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

                        if (IsOk(ignoreDoors, ourZ, testTop, tiles, items))
                        {
                            newZ     = ourZ;
                            moveIsOk = true;
                        }
                    }
                }
            }

            #endregion

            if (considerLand && !landBlocks && (stepTop) >= landLow)
            {
                int ourZ    = landCenter;
                int ourTop  = ourZ + PersonHeight;
                int testTop = checkTop;

                if (ourZ + PersonHeight > testTop)
                {
                    testTop = ourZ + PersonHeight;
                }

                bool shouldCheck = true;

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

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

                if (shouldCheck && IsOk(ignoreDoors, ourZ, testTop, tiles, items))
                {
                    newZ     = ourZ;
                    moveIsOk = true;
                }
            }

            return(moveIsOk);
        }