Beispiel #1
0
        public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
        {
            var isDiamond = map.TileShape == TileShape.Diamond;
            var b = map.Bounds;

            // Fudge the heightmap offset by adding as much extra as we need / can.
            // This tries to correct for our incorrect assumption that MPos == PPos
            var heightOffset = Math.Min(map.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
            var width = b.Width;
            var height = b.Height + heightOffset;

            var bitmapWidth = width;
            if (isDiamond)
                bitmapWidth = 2 * bitmapWidth - 1;

            if (!actualSize)
                bitmapWidth = height = Exts.NextPowerOf2(Math.Max(bitmapWidth, height));

            var terrain = new Bitmap(bitmapWidth, height);

            var bitmapData = terrain.LockBits(terrain.Bounds(),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            var mapTiles = map.MapTiles.Value;

            unsafe
            {
                var colors = (int*)bitmapData.Scan0;
                var stride = bitmapData.Stride / 4;
                for (var y = 0; y < height; y++)
                {
                    for (var x = 0; x < width; x++)
                    {
                        var uv = new MPos(x + b.Left, y + b.Top);
                        var type = tileset.GetTileInfo(mapTiles[uv]);
                        var leftColor = type != null ? type.LeftColor : Color.Black;

                        if (isDiamond)
                        {
                            // Odd rows are shifted right by 1px
                            var dx = uv.V & 1;
                            var rightColor = type != null ? type.RightColor : Color.Black;
                            if (x + dx > 0)
                                colors[y * stride + 2 * x + dx - 1] = leftColor.ToArgb();

                            if (2 * x + dx < stride)
                                colors[y * stride + 2 * x + dx] = rightColor.ToArgb();
                        }
                        else
                            colors[y * stride + x] = leftColor.ToArgb();
                    }
                }
            }

            terrain.UnlockBits(bitmapData);
            return terrain;
        }
Beispiel #2
0
        public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion, Shroud shroud)
        {
            actor = self;
            isVisibleTest = shroud.IsVisibleTest(footprintRegion);

            Footprint = footprint;
            CenterPosition = self.CenterPosition;
            Bounds = self.Bounds;

            UpdateVisibility();
        }
        public FrozenActor(Actor self, MPos[] footprint, Shroud shroud)
        {
            actor = self;
            this.shroud = shroud;

            // Consider all cells inside the map area (ignoring the current map bounds)
            Footprint = footprint
                .Where(m => shroud.Contains(m))
                .ToArray();

            CenterPosition = self.CenterPosition;
            Bounds = self.Bounds;

            UpdateVisibility();
        }
Beispiel #4
0
		public void Update(MPos uv, Sprite sprite, float2 pos)
		{
			if (sprite != null)
			{
				if (sprite.Sheet != Sheet)
					throw new InvalidDataException("Attempted to add sprite from a different sheet");

				if (sprite.BlendMode != BlendMode)
					throw new InvalidDataException("Attempted to add sprite with a different blend mode");
			}
			else
				sprite = emptySprite;

			var offset = rowStride * uv.V + 4 * uv.U;
			Util.FastCreateQuad(vertices, pos, sprite, palette.TextureIndex, offset, sprite.Size);

			dirtyRows.Add(uv.V);
		}
        static void ReadWaypoints(Map map, IniFile file, int2 fullSize)
        {
            var waypointsSection = file.GetSection("Waypoints", true);

            foreach (var kv in waypointsSection)
            {
                var pos  = int.Parse(kv.Value);
                var ry   = pos / 1000;
                var rx   = pos - ry * 1000;
                var dx   = rx - ry + fullSize.X - 1;
                var dy   = rx + ry - fullSize.X - 1;
                var cell = new MPos(dx / 2, dy).ToCPos(map);

                var ar = new ActorReference((!int.TryParse(kv.Key, out var wpindex) || wpindex > 7) ? "waypoint" : "mpspawn");
                ar.Add(new LocationInit(cell));
                ar.Add(new OwnerInit("Neutral"));

                map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
            }
        }
        public void Update(MPos uv, Sprite sprite, float3 pos)
        {
            if (sprite != null)
            {
                //if (sprite.Sheet != Sheet)
                //	throw new InvalidDataException("Attempted to add sprite from a different sheet");

                if (sprite.BlendMode != BlendMode)
                {
                    throw new InvalidDataException("Attempted to add sprite with a different blend mode");
                }
            }
            else
            {
                sprite = emptySprite;
            }

            // The vertex buffer does not have geometry for cells outside the map
            if (!map.Tiles.Contains(uv))
            {
                return;
            }
            SamplerPointer textslot;


            var offset = TerrainFullRowLenInVertexRowsNums * uv.V + 6 * uv.U;

            if (sprite.SpriteType == 4)             //megaTexture
            {
                Sprite tmpsp = new Sprite(sprite.Sheet, new Rectangle((int)pos.X, (int)pos.Y, 16, 16), TextureChannel.RGBA);
                tmpsp.SpriteType = 4;
                textslot         = SetRenderStateForSprite(tmpsp);
                Util.FastCreateQuad(vertices, pos, tmpsp, textslot, palette.TextureIndex, offset, tmpsp.Size);
            }
            else
            {
                textslot = SetRenderStateForSprite(sprite);
                Util.FastCreateQuad(vertices, pos, sprite, textslot, palette.TextureIndex, offset, sprite.Size);
            }
            dirtyRows.Add(uv.V);
        }
Beispiel #7
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 #8
0
        public ChatBox(CPos position)
        {
            panel = new TextPanel(new MPos(8120, 2048), FontManager.Default, "stone")
            {
                Position = position
            };

            input = new TextBox("wooden", 45)
            {
                Position = position + new CPos(-800, 2048 + 512, 0),
                OnEnter  = SendText
            };
            send = new Button("send", "wooden", SendText)
            {
                Position = position + new CPos(8120 - 800, 2048 + 512, 0)
            };

            Position        += new CPos(0, 5632, 0);
            Bounds           = new MPos(8120 + 512, 4096);
            SelectableBounds = Bounds;
        }
Beispiel #9
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 #10
0
        public ShroudLayer(MPos bounds)
        {
            Bounds = bounds * new MPos(2, 2);

            Shroud = new Shroud[Bounds.X, Bounds.Y];
            for (int x = 0; x < Bounds.X; x++)
            {
                for (int y = 0; y < Bounds.Y; y++)
                {
                    var shroud = new Shroud(new MPos(x, y));

                    var list = new List <Shroud>()
                    {
                        shroud
                    };

                    Shroud[x, y] = shroud;

                    listenerPositions.Add(new MPos(x, y), list);
                }
            }
        }
Beispiel #11
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 #12
0
        void Initialize(string mapFile)
        {
            mapSize = new Size(stream.ReadUInt16(), stream.ReadUInt16());

            tileSet = rules.TileSets["ARRAKIS"];

            map = new Map(tileSet, mapSize.Width + 2 * MapCordonWidth, mapSize.Height + 2 * MapCordonWidth)
            {
                Title  = Path.GetFileNameWithoutExtension(mapFile),
                Author = "Westwood Studios"
            };

            var tl = new MPos(MapCordonWidth, MapCordonWidth);
            var br = new MPos(MapCordonWidth + mapSize.Width - 1, MapCordonWidth + mapSize.Height - 1);

            map.SetBounds(tl, br);

            // Get all templates from the tileset YAML file that have at least one frame and an Image property corresponding to the requested tileset
            // Each frame is a tile from the Dune 2000 tileset files, with the Frame ID being the index of the tile in the original file
            tileSetsFromYaml = tileSet.Templates.Where(t => t.Value.Frames != null &&
                                                       t.Value.Images[0].ToLower() == tilesetName.ToLower()).Select(ts => ts.Value).ToList();
        }
Beispiel #13
0
        public Tooltip(string title, params string[] text)
        {
            font = FontManager.Default;

            this.title = new TextLine(CPos.Zero, font);
            this.title.WriteText(title);
            this.text = new TextBlock(CPos.Zero, font, TextOffset.LEFT);
            this.text.Add(text);

            var width = font.GetWidth(this.title.Text);

            if (text.Length != 0)
            {
                var textWidth = this.text.Bounds.X;

                if (textWidth > width)
                {
                    width = textWidth;
                }
            }

            bounds = new MPos(2 * margin + width, 2 * margin + (text.Length + 1) * font.MaxHeight / 2 + text.Length * font.HeightGap / 2);
        }
Beispiel #14
0
        // NOTE: pos required to be in map bounds
        bool AnyActorsAt(MPos uv, CPos a, CellLayer <InfluenceNode> layer, SubCell sub, bool checkTransient)
        {
            var always = sub == SubCell.FullCell || sub == SubCell.Any;

            for (var i = layer[uv]; i != null; i = i.Next)
            {
                if (always || i.SubCell == sub || i.SubCell == SubCell.FullCell)
                {
                    if (checkTransient)
                    {
                        return(true);
                    }

                    var pos = i.Actor.TraitOrDefault <IPositionable>();
                    if (pos == null || !pos.IsLeavingCell(a, i.SubCell))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #15
0
		static void ReadTerrainActors(Map map, IniFile file, int2 fullSize)
		{
			var terrainSection = file.GetSection("Terrain", true);
			foreach (var kv in terrainSection)
			{
				var pos = int.Parse(kv.Key);
				var ry = pos / 1000;
				var rx = pos - ry * 1000;
				var dx = rx - ry + fullSize.X - 1;
				var dy = rx + ry - fullSize.X - 1;
				var cell = new MPos(dx / 2, dy).ToCPos(map);
				var name = kv.Value.ToLowerInvariant();

				var ar = new ActorReference(name);
				ar.Add(new LocationInit(cell));
				ar.Add(new OwnerInit("Neutral"));

				if (!map.Rules.Actors.ContainsKey(name))
					Console.WriteLine("Ignoring unknown actor type: `{0}`".F(name));
				else
					map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
			}
		}
Beispiel #16
0
        public void Update(MPos uv, Sprite sprite, float3 pos, bool ignoreTint)
        {
            if (sprite != null)
            {
                if (sprite.Sheet != Sheet)
                {
                    throw new InvalidDataException("Attempted to add sprite from a different sheet");
                }

                if (sprite.BlendMode != BlendMode)
                {
                    throw new InvalidDataException("Attempted to add sprite with a different blend mode");
                }
            }
            else
            {
                sprite = emptySprite;
            }

            // The vertex buffer does not have geometry for cells outside the map
            if (!map.Tiles.Contains(uv))
            {
                return;
            }

            var offset = rowStride * uv.V + 6 * uv.U;

            Util.FastCreateQuad(vertices, pos, sprite, int2.Zero, palette.TextureIndex, offset, sprite.Size, float3.Ones);

            if (worldRenderer.TerrainLighting != null)
            {
                this.ignoreTint[offset] = ignoreTint;
                UpdateTint(uv);
            }

            dirtyRows.Add(uv.V);
        }
        public static bool IsVisibleIgnoringBounds(MPos position)
        {
            if (map == null)
            {
                return(false);
            }

            if (shroud.RevealAll)
            {
                return(true);
            }

            if (!position.InRange(lastCameraPosition, lastCameraPosition + lastCameraZoom))
            {
                return(false);
            }

            if (position.X < 0)
            {
                position = new MPos(0, position.Y);
            }
            else if (position.X >= mapBounds.X)
            {
                position = new MPos(mapBounds.X - 1, position.Y);
            }

            if (position.Y < 0)
            {
                position = new MPos(position.X, 0);
            }
            else if (position.Y >= mapBounds.Y)
            {
                position = new MPos(position.X, mapBounds.Y - 1);
            }

            return(visible[position.X, position.Y]);
        }
Beispiel #18
0
        List <Triangle> getTriangles(World world, CPos position, int height, MPos shroudPos, int radius)
        {
            var outerRadius = MathF.Sqrt(2) * radius * 1024;

            var pos1 = (shroudPos - new MPos(radius, radius)) / new MPos(2, 2);
            // Why MPos(1, 1) here? -> when 7/2=3, but we want 4. Thus (7+1)/2=4. (8+1)/2=4 so works for this case as well.
            var pos2 = (shroudPos + new MPos(radius, radius) + new MPos(1, 1)) / new MPos(2, 2);

            var triangles = new List <Triangle>();

            var walls = world.WallLayer.GetRange(pos1, pos2);

            foreach (var wall in walls)
            {
                if (wall.Physics.IsEmpty || wall.Type.IsTransparent)
                {
                    continue;
                }

                if (height > wall.Type.Height)
                {
                    continue;
                }

                var angleA = (position - wall.EndPointA).FlatAngle;
                var angleB = (position - wall.EndPointB).FlatAngle;

                var pointC = position + CPos.FromFlatAngle(angleA, outerRadius);
                var pointD = position + CPos.FromFlatAngle(angleB, outerRadius);

                triangles.Add(new Triangle(wall.EndPointA, wall.EndPointB, pointC));
                triangles.Add(new Triangle(wall.EndPointB, pointC, pointD));
            }

            return(triangles);
        }
Beispiel #19
0
        void UpdateTerrainColor(MPos uv)
        {
            var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ?
                            playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, radarTerrainLayers, uv);
            var leftColor  = colorPair.Left;
            var rightColor = colorPair.Right;

            var stride = radarSheet.Size.Width;

            unsafe
            {
                fixed(byte *colorBytes = &radarData[0])
                {
                    var colors = (int *)colorBytes;

                    if (isRectangularIsometric)
                    {
                        // Odd rows are shifted right by 1px
                        var dx = uv.V & 1;
                        if (uv.U + dx > 0)
                        {
                            colors[uv.V * stride + 2 * uv.U + dx - 1] = leftColor;
                        }

                        if (2 * uv.U + dx < stride)
                        {
                            colors[uv.V * stride + 2 * uv.U + dx] = rightColor;
                        }
                    }
                    else
                    {
                        colors[uv.V * stride + uv.U] = leftColor;
                    }
                }
            }
        }
Beispiel #20
0
        public static void PrintGeneratorMap(MPos bounds, NoiseMap noise, bool[,] dirty, int id)
        {
            using var image = new Bitmap(bounds.X, bounds.Y);

            for (int x = 0; x < bounds.X; x++)
            {
                for (int y = 0; y < bounds.Y; y++)
                {
                    System.Drawing.Color color = Color.Red;
                    if (!dirty[x, y])
                    {
                        var value = (int)(noise[x, y] * 255);
                        color = System.Drawing.Color.FromArgb(value, value, value);
                    }

                    image.SetPixel(x, y, color);
                }
            }
            var path = FileExplorer.Logs + "debugMaps/";

            checkDirectory(path);

            image.Save(path + $"generator{id}.png");
        }
		static void ReadTerrainActors(Map map, IniFile file, int2 fullSize)
		{
			var terrainSection = file.GetSection("Terrain", true);
			foreach (var kv in terrainSection)
			{
				var pos = int.Parse(kv.Key);
				var ry = pos / 1000;
				var rx = pos - ry * 1000;
				var dx = rx - ry + fullSize.X - 1;
				var dy = rx + ry - fullSize.X - 1;
				var cell = new MPos(dx / 2, dy).ToCPos(map);
				var name = kv.Value.ToLowerInvariant();

				if (ReplaceActors.ContainsKey(name))
				{
					name = ReplaceActors[name];
				}

				var ar = new ActorReference(name);
				ar.Add(new LocationInit(cell));
				ar.Add(new OwnerInit("Neutral"));

				if (!map.Rules.Actors.ContainsKey(name))
					Console.WriteLine("Ignoring unknown actor type: `{0}`".F(name));
				else
					map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
			}
		}
Beispiel #22
0
        public override bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits, int refundableValue)
        {
            if (IsTraitDisabled || IsTraitPaused)
            {
                return(false);
            }

            var info         = (ProductionAirdropInfo)Info;
            var owner        = self.Owner;
            var map          = owner.World.Map;
            var aircraftInfo = self.World.Map.Rules.Actors[info.ActorType].TraitInfo <AircraftInfo>();

            CPos   startPos;
            CPos   endPos;
            WAngle spawnFacing;

            if (info.BaselineSpawn)
            {
                var bounds   = map.Bounds;
                var center   = new MPos(bounds.Left + bounds.Width / 2, bounds.Top + bounds.Height / 2).ToCPos(map);
                var spawnVec = owner.HomeLocation - center;
                startPos = owner.HomeLocation + spawnVec * (Exts.ISqrt((bounds.Height * bounds.Height + bounds.Width * bounds.Width) / (4 * spawnVec.LengthSquared)));
                endPos   = startPos;
                var spawnDirection = new WVec((self.Location - startPos).X, (self.Location - startPos).Y, 0);
                spawnFacing = spawnDirection.Yaw;
            }
            else
            {
                // Start a fixed distance away: the width of the map.
                // This makes the production timing independent of spawnpoint
                var loc = self.Location.ToMPos(map);
                startPos    = new MPos(loc.U + map.Bounds.Width, loc.V).ToCPos(map);
                endPos      = new MPos(map.Bounds.Left, loc.V).ToCPos(map);
                spawnFacing = info.Facing;
            }

            // Assume a single exit point for simplicity
            var exit = self.Info.TraitInfos <ExitInfo>().First();

            foreach (var tower in self.TraitsImplementing <INotifyDelivery>())
            {
                tower.IncomingDelivery(self);
            }

            owner.World.AddFrameEndTask(w =>
            {
                if (!self.IsInWorld || self.IsDead)
                {
                    owner.PlayerActor.Trait <PlayerResources>().GiveCash(refundableValue);
                    return;
                }

                var actor = w.CreateActor(info.ActorType, new TypeDictionary
                {
                    new CenterPositionInit(w.Map.CenterOfCell(startPos) + new WVec(WDist.Zero, WDist.Zero, aircraftInfo.CruiseAltitude)),
                    new OwnerInit(owner),
                    new FacingInit(spawnFacing)
                });

                var exitCell = self.Location + exit.ExitCell;
                actor.QueueActivity(new Land(actor, Target.FromActor(self), WDist.Zero, WVec.Zero, info.Facing, clearCells: new CPos[1] {
                    exitCell
                }));
                actor.QueueActivity(new CallFunc(() =>
                {
                    if (!self.IsInWorld || self.IsDead)
                    {
                        owner.PlayerActor.Trait <PlayerResources>().GiveCash(refundableValue);
                        return;
                    }

                    foreach (var cargo in self.TraitsImplementing <INotifyDelivery>())
                    {
                        cargo.Delivered(self);
                    }

                    self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, productionType, inits));
                    Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName);
                    TextNotificationsManager.AddTransientLine(info.ReadyTextNotification, self.Owner);
                }));

                actor.QueueActivity(new FlyOffMap(actor, Target.FromCell(w, endPos)));
                actor.QueueActivity(new RemoveSelf());
            });

            return(true);
        }
Beispiel #23
0
        public PhysicsSector[] GetSectors(SimplePhysics physics)
        {
            if (physics.IsEmpty)
            {
                return(new PhysicsSector[0]);
            }

            var position = physics.Position - Map.Offset;

            // Add margin to be sure.
            var radiusX = physics.Type.RadiusX + 10;
            var radiusY = physics.Type.RadiusY + 10;
            var points  = new MPos[4];

            // Corner points

            points[0] = new MPos(position.X + radiusX, position.Y + radiusY);             // Sector 1 ( x| y)
            points[1] = new MPos(position.X + radiusX, position.Y - radiusY);             // Sector 2 ( x|-y)
            points[2] = new MPos(position.X - radiusX, position.Y - radiusY);             // Sector 3 (-x|-y)
            points[3] = new MPos(position.X - radiusX, position.Y + radiusY);             // Sector 4 (-x| y)

            // Corner sectors

            var sectorPositions = new MPos[4];

            for (int i = 0; i < 4; i++)
            {
                var point = points[i];

                var x = point.X / (SectorSize * 1024f);
                if (x < 0)
                {
                    x = 0;
                }
                if (x >= Bounds.X)
                {
                    x = Bounds.X - 1;
                }

                var y = point.Y / (SectorSize * 1024f);
                if (y < 0)
                {
                    y = 0;
                }
                if (y >= Bounds.Y)
                {
                    y = Bounds.Y - 1;
                }

                sectorPositions[i] = new MPos((int)Math.Floor(x), (int)Math.Floor(y));
            }

            // Determine Size of the Sector field to enter and the sector with the smallest value (sector 3)
            var startPosition = sectorPositions[2];
            // Difference plus one to have the field (e.g. 1 and 2 -> diff. 1 + 1 = 2 fields)
            var xSize = (sectorPositions[1].X - sectorPositions[2].X) + 1;
            var ySize = (sectorPositions[3].Y - sectorPositions[2].Y) + 1;

            var sectors = new List <PhysicsSector>();

            for (int x = 0; x < xSize; x++)
            {
                for (int y = 0; y < ySize; y++)
                {
                    var sector = Sectors[startPosition.X + x, startPosition.Y + y];
                    if (!sectors.Contains(sector))
                    {
                        sectors.Add(sector);
                    }
                }
            }

            return(sectors.ToArray());
        }
Beispiel #24
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 #25
0
        public byte[] SavePreview()
        {
            var tileset = Rules.TileSet;
            var resources = Rules.Actors["world"].TraitInfos<ResourceTypeInfo>()
                .ToDictionary(r => r.ResourceType, r => r.TerrainType);

            using (var stream = new MemoryStream())
            {
                var isRectangularIsometric = Grid.Type == MapGridType.RectangularIsometric;

                // Fudge the heightmap offset by adding as much extra as we need / can.
                // This tries to correct for our incorrect assumption that MPos == PPos
                var heightOffset = Math.Min(Grid.MaximumTerrainHeight, MapSize.Y - Bounds.Bottom);
                var width = Bounds.Width;
                var height = Bounds.Height + heightOffset;

                var bitmapWidth = width;
                if (isRectangularIsometric)
                    bitmapWidth = 2 * bitmapWidth - 1;

                using (var bitmap = new Bitmap(bitmapWidth, height))
                {
                    var bitmapData = bitmap.LockBits(bitmap.Bounds(),
                        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

                    unsafe
                    {
                        var colors = (int*)bitmapData.Scan0;
                        var stride = bitmapData.Stride / 4;
                        Color leftColor, rightColor;

                        for (var y = 0; y < height; y++)
                        {
                            for (var x = 0; x < width; x++)
                            {
                                var uv = new MPos(x + Bounds.Left, y + Bounds.Top);
                                var resourceType = Resources[uv].Type;
                                if (resourceType != 0)
                                {
                                    // Cell contains resources
                                    string res;
                                    if (!resources.TryGetValue(resourceType, out res))
                                        continue;

                                    leftColor = rightColor = tileset[tileset.GetTerrainIndex(res)].Color;
                                }
                                else
                                {
                                    // Cell contains terrain
                                    var type = tileset.GetTileInfo(Tiles[uv]);
                                    leftColor = type != null ? type.LeftColor : Color.Black;
                                    rightColor = type != null ? type.RightColor : Color.Black;
                                }

                                if (isRectangularIsometric)
                                {
                                    // Odd rows are shifted right by 1px
                                    var dx = uv.V & 1;
                                    if (x + dx > 0)
                                        colors[y * stride + 2 * x + dx - 1] = leftColor.ToArgb();

                                    if (2 * x + dx < stride)
                                        colors[y * stride + 2 * x + dx] = rightColor.ToArgb();
                                }
                                else
                                    colors[y * stride + x] = leftColor.ToArgb();
                            }
                        }
                    }

                    bitmap.UnlockBits(bitmapData);
                    bitmap.Save(stream, ImageFormat.Png);
                }

                return stream.ToArray();
            }
        }
Beispiel #26
0
 public bool Contains(MPos uv)
 {
     return Bounds.Contains(uv.U, uv.V);
 }
Beispiel #27
0
        void PostInit()
        {
            rules = Exts.Lazy(() =>
            {
                try
                {
                    return Game.ModData.RulesetCache.LoadMapRules(this);
                }
                catch (Exception e)
                {
                    InvalidCustomRules = true;
                    Log.Write("debug", "Failed to load rules for {0} with error {1}", Title, e.Message);
                }

                return Game.ModData.DefaultRules;
            });

            cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]);

            var tl = new MPos(Bounds.Left, Bounds.Top).ToCPos(this);
            var br = new MPos(Bounds.Right - 1, Bounds.Bottom - 1).ToCPos(this);
            Cells = new CellRegion(TileShape, tl, br);

            CustomTerrain = new CellLayer<byte>(this);
            foreach (var uv in Cells.MapCoords)
                CustomTerrain[uv] = byte.MaxValue;

            var leftDelta = TileShape == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
            var topDelta = TileShape == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
            var rightDelta = TileShape == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
            var bottomDelta = TileShape == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
            CellCorners = CellCornerHalfHeights.Select(ramp => new WVec[]
            {
                leftDelta + new WVec(0, 0, 512 * ramp[0]),
                topDelta + new WVec(0, 0, 512 * ramp[1]),
                rightDelta + new WVec(0, 0, 512 * ramp[2]),
                bottomDelta + new WVec(0, 0, 512 * ramp[3])
            }).ToArray();
        }
Beispiel #28
0
        static void ReadActors(Map map, IniFile file, string type, int2 fullSize)
        {
            var structuresSection = file.GetSection(type, true);

            foreach (var kv in structuresSection)
            {
                var isDeployed = false;
                var entries    = kv.Value.Split(',');

                var name = entries[1].ToLowerInvariant();

                if (DeployableActors.ContainsKey(name))
                {
                    name       = DeployableActors[name];
                    isDeployed = true;
                }

                if (ReplaceActors.ContainsKey(name))
                {
                    name = ReplaceActors[name];
                }

                var health = short.Parse(entries[2]);
                var rx     = int.Parse(entries[3]);
                var ry     = int.Parse(entries[4]);
                var facing = byte.Parse(entries[5]) + 96;

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

                var ar = new ActorReference(name)
                {
                    new LocationInit(cell),
                    new OwnerInit("Neutral")
                };

                if (health != 256)
                {
                    ar.Add(new HealthInit(100 * health / 256));
                }

                if (facing != 96)
                {
                    ar.Add(new FacingInit(facing));
                }

                if (isDeployed)
                {
                    ar.Add(new DeployStateInit(DeployState.Deployed));
                }

                if (!map.Rules.Actors.ContainsKey(name))
                {
                    Console.WriteLine("Ignoring unknown actor type: `{0}`".F(name));
                }
                else
                {
                    map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
                }
            }
        }
        static void ReadOverlay(Map map, IniFile file, int2 fullSize)
        {
            var overlaySection    = file.GetSection("OverlayPack");
            var overlayCompressed = Convert.FromBase64String(string.Concat(overlaySection.Select(kvp => kvp.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(string.Concat(overlayDataSection.Select(kvp => kvp.Value)));
            var overlayDataPack       = new byte[1 << 18];

            UnpackLCW(overlayDataCompressed, overlayDataPack, temp);

            var overlayIndex = new CellLayer <int>(map);

            overlayIndex.Clear(0xFF);

            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;
                    }

                    overlayIndex[uv] = rx + 512 * ry;
                }
            }

            foreach (var cell in map.AllCells)
            {
                var overlayType = overlayPack[overlayIndex[cell]];
                if (overlayType == 0xFF)
                {
                    continue;
                }

                if (OverlayToActor.TryGetValue(overlayType, out var actorType))
                {
                    if (string.IsNullOrEmpty(actorType))
                    {
                        continue;
                    }

                    var shape = new Size(1, 1);
                    if (OverlayShapes.TryGetValue(overlayType, out shape))
                    {
                        // Only import the top-left cell of multi-celled overlays
                        var aboveType = overlayPack[overlayIndex[cell - new CVec(1, 0)]];
                        if (shape.Width > 1 && aboveType != 0xFF)
                        {
                            if (OverlayToActor.TryGetValue(aboveType, out var a) && a == actorType)
                            {
                                continue;
                            }
                        }

                        var leftType = overlayPack[overlayIndex[cell - new CVec(0, 1)]];
                        if (shape.Height > 1 && leftType != 0xFF)
                        {
                            if (OverlayToActor.TryGetValue(leftType, out var a) && a == actorType)
                            {
                                continue;
                            }
                        }
                    }

                    // Fix position of vein hole actors
                    var location = cell;
                    if (actorType == "veinhole")
                    {
                        location -= new CVec(1, 1);
                    }

                    var ar = new ActorReference(actorType)
                    {
                        new LocationInit(location),
                        new OwnerInit("Neutral")
                    };

                    if (OverlayToHealth.TryGetValue(overlayType, out var damageState))
                    {
                        var health = 100;
                        if (damageState == DamageState.Critical)
                        {
                            health = 25;
                        }
                        else if (damageState == DamageState.Heavy)
                        {
                            health = 50;
                        }
                        else if (damageState == DamageState.Medium)
                        {
                            health = 75;
                        }

                        if (health != 100)
                        {
                            ar.Add(new HealthInit(health));
                        }
                    }

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

                    continue;
                }

                // TS maps encode the non-harvestable border tiles as overlay
                // Only convert to vein resources if the overlay data specifies non-border frames
                if (overlayType == 0x7E)
                {
                    var frame = overlayDataPack[overlayIndex[cell]];
                    if (frame < 48 || frame > 60)
                    {
                        continue;
                    }

                    // Pick half or full density based on the frame
                    map.Resources[cell] = new ResourceTile(3, (byte)(frame == 52 ? 1 : 2));
                    continue;
                }

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

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

                Console.WriteLine("{0} unknown overlay {1}", cell, overlayType);
            }
        }
		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);

			var overlayIndex = new CellLayer<int>(map);
			overlayIndex.Clear(0xFF);

			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;

					overlayIndex[uv] = rx + 512 * ry;
				}
			}

			foreach (var cell in map.AllCells)
			{
				var overlayType = overlayPack[overlayIndex[cell]];
				if (overlayType == 0xFF)
					continue;

				string actorType;
				if (OverlayToActor.TryGetValue(overlayType, out actorType))
				{
					var shape = new Size(1, 1);
					if (OverlayShapes.TryGetValue(overlayType, out shape))
					{
						// Only import the top-left cell of multi-celled overlays
						var aboveType = overlayPack[overlayIndex[cell - new CVec(1, 0)]];
						if (shape.Width > 1 && aboveType != 0xFF)
						{
							string a;
							if (OverlayToActor.TryGetValue(aboveType, out a) && a == actorType)
								continue;
						}

						var leftType = overlayPack[overlayIndex[cell - new CVec(0, 1)]];
						if (shape.Height > 1 && leftType != 0xFF)
						{
							string a;
							if (OverlayToActor.TryGetValue(leftType, out a) && a == actorType)
								continue;
						}
					}

					var ar = new ActorReference(actorType)
					{
						new LocationInit(cell),
						new OwnerInit("Neutral")
					};

					DamageState damageState;
					if (OverlayToHealth.TryGetValue(overlayType, out damageState))
					{
						var health = 100;
						if (damageState == DamageState.Critical)
							health = 25;
						else if (damageState == DamageState.Heavy)
							health = 50;
						else if (damageState == DamageState.Medium)
							health = 75;

						if (health != 100)
							ar.Add(new HealthInit(health));
					}

					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[cell] = new ResourceTile(resourceType, overlayDataPack[overlayIndex[cell]]);
					continue;
				}

				Console.WriteLine("{0} unknown overlay {1}", cell, overlayType);
			}
		}
		static void ReadWaypoints(Map map, IniFile file, int2 fullSize)
		{
			var waypointsSection = file.GetSection("Waypoints", true);
			foreach (var kv in waypointsSection)
			{
				var pos = int.Parse(kv.Value);
				var ry = pos / 1000;
				var rx = pos - ry * 1000;
				var dx = rx - ry + fullSize.X - 1;
				var dy = rx + ry - fullSize.X - 1;
				var cell = new MPos(dx / 2, dy).ToCPos(map);

				int wpindex;
				var ar = new ActorReference((!int.TryParse(kv.Key, out wpindex) || wpindex > 7) ? "waypoint" : "mpspawn");
				ar.Add(new LocationInit(cell));
				ar.Add(new OwnerInit("Neutral"));

				map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
			}
		}
		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 #33
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);
        }
Beispiel #34
0
        // editor magic.
        public void Resize(int width, int height)
        {
            var oldMapTiles = MapTiles.Value;
            var oldMapResources = MapResources.Value;
            var oldMapHeight = MapHeight.Value;
            var newSize = new Size(width, height);

            MapTiles = Exts.Lazy(() => CellLayer.Resize(oldMapTiles, newSize, oldMapTiles[MPos.Zero]));
            MapResources = Exts.Lazy(() => CellLayer.Resize(oldMapResources, newSize, oldMapResources[MPos.Zero]));
            MapHeight = Exts.Lazy(() => CellLayer.Resize(oldMapHeight, newSize, oldMapHeight[MPos.Zero]));
            MapSize = new int2(newSize);

            var tl = new MPos(0, 0).ToCPos(this);
            var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
            AllCells = new CellRegion(TileShape, tl, br);
        }
Beispiel #35
0
 public MPos Clamp(MPos uv)
 {
     var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1);
     return uv.Clamp(bounds);
 }
Beispiel #36
0
		public bool IsVisible(MPos uv)
		{
			if (!visibleCount.Contains(uv))
				return false;

			foreach (var puv in map.ProjectedCellsCovering(uv))
				if (IsVisible(puv))
					return true;

			return false;
		}
Beispiel #37
0
		public bool IsExplored(MPos uv)
		{
			if (!map.Contains(uv))
				return false;

			foreach (var puv in map.ProjectedCellsCovering(uv))
				if (IsExplored(puv))
					return true;

			return false;
		}
		static void ReadActors(Map map, IniFile file, string type, int2 fullSize)
		{
			var structuresSection = file.GetSection(type, true);
			foreach (var kv in structuresSection)
			{
				var isDeployed = false;
				var entries = kv.Value.Split(',');

				var name = entries[1].ToLowerInvariant();

				if (DeployableActors.ContainsKey(name))
				{
					name = DeployableActors[name];
					isDeployed = true;
				}

				if (ReplaceActors.ContainsKey(name))
				{
					name = ReplaceActors[name];
				}

				var health = short.Parse(entries[2]);
				var rx = int.Parse(entries[3]);
				var ry = int.Parse(entries[4]);
				var facing = (byte)(byte.Parse(entries[5]) + 96);

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

				var ar = new ActorReference(name)
				{
					new LocationInit(cell),
					new OwnerInit("Neutral"),
					new HealthInit(100 * health / 256),
					new FacingInit(facing),
				};

				if (isDeployed)
					ar.Add(new DeployStateInit(DeployState.Deployed));

				if (!map.Rules.Actors.ContainsKey(name))
					Console.WriteLine("Ignoring unknown actor type: `{0}`".F(name));
				else
					map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
			}
		}
Beispiel #39
0
 public void Update(MPos uv, Sprite sprite, PaletteReference palette, in float3 pos, float scale, float alpha, bool ignoreTint)
Beispiel #40
0
 public bool Contains(MPos uv)
 {
     // The first check ensures that the cell is within the valid map region, avoiding
     // potential crashes in deeper code.  All CellLayers have the same geometry, and
     // CustomTerrain is convenient.
     return CustomTerrain.Contains(uv) && ContainsAllProjectedCellsCovering(uv);
 }
Beispiel #41
0
        public void ResizeCordon(int left, int top, int right, int bottom)
        {
            Bounds = Rectangle.FromLTRB(left, top, right, bottom);

            var tl = new MPos(Bounds.Left, Bounds.Top).ToCPos(this);
            var br = new MPos(Bounds.Right - 1, Bounds.Bottom - 1).ToCPos(this);
            Cells = new CellRegion(TileShape, tl, br);
        }
Beispiel #42
0
        // Add the static resources defined in the map; if the map lives
        // in a world use AddCustomTerrain instead
        static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
        {
            var terrain = new Bitmap(terrainBitmap);
            var isDiamond = map.TileShape == TileShape.Diamond;
            var b = map.Bounds;

            // Fudge the heightmap offset by adding as much extra as we need / can
            // This tries to correct for our incorrect assumption that MPos == PPos
            var heightOffset = Math.Min(map.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
            var width = b.Width;
            var height = b.Height + heightOffset;

            var resources = resourceRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
                .ToDictionary(r => r.ResourceType, r => r.TerrainType);

            var bitmapData = terrain.LockBits(terrain.Bounds(),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            unsafe
            {
                var colors = (int*)bitmapData.Scan0;
                var stride = bitmapData.Stride / 4;
                for (var y = 0; y < height; y++)
                {
                    for (var x = 0; x < width; x++)
                    {
                        var uv = new MPos(x + b.Left, y + b.Top);
                        if (map.MapResources.Value[uv].Type == 0)
                            continue;

                        string res;
                        if (!resources.TryGetValue(map.MapResources.Value[uv].Type, out res))
                            continue;

                        var color = tileset[tileset.GetTerrainIndex(res)].Color.ToArgb();
                        if (isDiamond)
                        {
                            // Odd rows are shifted right by 1px
                            var dx = uv.V & 1;
                            if (x + dx > 0)
                                colors[y * stride + 2 * x + dx - 1] = color;

                            if (2 * x + dx < stride)
                                colors[y * stride + 2 * x + dx] = color;
                        }
                        else
                            colors[y * stride + x] = color;
                    }
                }
            }

            terrain.UnlockBits(bitmapData);

            return terrain;
        }
Beispiel #43
0
        public bool IsExplored(MPos uv)
        {
            if (!map.Contains(uv))
                return false;

            return map.ProjectedCellsCovering(uv).Any(isExploredTest);
        }
Beispiel #44
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 #45
0
 // NOTE: pos required to be in map bounds
 bool AnyActorsAt(MPos uv, CellLayer <InfluenceNode> layer)
 {
     return(layer[uv] != null);
 }
Beispiel #46
0
		public const int ChunkSize = 8;		// 8x8 chunks ==> 192x192 bitmaps.

		Bitmap RenderChunk(int u, int v)
		{
			var bitmap = new Bitmap(ChunkSize * TileSetRenderer.TileSize, ChunkSize * TileSetRenderer.TileSize);

			var data = bitmap.LockBits(bitmap.Bounds(),
				ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

			unsafe
			{
				var p = (int*)data.Scan0.ToPointer();
				var stride = data.Stride >> 2;

				for (var i = 0; i < ChunkSize; i++)
					for (var j = 0; j < ChunkSize; j++)
					{
						var ui = u * ChunkSize + i;
						var vj = v * ChunkSize + j;
						var uv = new MPos(ui, vj);
						if (uv.U >= Map.MapSize.X || uv.V >= Map.MapSize.Y)
						{
							for (var x = 0; x < TileSetRenderer.TileSize; x++)
								for (var y = 0; y < TileSetRenderer.TileSize; y++)
									p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] = 0;

							continue;
						}

						var tr = Map.MapTiles.Value[uv];
						var tile = TileSetRenderer.Data(tr.Type);
						if (tile == null)
							continue;

						var index = (tr.Index < tile.Length) ? tr.Index : (byte)0;
						var rawImage = tile[index];
						for (var x = 0; x < TileSetRenderer.TileSize; x++)
							for (var y = 0; y < TileSetRenderer.TileSize; y++)
								p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] =
									Palette.GetColor(rawImage[x + TileSetRenderer.TileSize * y]).ToArgb();

						if (Map.MapResources.Value[uv].Type != 0)
						{
							var resourceImage = ResourceTemplates[Map.MapResources.Value[uv].Type].Bitmap;
							var srcdata = resourceImage.LockBits(resourceImage.Bounds(),
								ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

							var q = (int*)srcdata.Scan0.ToPointer();
							var srcstride = srcdata.Stride >> 2;

							for (var x = 0; x < TileSetRenderer.TileSize; x++)
								for (var y = 0; y < TileSetRenderer.TileSize; y++)
								{
									var c = q[y * srcstride + x];
									if ((c & 0xff000000) != 0)	/* quick & dirty, i cbf doing real alpha */
										p[(j * TileSetRenderer.TileSize + y) * stride + i * TileSetRenderer.TileSize + x] = c;
								}

							resourceImage.UnlockBits(srcdata);
						}
					}
			}

			bitmap.UnlockBits(data);

			if (ShowGrid)
			{
				using (var g = SGraphics.FromImage(bitmap))
				{
					var ts = Game.ModData.Manifest.TileSize;
					var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
					ControlPaint.DrawGrid(g, rect, new Size(2, ts.Height), Color.DarkRed);
					ControlPaint.DrawGrid(g, rect, new Size(ts.Width, 2), Color.DarkRed);
					ControlPaint.DrawGrid(g, rect, new Size(ts.Width, ts.Height), Color.Red);
				}
			}

			return bitmap;
		}
Beispiel #47
0
        void place()
        {
            if (currentSelected != Selected.WALL && !game.World.IsInWorld(MouseInput.GamePosition))
            {
                return;
            }

            var pos    = MouseInput.GamePosition;
            var mpos   = pos.ToMPos();
            var bounds = game.World.Map.Bounds;

            switch (currentSelected)
            {
            case Selected.ACTOR:
                if (actorWidget.CurrentType == null)
                {
                    return;
                }

                if (actorWidget.RelativeHP == 0)
                {
                    return;
                }

                pos = actorWidget.Rasterization ? rasterizedPosition(pos) : pos;

                var team  = Math.Max(actorWidget.Team, (byte)0);
                var actor = ActorCache.Create(game.World, actorWidget.CurrentType, pos, team, actorWidget.Bot, false, actorWidget.RelativeHP);
                actor.Angle = actorWidget.RelativeFacing * Angle.MaxRange;

                game.World.Add(actor);
                break;

            case Selected.TILE:
                if (terrainWidget.CurrentType == null)
                {
                    return;
                }

                if (mpos.X < 0 || mpos.Y < 0 || mpos.X >= bounds.X || mpos.Y >= bounds.Y)
                {
                    return;
                }

                if (game.World.TerrainLayer.Terrain[mpos.X, mpos.Y].Type == terrainWidget.CurrentType)
                {
                    return;
                }

                var terrain = TerrainCache.Create(game.World, mpos, terrainWidget.CurrentType.ID);
                game.World.TerrainLayer.Set(terrain);

                WorldRenderer.CheckTerrainAround(mpos, true);

                break;

            case Selected.WALL:
                if (wallWidget.CurrentType == null)
                {
                    return;
                }

                if (mpos.X < 0 || mpos.Y < 0 || mpos.X > bounds.X || mpos.Y > bounds.Y)
                {
                    return;
                }

                mpos = new MPos(mpos.X * 2 + (wallWidget.Horizontal ? 0 : 1), mpos.Y);

                var wallLayer = game.World.WallLayer;

                if (mpos.X >= wallLayer.Bounds.X - 2)
                {
                    return;
                }

                if (mpos.Y >= wallLayer.Bounds.Y - 2 && wallWidget.Horizontal)
                {
                    return;
                }

                var type = wallWidget.CurrentType;

                var plannedHealth = (int)(type.Health * wallWidget.RelativeHP);
                if (plannedHealth == 0 && type.Health != 0)
                {
                    return;
                }

                var currentWall = wallLayer.Walls[mpos.X, mpos.Y];
                if (currentWall != null && currentWall.Type.ID == type.ID && currentWall.Health == plannedHealth)
                {
                    return;
                }

                var wall = WallCache.Create(mpos, wallLayer, type.ID);
                wall.Health = plannedHealth;

                wallLayer.Set(wall);
                break;
            }
        }
Beispiel #48
0
 public Shroud(MPos pos)
 {
     Listener        = pos;
     graphicPosition = new CPos(pos.X * 512 - 256, pos.Y * 512 - 256, 0);
 }
Beispiel #49
0
 public PhysicsSector(MPos position)
 {
     Position = position;
 }
Beispiel #50
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);

            var overlayIndex = new CellLayer <int>(map);

            overlayIndex.Clear(0xFF);

            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;
                    }

                    overlayIndex[uv] = rx + 512 * ry;
                }
            }

            foreach (var cell in map.AllCells)
            {
                var overlayType = overlayPack[overlayIndex[cell]];
                if (overlayType == 0xFF)
                {
                    continue;
                }

                if (OverlayToActor.TryGetValue(overlayType, out var actorType))
                {
                    var shape = new Size(1, 1);
                    if (OverlayShapes.TryGetValue(overlayType, out shape))
                    {
                        // Only import the top-left cell of multi-celled overlays
                        var aboveType = overlayPack[overlayIndex[cell - new CVec(1, 0)]];
                        if (shape.Width > 1 && aboveType != 0xFF)
                        {
                            if (OverlayToActor.TryGetValue(aboveType, out var a) && a == actorType)
                            {
                                continue;
                            }
                        }

                        var leftType = overlayPack[overlayIndex[cell - new CVec(0, 1)]];
                        if (shape.Height > 1 && leftType != 0xFF)
                        {
                            if (OverlayToActor.TryGetValue(leftType, out var a) && a == actorType)
                            {
                                continue;
                            }
                        }
                    }

                    var ar = new ActorReference(actorType)
                    {
                        new LocationInit(cell),
                        new OwnerInit("Neutral")
                    };

                    if (OverlayToHealth.TryGetValue(overlayType, out var damageState))
                    {
                        var health = 100;
                        if (damageState == DamageState.Critical)
                        {
                            health = 25;
                        }
                        else if (damageState == DamageState.Heavy)
                        {
                            health = 50;
                        }
                        else if (damageState == DamageState.Medium)
                        {
                            health = 75;
                        }

                        if (health != 100)
                        {
                            ar.Add(new HealthInit(health));
                        }
                    }

                    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[cell] = new ResourceTile(resourceType, overlayDataPack[overlayIndex[cell]]);
                    continue;
                }

                Console.WriteLine("{0} unknown overlay {1}", cell, overlayType);
            }
        }
Beispiel #51
0
        public bool IsVisible(MPos uv)
        {
            if (!visibleCount.Contains(uv))
                return false;

            return map.ProjectedCellsCovering(uv).Any(isVisibleTest);
        }
Beispiel #52
0
        void notifyNeighbors(MPos pos, bool added, bool ignoresNearby)
        {
            byte s = 0;

            bool left   = pos.X >= 2;
            bool right  = pos.X < Bounds.X - 3;
            bool top    = pos.Y > 0;
            bool bottom = pos.Y < Bounds.Y - 2;

            /*
             *
             * HORIZONTAL
             |0		|3
             |		|
             | 1		|		|	    4
             | --------o-------o--------
             |	    |
             |		|
             |         2|		|5
             |
             | VERTICAL
             |1
             |
             | 0		|		2
             | --------o--------
             |
             |
             |
             | --------o--------
             | 3		|		5
             |
             |         4|
             |
             | BYTE 012 345 67
             |   000 000 --
             */

            Wall wall;

            if (pos.X % 2 != 0)
            {
                // Horizontal
                if (top)
                {
                    wall = Walls[pos.X - 1, pos.Y - 1];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b00000100, added);
                        }
                        s |= 0b10000000;
                    }
                }

                if (left)
                {
                    wall = Walls[pos.X - 2, pos.Y];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b00001000, added);
                        }
                        s |= 0b01000000;
                    }
                }

                wall = Walls[pos.X - 1, pos.Y];
                if (wall != null && !wall.Type.IgnoreForNearby)
                {
                    if (!ignoresNearby)
                    {
                        wall.SetNeighborState(0b00100000, added);
                    }
                    s |= 0b00100000;
                }

                if (right)
                {
                    if (top)
                    {
                        wall = Walls[pos.X + 1, pos.Y - 1];
                        if (wall != null && !wall.Type.IgnoreForNearby)
                        {
                            if (!ignoresNearby)
                            {
                                wall.SetNeighborState(0b00010000, added);
                            }
                            s |= 0b00010000;
                        }
                    }

                    wall = Walls[pos.X + 2, pos.Y];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b01000000, added);
                        }
                        s |= 0b00001000;
                    }

                    wall = Walls[pos.X + 1, pos.Y];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b10000000, added);
                        }
                        s |= 0b00000100;
                    }
                }
            }
            else
            {
                // Vertical
                if (left)
                {
                    wall = Walls[pos.X - 1, pos.Y];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b00000100, added);
                        }
                        s |= 0b10000000;
                    }
                }

                if (top)
                {
                    wall = Walls[pos.X, pos.Y - 1];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b00001000, added);
                        }
                        s |= 0b01000000;
                    }
                }

                wall = Walls[pos.X + 1, pos.Y];
                if (wall != null && !wall.Type.IgnoreForNearby)
                {
                    if (!ignoresNearby)
                    {
                        wall.SetNeighborState(0b00100000, added);
                    }
                    s |= 0b00100000;
                }

                if (bottom)
                {
                    if (left)
                    {
                        wall = Walls[pos.X - 1, pos.Y + 1];
                        if (wall != null && !wall.Type.IgnoreForNearby)
                        {
                            if (!ignoresNearby)
                            {
                                wall.SetNeighborState(0b00010000, added);
                            }
                            s |= 0b00010000;
                        }
                    }

                    wall = Walls[pos.X, pos.Y + 1];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b01000000, added);
                        }
                        s |= 0b00001000;
                    }

                    wall = Walls[pos.X + 1, pos.Y + 1];
                    if (wall != null && !wall.Type.IgnoreForNearby)
                    {
                        if (!ignoresNearby)
                        {
                            wall.SetNeighborState(0b10000000, added);
                        }
                        s |= 0b00000100;
                    }
                }
            }

            if (added)
            {
                Walls[pos.X, pos.Y].SetNeighborState(s, true);
            }
        }
Beispiel #53
0
 void CellTerrainColorChanged(MPos uv)
 {
     UpdateTerrainColor(uv);
 }
Beispiel #54
0
 int VertexArrayOffset(MPos uv)
 {
     return(4 * (uv.V * map.MapSize.X + uv.U));
 }
Beispiel #55
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 #56
0
        public PPos[] ProjectedCellsCovering(MPos uv)
        {
            if (!initializedCellProjection)
                InitializeCellProjection();

            if (!cellProjection.Contains(uv))
                return NoProjectedCells;

            return cellProjection[uv];
        }
Beispiel #57
0
        public NewMapLogic(Action onExit, Action<string> onSelect, Ruleset modRules, Widget widget, World world)
        {
            panel = widget;

            panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };

            var tilesetDropDown = panel.Get<DropDownButtonWidget>("TILESET");
            var tilesets = modRules.TileSets.Select(t => t.Key).ToList();
            Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
            {
                var item = ScrollItemWidget.Setup(template,
                    () => tilesetDropDown.Text == option,
                    () => { tilesetDropDown.Text = option; });
                item.Get<LabelWidget>("LABEL").GetText = () => option;
                return item;
            };
            tilesetDropDown.Text = tilesets.First();
            tilesetDropDown.OnClick = () =>
                tilesetDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, tilesets, setupItem);

            var widthTextField = panel.Get<TextFieldWidget>("WIDTH");
            var heightTextField = panel.Get<TextFieldWidget>("HEIGHT");

            panel.Get<ButtonWidget>("CREATE_BUTTON").OnClick = () =>
            {
                int width, height;
                int.TryParse(widthTextField.Text, out width);
                int.TryParse(heightTextField.Text, out height);

                // Require at least a 2x2 playable area so that the
                // ground is visible through the edge shroud
                width = Math.Max(2, width);
                height = Math.Max(2, height);

                var maxTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;
                var tileset = modRules.TileSets[tilesetDropDown.Text];
                var map = new Map(tileset, width + 2, height + maxTerrainHeight + 2);

                var tl = new MPos(1, 1);
                var br = new MPos(width, height + maxTerrainHeight);
                map.SetBounds(tl, br);

                map.PlayerDefinitions = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length).ToMiniYaml();
                map.FixOpenAreas(modRules);

                Action<string> afterSave = uid =>
                {
                    // HACK: Work around a synced-code change check.
                    // It's not clear why this is needed here, but not in the other places that load maps.
                    Game.RunAfterTick(() =>
                    {
                        ConnectionLogic.Connect(System.Net.IPAddress.Loopback.ToString(),
                            Game.CreateLocalServer(uid), "",
                            () => Game.LoadEditor(uid),
                            () => { Game.CloseServer(); onExit(); });
                    });

                    Ui.CloseWindow();
                    onSelect(uid);
                };

                Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs()
                {
                    { "onSave", afterSave },
                    { "onExit", () => { Ui.CloseWindow(); onExit(); } },
                    { "map", map },
                    { "playerDefinitions", map.PlayerDefinitions },
                    { "actorDefinitions", map.ActorDefinitions }
                });
            };
        }
        void Initialize(string mapFile)
        {
            mapSize = new Size(stream.ReadUInt16(), stream.ReadUInt16());

            tileSet = rules.TileSets["ARRAKIS"];

            map = new Map(tileSet, mapSize.Width + 2 * MapCordonWidth, mapSize.Height + 2 * MapCordonWidth)
            {
                Title = Path.GetFileNameWithoutExtension(mapFile),
                Author = "Westwood Studios"
            };

            var tl = new MPos(MapCordonWidth, MapCordonWidth);
            var br = new MPos(MapCordonWidth + mapSize.Width - 1, MapCordonWidth + mapSize.Height - 1);
            map.SetBounds(tl, br);

            // Get all templates from the tileset YAML file that have at least one frame and an Image property corresponding to the requested tileset
            // Each frame is a tile from the Dune 2000 tileset files, with the Frame ID being the index of the tile in the original file
            tileSetsFromYaml = tileSet.Templates.Where(t => t.Value.Frames != null
                && t.Value.Images[0].ToLower() == tilesetName.ToLower()).Select(ts => ts.Value).ToList();
        }
Beispiel #59
0
        static void ReadActors(Map map, IniFile file, string type, int2 fullSize)
        {
            var structuresSection = file.GetSection(type, true);

            foreach (var kv in structuresSection)
            {
                var isDeployed = false;
                var entries    = kv.Value.Split(',');

                var name = entries[1].ToLowerInvariant();

                if (DeployableActors.ContainsKey(name))
                {
                    name       = DeployableActors[name];
                    isDeployed = true;
                }

                if (ReplaceActors.ContainsKey(name))
                {
                    name = ReplaceActors[name];
                }

                var health = short.Parse(entries[2]);
                var rx     = int.Parse(entries[3]);
                var ry     = int.Parse(entries[4]);
                var facing = (byte)(224 - byte.Parse(entries[type == "Infantry" ? 7 : 5]));

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

                var ar = new ActorReference(name)
                {
                    new LocationInit(cell),
                    new OwnerInit(CreepActors.Contains(entries[1]) ? "Creeps" : "Neutral")
                };

                if (type == "Infantry")
                {
                    var subcell = 0;
                    switch (byte.Parse(entries[5]))
                    {
                    case 2: subcell = 3; break;

                    case 3: subcell = 1; break;

                    case 4: subcell = 2; break;
                    }

                    if (subcell != 0)
                    {
                        ar.Add(new SubCellInit((SubCell)subcell));
                    }
                }

                if (health != 256)
                {
                    ar.Add(new HealthInit(100 * health / 256));
                }

                ar.Add(new FacingInit(WAngle.FromFacing(facing)));

                if (isDeployed)
                {
                    ar.Add(new DeployStateInit(DeployState.Deployed));
                }

                if (!map.Rules.Actors.ContainsKey(name))
                {
                    Console.WriteLine("Ignoring unknown actor type: `{0}`".F(name));
                }
                else
                {
                    map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
                }
            }
        }
Beispiel #60
0
        bool ContainsAllProjectedCellsCovering(MPos uv)
        {
            if (Grid.MaximumTerrainHeight == 0)
                return Contains((PPos)uv);

            // If the cell has no valid projection, then we're off the map.
            var projectedCells = ProjectedCellsCovering(uv);
            if (projectedCells.Length == 0)
                return false;

            foreach (var puv in projectedCells)
                if (!Contains(puv))
                    return false;
            return true;
        }