Exemple #1
0
        public unsafe ushort[] ReadStaticArt(ushort graphic, out short width, out short height, out Rectangle imageRectangle)
        {
            imageRectangle.X      = 0;
            imageRectangle.Y      = 0;
            imageRectangle.Width  = 0;
            imageRectangle.Height = 0;

            (int length, int extra, bool patcher) = _file.SeekByEntryIndex(graphic + 0x4000);

            if (length == 0)
            {
                width = height = 0;

                return(_empty);
            }

            _file.Skip(4);
            width  = _file.ReadShort();
            height = _file.ReadShort();

            if (width == 0 || height == 0)
            {
                return(_empty);
            }

            ushort[] pixels      = new ushort[width * height];
            ushort * ptr         = (ushort *)_file.PositionAddress;
            ushort * lineoffsets = ptr;
            byte *   datastart   = (byte *)ptr + height * 2;
            int      x           = 0;
            int      y           = 0;

            ptr = (ushort *)(datastart + lineoffsets[0] * 2);
            int minX = width, minY = height, maxX = 0, maxY = 0;

            while (y < height)
            {
                ushort xoffs = *ptr++;
                ushort run   = *ptr++;

                if (xoffs + run >= 2048)
                {
                    pixels = new ushort[width * height];

                    return(pixels);
                }

                if (xoffs + run != 0)
                {
                    x += xoffs;
                    int pos = y * width + x;

                    for (int j = 0; j < run; j++)
                    {
                        ushort val = *ptr++;

                        if (val != 0)
                        {
                            val = (ushort)(0x8000 | val);
                        }
                        pixels[pos++] = val;
                    }

                    x += run;
                }
                else
                {
                    x = 0;
                    y++;
                    ptr = (ushort *)(datastart + lineoffsets[y] * 2);
                }
            }

            if (graphic >= 0x2053 && graphic <= 0x2062 || graphic >= 0x206A && graphic <= 0x2079)
            {
                for (int i = 0; i < width; i++)
                {
                    pixels[i] = 0;
                    pixels[(height - 1) * width + i] = 0;
                }

                for (int i = 0; i < height; i++)
                {
                    pixels[i * width]             = 0;
                    pixels[i * width + width - 1] = 0;
                }
            }
            else if (StaticFilters.IsCave(graphic) && Engine.Profile.Current != null && Engine.Profile.Current.EnableCaveBorder)
            {
                for (int yy = 0; yy < height; yy++)
                {
                    int startY = yy != 0 ? -1 : 0;
                    int endY   = yy + 1 < height ? 2 : 1;

                    for (int xx = 0; xx < width; xx++)
                    {
                        ref var pixel = ref pixels[yy * width + xx];

                        if (pixel == 0)
                        {
                            continue;
                        }

                        int startX = xx != 0 ? -1 : 0;
                        int endX   = xx + 1 < width ? 2 : 1;

                        for (int i = startY; i < endY; i++)
                        {
                            int currentY = yy + i;

                            for (int j = startX; j < endX; j++)
                            {
                                int currentX = xx + j;

                                ref var currentPixel = ref pixels[currentY * width + currentX];

                                if (currentPixel == 0u)
                                {
                                    pixel = 0x8000;
                                }
                            }
                        }
                    }
                }
Exemple #2
0
        private void AddTileToRenderList(GameObject obj, int worldX, int worldY, bool useObjectHandles, int maxZ)
        {
            for (; obj != null; obj = obj.Right)
            {
                if (obj.CurrentRenderIndex == _renderIndex || obj.IsDisposed)
                {
                    continue;
                }

                if (_updateDrawPosition && obj.CurrentRenderIndex != _renderIndex || obj.IsPositionChanged)
                {
                    obj.UpdateRealScreenPosition(_offset);
                }

                //obj.UseInRender = 0xFF;

                float drawX = obj.RealScreenPosition.X;
                float drawY = obj.RealScreenPosition.Y;

                if (drawX < _minPixel.X || drawX > _maxPixel.X)
                {
                    break;
                }

                int z          = obj.Z;
                int maxObjectZ = obj.PriorityZ;

                bool mounted  = false;
                bool ismobile = false;

                StaticTiles itemData     = default;
                bool        changinAlpha = false;

                switch (obj)
                {
                case Mobile mob:
                    maxObjectZ += Constants.DEFAULT_CHARACTER_HEIGHT;
                    ismobile    = true;
                    mounted     = mob.IsMounted;
                    break;

                default:

                    if (GameObjectHelper.TryGetStaticData(obj, out itemData))
                    {
                        if (obj is Static st)
                        {
                            if (StaticFilters.IsCave(st.OriginalGraphic))
                            {
                                if (Engine.Profile.Current.EnableCaveBorder && !st.IsBordered())
                                {
                                    st.SetBorder(true);
                                }
                                else if (!Engine.Profile.Current.EnableCaveBorder && st.IsBordered())
                                {
                                    st.SetBorder(false);
                                }
                            }
                            else if (StaticFilters.IsTree(st.OriginalGraphic))
                            {
                                if (Engine.Profile.Current.TreeToStumps && st.Graphic != Constants.TREE_REPLACE_GRAPHIC)
                                {
                                    st.SetGraphic(Constants.TREE_REPLACE_GRAPHIC);
                                }
                                else if (st.OriginalGraphic != st.Graphic && !Engine.Profile.Current.TreeToStumps)
                                {
                                    st.RestoreOriginalGraphic();
                                }
                            }
                        }

                        if (_noDrawRoofs && itemData.IsRoof)
                        {
                            if (_alphaChanged)
                            {
                                changinAlpha = obj.ProcessAlpha(0);
                            }
                            else
                            {
                                changinAlpha = obj.AlphaHue != 0;
                            }


                            if (!changinAlpha)
                            {
                                continue;
                            }
                        }

                        if ((Engine.Profile.Current.TreeToStumps && itemData.IsFoliage) || (Engine.Profile.Current.HideVegetation && StaticFilters.IsVegetation(obj.Graphic)))
                        {
                            continue;
                        }

                        maxObjectZ += itemData.Height;
                    }
                    break;
                }

                if (maxObjectZ > maxZ)
                {
                    break;
                }

                obj.CurrentRenderIndex = _renderIndex;

                bool iscorpse = !ismobile && obj is Item item && item.IsCorpse;

                if (!ismobile && !iscorpse && itemData.IsInternal)
                {
                    continue;
                }

                bool island = !ismobile && !iscorpse && obj is Land;

                if (!island && z >= _maxZ)
                {
                    if (!changinAlpha)
                    {
                        if (_alphaChanged)
                        {
                            changinAlpha = obj.ProcessAlpha(0);
                        }
                        else
                        {
                            changinAlpha = obj.AlphaHue != 0;
                        }

                        if (!changinAlpha)
                        {
                            continue;
                        }
                    }
                }

                int testMinZ = (int)drawY + z * 4;
                int testMaxZ = (int)drawY;

                if (island)
                {
                    Land t = obj as Land;
                    if (t.IsStretched)
                    {
                        testMinZ -= t.MinZ * 4;
                    }
                    else
                    {
                        testMinZ = testMaxZ;
                    }
                }
                else
                {
                    testMinZ = testMaxZ;
                }

                if (testMinZ < _minPixel.Y || testMaxZ > _maxPixel.Y)
                {
                    continue;
                }


                if (obj.Overheads != null && obj.Overheads.Count != 0)
                {
                    int offY;

                    if (ismobile && !mounted || iscorpse)
                    {
                        offY = -22;
                    }
                    else
                    {
                        switch (obj)
                        {
                        case Multi _:
                        case Static _: offY = -44;

                            break;
                        //case Item _:
                        //    offY = 44;

                        //break;
                        default: offY = 0;

                            break;
                        }
                    }

                    for (int i = 0; i < obj.Overheads.Count; i++)
                    {
                        TextOverhead v = obj.Overheads[i];
                        v.Bounds.X      = (v.Texture.Width >> 1) - 22;
                        v.Bounds.Y      = offY + v.Texture.Height;
                        v.Bounds.Width  = v.Texture.Width;
                        v.Bounds.Height = v.Texture.Height;
                        Overheads.AddOverhead(v);
                        offY += v.Texture.Height;

                        if (_alphaChanged)
                        {
                            if (v.TimeToLive > 0 && v.TimeToLive <= Constants.TIME_FADEOUT_TEXT)
                            {
                                if (!v.IsOverlapped)
                                {
                                    v.ProcessAlpha(0);
                                }
                            }
                            else if (!v.IsOverlapped && v.AlphaHue != 0xFF)
                            {
                                v.ProcessAlpha(0xFF);
                            }
                        }
                    }
                }


                if (ismobile || iscorpse)
                {
                    AddOffsetCharacterTileToRenderList(obj, useObjectHandles);
                }
                else if (itemData.IsFoliage)
                {
                    if (obj is Static st)
                    {
                        bool check = World.Player.X <= worldX && World.Player.Y <= worldY;

                        if (!check)
                        {
                            check = World.Player.Y <= worldY && World.Player.Position.X <= worldX + 1;

                            if (!check)
                            {
                                check = World.Player.X <= worldX && World.Player.Y <= worldY + 1;
                            }
                        }

                        if (check)
                        {
                            Rectangle rect = new Rectangle((int)drawX - st.FrameInfo.X,
                                                           (int)drawY - st.FrameInfo.Y,
                                                           st.FrameInfo.Width,
                                                           st.FrameInfo.Height);


                            check = rect.InRect(World.Player.GetOnScreenRectangle());
                        }

                        st.CharacterIsBehindFoliage = check;
                    }
                    else if (obj is Multi m)
                    {
                        bool check = World.Player.X <= worldX && World.Player.Y <= worldY;

                        if (!check)
                        {
                            check = World.Player.Y <= worldY && World.Player.Position.X <= worldX + 1;

                            if (!check)
                            {
                                check = World.Player.X <= worldX && World.Player.Y <= worldY + 1;
                            }
                        }

                        if (check)
                        {
                            Rectangle rect = new Rectangle((int)drawX - m.FrameInfo.X,
                                                           (int)drawY - m.FrameInfo.Y,
                                                           m.FrameInfo.Width,
                                                           m.FrameInfo.Height);


                            check = rect.InRect(World.Player.GetOnScreenRectangle());
                        }

                        m.CharacterIsBehindFoliage = check;
                    }
                }

                if (_alphaChanged && !changinAlpha)
                {
                    if (itemData.IsTranslucent)
                    {
                        obj.ProcessAlpha(178);
                    }
                    else if (!itemData.IsFoliage && obj.AlphaHue != 0xFF)
                    {
                        obj.ProcessAlpha(0xFF);
                    }
                }

                if (_renderListCount >= _renderList.Length)
                {
                    int newsize = _renderList.Length + 1000;
                    Array.Resize(ref _renderList, newsize);
                }

                if (useObjectHandles)
                {
                    obj.UseObjectHandles = (ismobile || iscorpse || obj is Item it && !it.IsLocked && !it.IsMulti) && !obj.ClosedObjectHandles;
                    _objectHandlesCount++;
                }
                else if (obj.ClosedObjectHandles)
                {
                    obj.ClosedObjectHandles = false;
                    obj.ObjectHandlesOpened = false;
                }
                else if (obj.UseObjectHandles)
                {
                    obj.ObjectHandlesOpened = false;
                    obj.UseObjectHandles    = false;
                }


                _renderList[_renderListCount] = obj;
                //obj.UseInRender = (byte) _renderIndex;
                _renderListCount++;
            }
        }
        private void AddTileToRenderList(GameObject obj, int worldX, int worldY, bool useObjectHandles, int maxZ)
        {
            for (; obj != null; obj = obj.Right)
            {
                if (obj.CurrentRenderIndex == _renderIndex || obj.IsDestroyed || !obj.AllowedToDraw)
                {
                    continue;
                }

                if (_updateDrawPosition && obj.CurrentRenderIndex != _renderIndex || obj.IsPositionChanged)
                {
                    obj.UpdateRealScreenPosition(_offset);
                }

                //obj.UseInRender = 0xFF;

                float drawX = obj.RealScreenPosition.X;
                float drawY = obj.RealScreenPosition.Y;

                if (drawX < _minPixel.X || drawX > _maxPixel.X)
                {
                    break;
                }

                int z          = obj.Z;
                int maxObjectZ = obj.PriorityZ;

                bool ismobile = false;

                StaticTiles itemData     = default;
                bool        changinAlpha = false;

                switch (obj)
                {
                case Mobile _:
                    maxObjectZ += Constants.DEFAULT_CHARACTER_HEIGHT;
                    ismobile    = true;
                    break;

                default:

                    if (GameObjectHelper.TryGetStaticData(obj, out itemData))
                    {
                        if (obj is Static st)
                        {
                            if (StaticFilters.IsCave(st.OriginalGraphic))
                            {
                                if (Engine.Profile.Current.EnableCaveBorder && !st.IsBordered())
                                {
                                    st.SetBorder(true);
                                }
                                else if (!Engine.Profile.Current.EnableCaveBorder && st.IsBordered())
                                {
                                    st.SetBorder(false);
                                }
                            }
                            else if (StaticFilters.IsTree(st.OriginalGraphic))
                            {
                                if (Engine.Profile.Current.TreeToStumps && st.Graphic != Constants.TREE_REPLACE_GRAPHIC)
                                {
                                    st.SetGraphic(Constants.TREE_REPLACE_GRAPHIC);
                                }
                                else if (st.OriginalGraphic != st.Graphic && !Engine.Profile.Current.TreeToStumps)
                                {
                                    st.RestoreOriginalGraphic();
                                }
                            }
                        }

                        if (_noDrawRoofs && itemData.IsRoof)
                        {
                            if (_alphaChanged)
                            {
                                changinAlpha = obj.ProcessAlpha(0);
                            }
                            else
                            {
                                changinAlpha = obj.AlphaHue != 0;
                            }


                            if (!changinAlpha)
                            {
                                continue;
                            }
                        }

                        if ((Engine.Profile.Current.TreeToStumps && itemData.IsFoliage) || (Engine.Profile.Current.HideVegetation && StaticFilters.IsVegetation(obj.Graphic)))
                        {
                            continue;
                        }

                        maxObjectZ += itemData.Height;
                    }
                    break;
                }

                if (maxObjectZ > maxZ)
                {
                    break;
                }

                obj.CurrentRenderIndex = _renderIndex;

                bool iscorpse = !ismobile && obj is Item item && item.IsCorpse;

                if (!ismobile && !iscorpse && itemData.IsInternal)
                {
                    continue;
                }

                bool island = !ismobile && !iscorpse && obj is Land;

                if (!island && z >= _maxZ)
                {
                    if (!changinAlpha)
                    {
                        if (_alphaChanged)
                        {
                            changinAlpha = obj.ProcessAlpha(0);
                        }
                        else
                        {
                            changinAlpha = obj.AlphaHue != 0;
                        }

                        if (!changinAlpha)
                        {
                            continue;
                        }
                    }
                }

                int testMinZ = (int)drawY + z * 4;
                int testMaxZ = (int)drawY;

                if (island)
                {
                    Land t = obj as Land;
                    if (t.IsStretched)
                    {
                        testMinZ -= t.MinZ * 4;
                    }
                    else
                    {
                        testMinZ = testMaxZ;
                    }
                }
                else
                {
                    testMinZ = testMaxZ;
                }

                if (testMinZ < _minPixel.Y || testMaxZ > _maxPixel.Y)
                {
                    continue;
                }


                if (obj.OverheadMessageContainer != null && !obj.OverheadMessageContainer.IsEmpty)
                {
                    _overheadManager.AddOverhead(obj.OverheadMessageContainer);
                }

                if (ismobile || iscorpse)
                {
                    AddOffsetCharacterTileToRenderList(obj, useObjectHandles);
                }
                else if (itemData.IsFoliage)
                {
                    bool check = World.Player.X <= worldX && World.Player.Y <= worldY;

                    if (!check)
                    {
                        check = World.Player.Y <= worldY && World.Player.Position.X <= worldX + 1;

                        if (!check)
                        {
                            check = World.Player.X <= worldX && World.Player.Y <= worldY + 1;
                        }
                    }

                    if (check)
                    {
                        Rectangle rect = new Rectangle((int)drawX - obj.FrameInfo.X,
                                                       (int)drawY - obj.FrameInfo.Y,
                                                       obj.FrameInfo.Width,
                                                       obj.FrameInfo.Height);

                        Rectangle r = World.Player.GetOnScreenRectangle();
                        check = Exstentions.InRect(ref rect, ref r);
                    }

                    if (obj is Static st)
                    {
                        st.CharacterIsBehindFoliage = check;
                    }
                    else if (obj is Multi m)
                    {
                        m.CharacterIsBehindFoliage = check;
                    }
                    else if (obj is Item it)
                    {
                        it.CharacterIsBehindFoliage = check;
                    }
                }

                if (_alphaChanged && !changinAlpha)
                {
                    if (itemData.IsTranslucent)
                    {
                        obj.ProcessAlpha(178);
                    }
                    else if (!itemData.IsFoliage && obj.AlphaHue != 0xFF)
                    {
                        obj.ProcessAlpha(0xFF);
                    }
                }

                if (_renderListCount >= _renderList.Length)
                {
                    int newsize = _renderList.Length + 1000;
                    //_renderList.Resize(newsize);
                    Array.Resize(ref _renderList, newsize);
                }

                if (useObjectHandles)
                {
                    obj.UseObjectHandles = (ismobile || iscorpse || obj is Item it && !it.IsLocked && !it.IsMulti) && !obj.ClosedObjectHandles;
                    _objectHandlesCount++;
                }
                else if (obj.ClosedObjectHandles)
                {
                    obj.ClosedObjectHandles = false;
                    obj.ObjectHandlesOpened = false;
                }
                else if (obj.UseObjectHandles)
                {
                    obj.ObjectHandlesOpened = false;
                    obj.UseObjectHandles    = false;
                }


                //ref var weak = ref _renderList[_renderListCount];

                //if (weak == null)
                //    weak = new WeakReference<GameObject>(obj);
                //else
                //    weak.SetTarget(obj);

                _renderList[_renderListCount] = obj;
                //_renderList.Enqueue(obj);
                //obj.UseInRender = (byte) _renderIndex;
                _renderListCount++;
            }
        }