Beispiel #1
0
        /// <summary>Scans the map in chunks, evaluating all actors in each.</summary>
        CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var map         = world.Map;
            var checkRadius = powerDecision.CoarseScanRadius;

            for (var i = 0; i < map.MapSize.X; i += checkRadius)
            {
                for (var j = 0; j < map.MapSize.Y; j += checkRadius)
                {
                    var tl     = new MPos(i, j);
                    var br     = new MPos(i + checkRadius, j + checkRadius);
                    var region = new CellRegion(map.Grid.Type, tl, br);

                    // HACK: The AI code should not be messing with raw coordinate transformations
                    var wtl     = world.Map.CenterOfCell(tl.ToCPos(map));
                    var wbr     = world.Map.CenterOfCell(br.ToCPos(map));
                    var targets = world.ActorMap.ActorsInBox(wtl, wbr);

                    var frozenTargets = player.FrozenActorLayer != null?player.FrozenActorLayer.FrozenActorsInRegion(region) : Enumerable.Empty <FrozenActor>();

                    var consideredAttractiveness = powerDecision.GetAttractiveness(targets, player) + powerDecision.GetAttractiveness(frozenTargets, player);
                    if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
                    {
                        continue;
                    }

                    bestAttractiveness = consideredAttractiveness;
                    bestLocation       = new MPos(i, j).ToCPos(map);
                }
            }

            return(bestLocation);
        }
Beispiel #2
0
        static void ReadTiles(Map map, IniFile file, int2 fullSize)
        {
            var terrainInfo = (ITemplatedTerrainInfo)Game.ModData.DefaultTerrainInfo[map.Tileset];
            var mapSection  = file.GetSection("IsoMapPack5");

            var data        = Convert.FromBase64String(mapSection.Aggregate(string.Empty, (a, b) => a + b.Value));
            var cells       = (fullSize.X * 2 - 1) * fullSize.Y;
            var lzoPackSize = cells * 11 + 4;             // last 4 bytes contains a lzo pack header saying no more data is left
            var isoMapPack  = new byte[lzoPackSize];

            UnpackLZO(data, isoMapPack);

            var mf = new MemoryStream(isoMapPack);

            for (var i = 0; i < cells; i++)
            {
                var rx      = mf.ReadUInt16();
                var ry      = mf.ReadUInt16();
                var tilenum = mf.ReadUInt16();
                /*var zero1 = */ mf.ReadInt16();
                var subtile = mf.ReadUInt8();
                var z       = mf.ReadUInt8();
                /*var zero2 = */ mf.ReadUInt8();

                var dx      = rx - ry + fullSize.X - 1;
                var dy      = rx + ry - fullSize.X - 1;
                var mapCell = new MPos(dx / 2, dy);
                var cell    = mapCell.ToCPos(map);

                if (map.Tiles.Contains(cell))
                {
                    if (!terrainInfo.Templates.ContainsKey(tilenum))
                    {
                        tilenum = subtile = 0;
                    }

                    map.Tiles[cell]  = new TerrainTile(tilenum, subtile);
                    map.Height[cell] = z;
                }
            }
        }
Beispiel #3
0
        void UpdateTint(MPos uv)
        {
            var offset = rowStride * uv.V + 6 * uv.U;

            if (ignoreTint[offset])
            {
                var noTint = float3.Ones;
                for (var i = 0; i < 6; i++)
                {
                    var v = vertices[offset + i];
                    vertices[offset + i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, palette.TextureIndex, v.C, noTint);
                }

                return;
            }

            // Allow the terrain tint to vary linearly across the cell to smooth out the staircase effect
            // This is done by sampling the lighting the corners of the sprite, even though those pixels are
            // transparent for isometric tiles
            var tl      = worldRenderer.TerrainLighting;
            var pos     = map.CenterOfCell(uv.ToCPos(map));
            var step    = map.Grid.Type == MapGridType.RectangularIsometric ? 724 : 512;
            var weights = new[]
            {
                tl.TintAt(pos + new WVec(-step, -step, 0)),
                tl.TintAt(pos + new WVec(step, -step, 0)),
                tl.TintAt(pos + new WVec(step, step, 0)),
                tl.TintAt(pos + new WVec(-step, step, 0))
            };

            // Apply tint directly to the underlying vertices
            // This saves us from having to re-query the sprite information, which has not changed
            for (var i = 0; i < 6; i++)
            {
                var v = vertices[offset + i];
                vertices[offset + i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, palette.TextureIndex, v.C, weights[CornerVertexMap[i]]);
            }

            dirtyRows.Add(uv.V);
        }
Beispiel #4
0
        CellRegion CalculateVisibleCells(bool insideBounds)
        {
            var map = worldRenderer.World.Map;

            // Calculate the viewport corners in "projected wpos" (at ground level), and
            // this to an equivalent projected cell for the two corners
            var tl = map.CellContaining(worldRenderer.ProjectedPosition(TopLeft)).ToMPos(map);
            var br = map.CellContaining(worldRenderer.ProjectedPosition(BottomRight)).ToMPos(map);

            // Diamond tile shapes don't have straight edges, and so we need
            // an additional cell margin to include the cells that are half
            // visible on each edge.
            if (map.TileShape == TileShape.Diamond)
            {
                tl = new MPos(tl.U - 1, tl.V - 1);
                br = new MPos(br.U + 1, br.V + 1);
            }

            // Clamp to the visible map bounds, if requested
            if (insideBounds)
            {
                tl = map.Clamp(tl);
                br = map.Clamp(br);
            }

            // Cells can be pushed up from below if they have non-zero height.
            // Each height step is equivalent to 512 WDist units, which is
            // one MPos step for diamond cells, but only half a MPos step
            // for classic cells. Doh!
            var heightOffset = map.TileShape == TileShape.Diamond ? map.MaximumTerrainHeight : map.MaximumTerrainHeight / 2;

            br = new MPos(br.U, br.V + heightOffset);

            // Finally, make sure that this region doesn't extend outside the map area.
            tl = map.MapHeight.Value.Clamp(tl);
            br = map.MapHeight.Value.Clamp(br);

            return(new CellRegion(map.TileShape, tl.ToCPos(map), br.ToCPos(map)));
        }
Beispiel #5
0
        public void WorldLoaded(World w, WorldRenderer wr)
        {
            /* based on SmudgeLayer.cs */
            var first = sideSprites.First().Value.First();
            var sheet = first.Sheet;
            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.Sheet != sheet)))
                throw new InvalidDataException("Resource sprites span multiple sheets. Try loading their sequences earlier.");

            var blendMode = first.BlendMode;
            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.BlendMode != blendMode)))
                throw new InvalidDataException("Smudges specify different blend modes. "
                    + "Try using different smudge types for smudges that use different blend modes.");

            render = new TerrainSpriteLayer(w, wr, sheet, blendMode, wr.Palette(Info.Palette), wr.World.Type != WorldType.Editor);

            var tilesLayer = w.Map.Tiles;
            for (var v = 0; v < tilesLayer.Size.Height; v++)
            {
                for (var u = 0; u < tilesLayer.Size.Width; u++)
                {
                    var mpos = new MPos(u, v);
                    var tile = tilesLayer[mpos];

                    if (tile.Type == 143)
                    {
                        ClearSides clear = ClearSides.None;

                        if (u > 0)
                        {
                            var leftPos = new MPos(u - 1, v);
                            var leftTile = tilesLayer[leftPos];
                            if (!(leftTile.Type >= 126 && leftTile.Type <= 143) &&
                                !(leftTile.Type >= 160 && leftTile.Type <= 175))
                            {
                                clear |= ClearSides.Left;
                            }
                        }

                        if (v > 0)
                        {
                            var topPos = new MPos(u, v - 1);
                            var topTile = tilesLayer[topPos];
                            if (!(topTile.Type >= 126 && topTile.Type <= 143) &&
                                !(topTile.Type >= 160 && topTile.Type <= 175))
                            {
                                clear |= ClearSides.Top;
                            }
                        }

                        if (u < tilesLayer.Size.Width - 1)
                        {
                            var rightPos = new MPos(u + 1, v);
                            var rightTile = tilesLayer[rightPos];
                            if (!(rightTile.Type >= 126 && rightTile.Type <= 143) &&
                                !(rightTile.Type >= 160 && rightTile.Type <= 175))
                            {
                                clear |= ClearSides.Right;
                            }
                        }

                        if (v < tilesLayer.Size.Height - 1)
                        {
                            var bottomPos = new MPos(u, v + 1);
                            var bottomTile = tilesLayer[bottomPos];
                            if (!(bottomTile.Type >= 126 && bottomTile.Type <= 143) &&
                                !(bottomTile.Type >= 160 && bottomTile.Type <= 175))
                            {
                                clear |= ClearSides.Bottom;
                            }
                        }

                        if (clear != ClearSides.None)
                        {
                            CPos cpos = mpos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["rock"][SpriteMap[clear]];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == 175)
                    {
                        ClearSides clear = ClearSides.None;

                        if (u > 0)
                        {
                            var leftPos = new MPos(u - 1, v);
                            var leftTile = tilesLayer[leftPos];
                            if (!(leftTile.Type >= 160 && leftTile.Type <= 175))
                            {
                                clear |= ClearSides.Left;
                            }
                        }

                        if (v > 0)
                        {
                            var topPos = new MPos(u, v - 1);
                            var topTile = tilesLayer[topPos];
                            if (!(topTile.Type >= 160 && topTile.Type <= 175))
                            {
                                clear |= ClearSides.Top;
                            }
                        }

                        if (u < tilesLayer.Size.Width - 1)
                        {
                            var rightPos = new MPos(u + 1, v);
                            var rightTile = tilesLayer[rightPos];
                            if (!(rightTile.Type >= 160 && rightTile.Type <= 175))
                            {
                                clear |= ClearSides.Right;
                            }
                        }

                        if (v < tilesLayer.Size.Height - 1)
                        {
                            var bottomPos = new MPos(u, v + 1);
                            var bottomTile = tilesLayer[bottomPos];
                            if (!(bottomTile.Type >= 160 && bottomTile.Type <= 175))
                            {
                                clear |= ClearSides.Bottom;
                            }
                        }

                        if (clear != ClearSides.None)
                        {
                            CPos cpos = mpos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["rough"][SpriteMap[clear]];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == 159)
                    {
                        ClearSides clear = ClearSides.None;

                        if (u > 0)
                        {
                            var leftPos = new MPos(u - 1, v);
                            var leftTile = tilesLayer[leftPos];
                            if (!(leftTile.Type >= 144 && leftTile.Type <= 159))
                            {
                                clear |= ClearSides.Left;
                            }
                        }

                        if (v > 0)
                        {
                            var topPos = new MPos(u, v - 1);
                            var topTile = tilesLayer[topPos];
                            if (!(topTile.Type >= 144 && topTile.Type <= 159))
                            {
                                clear |= ClearSides.Top;
                            }
                        }

                        if (u < tilesLayer.Size.Width - 1)
                        {
                            var rightPos = new MPos(u + 1, v);
                            var rightTile = tilesLayer[rightPos];
                            if (!(rightTile.Type >= 144 && rightTile.Type <= 159))
                            {
                                clear |= ClearSides.Right;
                            }
                        }

                        if (v < tilesLayer.Size.Height - 1)
                        {
                            var bottomPos = new MPos(u, v + 1);
                            var bottomTile = tilesLayer[bottomPos];
                            if (!(bottomTile.Type >= 144 && bottomTile.Type <= 159))
                            {
                                clear |= ClearSides.Bottom;
                            }
                        }

                        if (clear != ClearSides.None)
                        {
                            CPos cpos = mpos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["dune"][SpriteMap[clear]];
                            render.Update(cpos, sprite);
                        }
                    }
                }
            }
        }
Beispiel #6
0
        static void ReadOverlay(Map map, IniFile file, int2 fullSize)
        {
            var overlaySection    = file.GetSection("OverlayPack");
            var overlayCompressed = Convert.FromBase64String(overlaySection.Aggregate(string.Empty, (a, b) => a + b.Value));
            var overlayPack       = new byte[1 << 18];
            var temp = new byte[1 << 18];

            UnpackLCW(overlayCompressed, overlayPack, temp);

            var overlayDataSection    = file.GetSection("OverlayDataPack");
            var overlayDataCompressed = Convert.FromBase64String(overlayDataSection.Aggregate(string.Empty, (a, b) => a + b.Value));
            var overlayDataPack       = new byte[1 << 18];

            UnpackLCW(overlayDataCompressed, overlayDataPack, temp);

            for (var y = 0; y < fullSize.Y; y++)
            {
                for (var x = fullSize.X * 2 - 2; x >= 0; x--)
                {
                    var dx = (ushort)x;
                    var dy = (ushort)(y * 2 + x % 2);

                    var uv = new MPos(dx / 2, dy);
                    var rx = (ushort)((dx + dy) / 2 + 1);
                    var ry = (ushort)(dy - rx + fullSize.X + 1);

                    if (!map.Resources.Contains(uv))
                    {
                        continue;
                    }

                    var idx         = rx + 512 * ry;
                    var overlayType = overlayPack[idx];
                    if (overlayType == 0xFF)
                    {
                        continue;
                    }

                    string actorType;
                    if (OverlayToActor.TryGetValue(overlayType, out actorType))
                    {
                        var ar = new ActorReference(actorType)
                        {
                            new LocationInit(uv.ToCPos(map)),
                            new OwnerInit("Neutral")
                        };

                        map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
                        continue;
                    }

                    var resourceType = ResourceFromOverlay
                                       .Where(kv => kv.Value.Contains(overlayType))
                                       .Select(kv => kv.Key)
                                       .FirstOrDefault();

                    if (resourceType != 0)
                    {
                        map.Resources[uv] = new ResourceTile(resourceType, overlayDataPack[idx]);
                        continue;
                    }

                    Console.WriteLine("{0} unknown overlay {1}", uv, overlayType);
                }
            }
        }
Beispiel #7
0
        public void WorldLoaded(World w, WorldRenderer wr)
        {
            /* based on SmudgeLayer.cs */
            var first = sideSprites.First().Value.First();
            var sheet = first.Sheet;

            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.Sheet != sheet)))
            {
                throw new InvalidDataException("Resource sprites span multiple sheets. Try loading their sequences earlier.");
            }

            var blendMode = first.BlendMode;

            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.BlendMode != blendMode)))
            {
                throw new InvalidDataException("Smudges specify different blend modes. "
                                               + "Try using different smudge types for smudges that use different blend modes.");
            }

            render = new TerrainSpriteLayer(w, wr, sheet, blendMode, wr.Palette(Info.Palette), wr.World.Type != WorldType.Editor);

            var tilesLayer = w.Map.Tiles;

            for (var v = 0; v < tilesLayer.Size.Height; v++)
            {
                for (var u = 0; u < tilesLayer.Size.Width; u++)
                {
                    var pos  = new MPos(u, v);
                    var tile = tilesLayer[pos];

                    if (tile.Type == D2MapUtils.RockTile)
                    {
                        var index = D2MapUtils.SmoothIndexForPos(tilesLayer, pos);
                        if (index != 15)
                        {
                            CPos   cpos   = pos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["rock"][index];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == D2MapUtils.DuneTile)
                    {
                        var index = D2MapUtils.SmoothIndexForPos(tilesLayer, pos);
                        if (index != 15)
                        {
                            CPos   cpos   = pos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["dune"][index];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == D2MapUtils.RoughTile)
                    {
                        var index = D2MapUtils.SmoothIndexForPos(tilesLayer, pos);
                        if (index != 15)
                        {
                            CPos   cpos   = pos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["rough"][index];
                            render.Update(cpos, sprite);
                        }
                    }
                }
            }
        }
Beispiel #8
0
        CellRegion CalculateVisibleCells(bool insideBounds)
        {
            var map = worldRenderer.World.Map;

            // Calculate the viewport corners in "projected wpos" (at ground level), and
            // this to an equivalent projected cell for the two corners
            var tl = map.CellContaining(worldRenderer.ProjectedPosition(TopLeft)).ToMPos(map);
            var br = map.CellContaining(worldRenderer.ProjectedPosition(BottomRight)).ToMPos(map);

            // Diamond tile shapes don't have straight edges, and so we need
            // an additional cell margin to include the cells that are half
            // visible on each edge.
            if (map.TileShape == TileShape.Diamond)
            {
                tl = new MPos(tl.U - 1, tl.V - 1);
                br = new MPos(br.U + 1, br.V + 1);
            }

            // Clamp to the visible map bounds, if requested
            if (insideBounds)
            {
                tl = map.Clamp(tl);
                br = map.Clamp(br);
            }

            // Cells can be pushed up from below if they have non-zero height.
            // Each height step is equivalent to 512 WDist units, which is
            // one MPos step for diamond cells, but only half a MPos step
            // for classic cells. Doh!
            var heightOffset = map.TileShape == TileShape.Diamond ? map.MaximumTerrainHeight : map.MaximumTerrainHeight / 2;
            br = new MPos(br.U, br.V + heightOffset);

            // Finally, make sure that this region doesn't extend outside the map area.
            tl = map.MapHeight.Value.Clamp(tl);
            br = map.MapHeight.Value.Clamp(br);

            return new CellRegion(map.TileShape, tl.ToCPos(map), br.ToCPos(map));
        }
		static void ReadTiles(Map map, IniFile file, int2 fullSize)
		{
			var tileset = Game.ModData.DefaultTileSets[map.Tileset];
			var mapSection = file.GetSection("IsoMapPack5");

			var data = Convert.FromBase64String(mapSection.Aggregate(string.Empty, (a, b) => a + b.Value));
			int cells = (fullSize.X * 2 - 1) * fullSize.Y;
			int lzoPackSize = cells * 11 + 4; // last 4 bytes contains a lzo pack header saying no more data is left
			var isoMapPack = new byte[lzoPackSize];
			UnpackLZO(data, isoMapPack);

			var mf = new MemoryStream(isoMapPack);
			for (var i = 0; i < cells; i++)
			{
				var rx = mf.ReadUInt16();
				var ry = mf.ReadUInt16();
				var tilenum = mf.ReadUInt16();
				/*var zero1 = */mf.ReadInt16();
				var subtile = mf.ReadUInt8();
				var z = mf.ReadUInt8();
				/*var zero2 = */mf.ReadUInt8();

				int dx = rx - ry + fullSize.X - 1;
				int dy = rx + ry - fullSize.X - 1;
				var mapCell = new MPos(dx / 2, dy);
				var cell = mapCell.ToCPos(map);

				if (map.Tiles.Contains(cell))
				{
					if (!tileset.Templates.ContainsKey(tilenum))
						tilenum = subtile = 0;

					map.Tiles[cell] = new TerrainTile(tilenum, subtile);
					map.Height[cell] = z;
				}
			}
		}
Beispiel #10
0
        public void SetBounds(MPos tl, MPos br)
        {
            // The tl and br coordinates are inclusive, but the Rectangle
            // is exclusive.  Pad the right and bottom edges to match.
            Bounds = Rectangle.FromLTRB(tl.U, tl.V, br.U + 1, br.V + 1);
            CellsInsideBounds = new CellRegion(TileShape, tl.ToCPos(this), br.ToCPos(this));

            // Directly calculate the projected map corners in world units avoiding unnecessary
            // conversions.  This abuses the definition that the width of the cell is always
            // 1024 units, and that the height of two rows is 2048 for classic cells and 1024
            // for diamond cells.
            var wtop = tl.V * 1024;
            var wbottom = (br.V + 1) * 1024;
            if (TileShape == TileShape.Diamond)
            {
                wtop /= 2;
                wbottom /= 2;
            }

            ProjectedTopLeft = new WPos(tl.U * 1024, wtop, 0);
            ProjectedBottomRight = new WPos(br.U * 1024 - 1, wbottom - 1, 0);
        }
        void PreSpawnClouds(World world)
        {
            var facing = 256 * info.WindDirection / 32;
            var delta  = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing));

            /*
             * The following codes find the middle point in map. Because clouds must
             * start from an edge to another edge, the paths of clouds
             * which contain this point will always be the longest path no matter the direction,
             * as long as the map is a symmetrical shape.
             *
             * For example, the middle point in map is "@", @ is (u = X/2, v = Y/2)
             * You can imagine any wind direction with all edges clouds possibly spawn.
             *
             *              ____X____
             *				|		|
             *				|		|
             *				|	@	Y
             *				|		|
             *				|_______|
             *
             * By using this longest path, we can figure out the number of clouds should
             * spawn when a certain cloud completely goes over a longest path, which should be
             * neither too little nor too big compared with the clouds per map-cell later
             * spawned by `SpawnCloud`.
             */
            var middlePoint       = new MPos(world.Map.MapSize.X / 2, world.Map.MapSize.Y / 2);
            var middlePointTarget = world.Map.CenterOfCell(middlePoint.ToCPos(world.Map));

            // lDistance and averageSpeed used are for loop condition below.
            var longestCloudDistance = System.Math.Abs(
                (world.Map.DistanceToEdge(middlePointTarget, -delta) + info.Cordon).Length
                + (world.Map.DistanceToEdge(middlePointTarget, delta) + info.Cordon).Length);
            var averageCloudSpeed = System.Math.Abs((int)info.Speed.Average(s => s.Length));

            var stepPerSpawn       = averageCloudSpeed * info.SpawnInterval;
            var stepPerSpawnVector = stepPerSpawn * delta / 1024;

            /*
             * Spawn clouds.
             *
             * Try to make clouds spawning cover the entire map, meanwhile
             * with some randomization. Choose random spawning point and
             * find startEdge, then add offset to let they go further to cover
             * the map. The offset will be increased to simulate the movement
             * the cloud would have made otherwise.
             */
            var offset = WVec.Zero;

            while (longestCloudDistance > 0)
            {
                var position = world.Map.ChooseRandomCell(world.SharedRandom);
                var target   = world.Map.CenterOfCell(position) + new WVec(0, 0, info.CruiseAltitude.Length);

                var startEdge = target - (world.Map.DistanceToEdge(target, -delta) + info.Cordon).Length * delta / 1024;
                startEdge += offset;
                var finishEdge = target + (world.Map.DistanceToEdge(target, delta) + info.Cordon).Length * delta / 1024;

                var animation = new Animation(world, info.Image, () => WAngle.FromFacing(facing));
                animation.PlayRepeating(info.Sequences.Random(world.SharedRandom));

                world.AddFrameEndTask(w => w.Add(new Cloud(world, animation, startEdge, finishEdge, facing, info)));

                offset += stepPerSpawnVector;
                longestCloudDistance -= stepPerSpawn;
            }
        }
Beispiel #12
0
        public void Resize(int width, int height)
        {
            var oldMapTiles = Tiles;
            var oldMapResources = Resources;
            var oldMapHeight = Height;
            var newSize = new Size(width, height);

            Tiles = CellLayer.Resize(oldMapTiles, newSize, oldMapTiles[MPos.Zero]);
            Resources = CellLayer.Resize(oldMapResources, newSize, oldMapResources[MPos.Zero]);
            Height = CellLayer.Resize(oldMapHeight, newSize, oldMapHeight[MPos.Zero]);
            MapSize = new int2(newSize);

            var tl = new MPos(0, 0);
            var br = new MPos(MapSize.X - 1, MapSize.Y - 1);
            AllCells = new CellRegion(Grid.Type, tl.ToCPos(this), br.ToCPos(this));
            SetBounds(new PPos(tl.U + 1, tl.V + 1), new PPos(br.U - 1, br.V - 1));
        }
Beispiel #13
0
        static void ReadOverlay(Map map, IniFile file, int2 fullSize)
        {
            var overlaySection = file.GetSection("OverlayPack");
            var overlayCompressed = Convert.FromBase64String(overlaySection.Aggregate(string.Empty, (a, b) => a + b.Value));
            var overlayPack = new byte[1 << 18];
            var temp = new byte[1 << 18];
            UnpackLCW(overlayCompressed, overlayPack, temp);

            var overlayDataSection = file.GetSection("OverlayDataPack");
            var overlayDataCompressed = Convert.FromBase64String(overlayDataSection.Aggregate(string.Empty, (a, b) => a + b.Value));
            var overlayDataPack = new byte[1 << 18];
            UnpackLCW(overlayDataCompressed, overlayDataPack, temp);

            for (var y = 0; y < fullSize.Y; y++)
            {
                for (var x = fullSize.X * 2 - 2; x >= 0; x--)
                {
                    var dx = (ushort)x;
                    var dy = (ushort)(y * 2 + x % 2);

                    var uv = new MPos(dx / 2, dy);
                    var rx = (ushort)((dx + dy) / 2 + 1);
                    var ry = (ushort)(dy - rx + fullSize.X + 1);

                    if (!map.Resources.Contains(uv))
                        continue;

                    var idx = rx + 512 * ry;
                    var overlayType = overlayPack[idx];
                    if (overlayType == 0xFF)
                        continue;

                    string actorType;
                    if (OverlayToActor.TryGetValue(overlayType, out actorType))
                    {
                        var ar = new ActorReference(actorType)
                        {
                            new LocationInit(uv.ToCPos(map)),
                            new OwnerInit("Neutral")
                        };

                        map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
                        continue;
                    }

                    var resourceType = ResourceFromOverlay
                        .Where(kv => kv.Value.Contains(overlayType))
                        .Select(kv => kv.Key)
                        .FirstOrDefault();

                    if (resourceType != 0)
                    {
                        map.Resources[uv] = new ResourceTile(resourceType, overlayDataPack[idx]);
                        continue;
                    }

                    Console.WriteLine("{0} unknown overlay {1}", uv, overlayType);
                }
            }
        }
Beispiel #14
0
        Edges GetEdges(MPos uv, Func<MPos, bool> isVisible)
        {
            if (!isVisible(uv))
                return notVisibleEdges;

            var cell = uv.ToCPos(map);

            // If a side is shrouded then we also count the corners.
            var edge = Edges.None;
            if (!isVisible((cell + new CVec(0, -1)).ToMPos(map))) edge |= Edges.Top;
            if (!isVisible((cell + new CVec(1, 0)).ToMPos(map))) edge |= Edges.Right;
            if (!isVisible((cell + new CVec(0, 1)).ToMPos(map))) edge |= Edges.Bottom;
            if (!isVisible((cell + new CVec(-1, 0)).ToMPos(map))) edge |= Edges.Left;

            var ucorner = edge & Edges.AllCorners;
            if (!isVisible((cell + new CVec(-1, -1)).ToMPos(map))) edge |= Edges.TopLeft;
            if (!isVisible((cell + new CVec(1, -1)).ToMPos(map))) edge |= Edges.TopRight;
            if (!isVisible((cell + new CVec(1, 1)).ToMPos(map))) edge |= Edges.BottomRight;
            if (!isVisible((cell + new CVec(-1, 1)).ToMPos(map))) edge |= Edges.BottomLeft;

            // RA provides a set of frames for tiles with shrouded
            // corners but unshrouded edges. We want to detect this
            // situation without breaking the edge -> corner enabling
            // in other combinations. The XOR turns off the corner
            // bits that are enabled twice, which gives the behavior
            // we want here.
            return info.UseExtendedIndex ? edge ^ ucorner : edge & Edges.AllCorners;
        }
Beispiel #15
0
        public void WorldLoaded(World w, WorldRenderer wr)
        {
            /* based on SmudgeLayer.cs */
            var first = sideSprites.First().Value.First();
            var sheet = first.Sheet;

            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.Sheet != sheet)))
            {
                throw new InvalidDataException("Resource sprites span multiple sheets. Try loading their sequences earlier.");
            }

            var blendMode = first.BlendMode;

            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.BlendMode != blendMode)))
            {
                throw new InvalidDataException("Smudges specify different blend modes. "
                                               + "Try using different smudge types for smudges that use different blend modes.");
            }

            render = new TerrainSpriteLayer(w, wr, sheet, blendMode, wr.Palette(Info.Palette), wr.World.Type != WorldType.Editor);

            var tilesLayer = w.Map.Tiles;

            for (var v = 0; v < tilesLayer.Size.Height; v++)
            {
                for (var u = 0; u < tilesLayer.Size.Width; u++)
                {
                    var mpos = new MPos(u, v);
                    var tile = tilesLayer[mpos];

                    if (tile.Type == 143)
                    {
                        ClearSides clear = ClearSides.None;

                        if (u > 0)
                        {
                            var leftPos  = new MPos(u - 1, v);
                            var leftTile = tilesLayer[leftPos];
                            if (!(leftTile.Type >= 126 && leftTile.Type <= 143) &&
                                !(leftTile.Type >= 160 && leftTile.Type <= 175))
                            {
                                clear |= ClearSides.Left;
                            }
                        }

                        if (v > 0)
                        {
                            var topPos  = new MPos(u, v - 1);
                            var topTile = tilesLayer[topPos];
                            if (!(topTile.Type >= 126 && topTile.Type <= 143) &&
                                !(topTile.Type >= 160 && topTile.Type <= 175))
                            {
                                clear |= ClearSides.Top;
                            }
                        }

                        if (u < tilesLayer.Size.Width - 1)
                        {
                            var rightPos  = new MPos(u + 1, v);
                            var rightTile = tilesLayer[rightPos];
                            if (!(rightTile.Type >= 126 && rightTile.Type <= 143) &&
                                !(rightTile.Type >= 160 && rightTile.Type <= 175))
                            {
                                clear |= ClearSides.Right;
                            }
                        }

                        if (v < tilesLayer.Size.Height - 1)
                        {
                            var bottomPos  = new MPos(u, v + 1);
                            var bottomTile = tilesLayer[bottomPos];
                            if (!(bottomTile.Type >= 126 && bottomTile.Type <= 143) &&
                                !(bottomTile.Type >= 160 && bottomTile.Type <= 175))
                            {
                                clear |= ClearSides.Bottom;
                            }
                        }

                        if (clear != ClearSides.None)
                        {
                            CPos   cpos   = mpos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["rock"][SpriteMap[clear]];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == 175)
                    {
                        ClearSides clear = ClearSides.None;

                        if (u > 0)
                        {
                            var leftPos  = new MPos(u - 1, v);
                            var leftTile = tilesLayer[leftPos];
                            if (!(leftTile.Type >= 160 && leftTile.Type <= 175))
                            {
                                clear |= ClearSides.Left;
                            }
                        }

                        if (v > 0)
                        {
                            var topPos  = new MPos(u, v - 1);
                            var topTile = tilesLayer[topPos];
                            if (!(topTile.Type >= 160 && topTile.Type <= 175))
                            {
                                clear |= ClearSides.Top;
                            }
                        }

                        if (u < tilesLayer.Size.Width - 1)
                        {
                            var rightPos  = new MPos(u + 1, v);
                            var rightTile = tilesLayer[rightPos];
                            if (!(rightTile.Type >= 160 && rightTile.Type <= 175))
                            {
                                clear |= ClearSides.Right;
                            }
                        }

                        if (v < tilesLayer.Size.Height - 1)
                        {
                            var bottomPos  = new MPos(u, v + 1);
                            var bottomTile = tilesLayer[bottomPos];
                            if (!(bottomTile.Type >= 160 && bottomTile.Type <= 175))
                            {
                                clear |= ClearSides.Bottom;
                            }
                        }

                        if (clear != ClearSides.None)
                        {
                            CPos   cpos   = mpos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["rough"][SpriteMap[clear]];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == 159)
                    {
                        ClearSides clear = ClearSides.None;

                        if (u > 0)
                        {
                            var leftPos  = new MPos(u - 1, v);
                            var leftTile = tilesLayer[leftPos];
                            if (!(leftTile.Type >= 144 && leftTile.Type <= 159))
                            {
                                clear |= ClearSides.Left;
                            }
                        }

                        if (v > 0)
                        {
                            var topPos  = new MPos(u, v - 1);
                            var topTile = tilesLayer[topPos];
                            if (!(topTile.Type >= 144 && topTile.Type <= 159))
                            {
                                clear |= ClearSides.Top;
                            }
                        }

                        if (u < tilesLayer.Size.Width - 1)
                        {
                            var rightPos  = new MPos(u + 1, v);
                            var rightTile = tilesLayer[rightPos];
                            if (!(rightTile.Type >= 144 && rightTile.Type <= 159))
                            {
                                clear |= ClearSides.Right;
                            }
                        }

                        if (v < tilesLayer.Size.Height - 1)
                        {
                            var bottomPos  = new MPos(u, v + 1);
                            var bottomTile = tilesLayer[bottomPos];
                            if (!(bottomTile.Type >= 144 && bottomTile.Type <= 159))
                            {
                                clear |= ClearSides.Bottom;
                            }
                        }

                        if (clear != ClearSides.None)
                        {
                            CPos   cpos   = mpos.ToCPos(w.Map);
                            Sprite sprite = sideSprites["dune"][SpriteMap[clear]];
                            render.Update(cpos, sprite);
                        }
                    }
                }
            }
        }
        public void WorldLoaded(World w, WorldRenderer wr)
        {
            /* based on SmudgeLayer.cs */
            var first   = sideSprites.First().Value.First();
            var sheet2D = first.Sheet2D;
            //this check can be removed
            //if (sideSprites.Values.Any(sprites => sprites.Any(s => s.Sheet2D != sheet2D)))
            //	throw new InvalidDataException("Resource sprites span multiple sheets. Try loading their sequences earlier.");

            var blendMode = first.BlendMode;

            if (sideSprites.Values.Any(sprites => sprites.Any(s => s.BlendMode != blendMode)))
            {
                throw new InvalidDataException("Smudges specify different blend modes. "
                                               + "Try using different smudge types for smudges that use different blend modes.");
            }

            // using base TerrainRenderer to avoid using one more renderer through TerrainSpriteLayer class as it was done.
            //var terrainRenderer = w.WorldActor.TraitOrDefault<IRenderTerrain>(); //to get TerrainRenderer.cs class
            //TerrainRenderer = terrainRenderer.GetTerrainSpriteLayerRenderer(); //get all Sprites that it has from tileset\*.yaml file
            //render = TerrainRenderer[Info.Palette];
            // Nowadays way to accomplish task is to add one more renderer through TerrainSpriteLayer class and we get one more Batch for total terrain vertexes
            render = new TerrainSpriteLayer(w, wr, sheet2D, blendMode, wr.Palette(Info.Palette), wr.World.Type != WorldType.Editor, "D2TerrainLayer");
            MersenneTwister random = new MersenneTwister();

            var tilesLayer = w.Map.Tiles;

            for (var v = 0; v < tilesLayer.Size.Height; v++)
            {
                for (var u = 0; u < tilesLayer.Size.Width; u++)
                {
                    var pos  = new MPos(u, v);
                    var tile = tilesLayer[pos];

                    if (tile.Type == D2MapUtils.RockTile)
                    {
                        var index = D2MapUtils.SmoothIndexForPos(tilesLayer, pos);
                        if (index != 15)
                        {
                            CPos cpos = pos.ToCPos(w.Map);
                            //ushort sdf;
                            //int ffd = (128 + Convert.ToInt32(index));
                            //sdf = Convert.ToUInt16(ffd);
                            //var t = new TerrainTile(sdf, 0);
                            //Sprite sprite = wr.Theater.TileSprite(t, 0);
                            Sprite sprite = sideSprites["rock"][index];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == D2MapUtils.DuneTile)
                    {
                        var index = D2MapUtils.SmoothIndexForPos(tilesLayer, pos);
                        if (index != 15)
                        {
                            CPos cpos = pos.ToCPos(w.Map);
                            //ushort sdf;
                            //int ffd = (144 + Convert.ToInt32(index)); //158
                            //sdf = Convert.ToUInt16(ffd);
                            //var t = new TerrainTile(sdf, 0);
                            //Sprite sprite = wr.Theater.TileSprite(t, 0);
                            Sprite sprite = sideSprites["dune"][index];
                            render.Update(cpos, sprite);
                        }
                    }

                    if (tile.Type == D2MapUtils.RoughTile)
                    {
                        var index = D2MapUtils.SmoothIndexForPos(tilesLayer, pos);
                        if (index != 15)
                        {
                            CPos cpos = pos.ToCPos(w.Map);
                            //ushort sdf;
                            //int ffd = (160 + Convert.ToInt32(index));
                            //sdf = Convert.ToUInt16(ffd);
                            //var t = new TerrainTile(sdf, 0);
                            //Sprite sprite = wr.Theater.TileSprite(t, 0);
                            Sprite sprite = sideSprites["rough"][index];
                            render.Update(cpos, sprite);
                        }
                    }
                }
            }
        }