public ElevatedBridgeLayer(Actor self, ElevatedBridgeLayerInfo info) { map = self.World.Map; cellCenters = new CellLayer <WPos>(map); terrainIndices = new CellLayer <byte>(map); terrainIndices.Clear(map.Rules.TerrainInfo.GetTerrainIndex(info.ImpassableTerrainType)); }
void WorldOnRenderPlayerChanged(Player player) { var newShroud = player != null ? player.Shroud : null; if (shroud != newShroud) { if (shroud != null) { shroud.OnShroudChanged -= UpdateShroudCell; } if (newShroud != null) { visibleUnderShroud = puv => newShroud.IsExplored(puv); visibleUnderFog = puv => newShroud.IsVisible(puv); newShroud.OnShroudChanged += UpdateShroudCell; } else { visibleUnderShroud = puv => map.Contains(puv); visibleUnderFog = puv => map.Contains(puv); } shroud = newShroud; } // Dirty the full projected space so the cells outside // the map bounds can be initialized as fully shrouded. cellsDirty.Clear(true); var tl = new PPos(0, 0); var br = new PPos(map.MapSize.X - 1, map.MapSize.Y - 1); UpdateShroud(new ProjectedCellRegion(map, tl, br)); }
public TerrainTunnelLayer(Actor self, TerrainTunnelLayerInfo info) { map = self.World.Map; cellCenters = new CellLayer <WPos>(map); terrainIndices = new CellLayer <byte>(map); terrainIndices.Clear(map.Rules.TileSet.GetTerrainIndex(info.ImpassableTerrainType)); }
void Update(Shroud newShroud) { if (currentShroud != newShroud) { if (currentShroud != null) { currentShroud.CellsChanged -= MarkCellsDirty; } if (newShroud != null) { shroudDirty.Clear(true); newShroud.CellsChanged += MarkCellsDirty; } cellsDirty.Clear(); cellsAndNeighborsDirty.Clear(); currentShroud = newShroud; } if (currentShroud != null) { mapBorderShroudIsCached = false; // We need to mark newly dirtied areas of the shroud. // Expand the dirty area to cover the neighboring cells, since shroud is affected by neighboring cells. foreach (var cell in cellsDirty) { cellsAndNeighborsDirty.Add(cell); foreach (var direction in CVec.Directions) { cellsAndNeighborsDirty.Add(cell + direction); } } foreach (var cell in cellsAndNeighborsDirty) { shroudDirty[cell] = true; } cellsDirty.Clear(); cellsAndNeighborsDirty.Clear(); } else if (!mapBorderShroudIsCached) { mapBorderShroudIsCached = true; CacheMapBorderShroud(); } }
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); } }
public static Map FromTileset(TileSet tileset) { var size = new Size(1, 1); var tileShape = Game.ModData.Manifest.TileShape; var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0); var makeMapTiles = Exts.Lazy(() => { var ret = new CellLayer<TerrainTile>(tileShape, size); ret.Clear(tileRef); return ret; }); var makeMapHeight = Exts.Lazy(() => { var ret = new CellLayer<byte>(tileShape, size); ret.Clear(0); return ret; }); var map = new Map() { Title = "Name your map here", Description = "Describe your map here", Author = "Your name here", MapSize = new int2(size), Tileset = tileset.Id, Videos = new MapVideos(), Options = new MapOptions(), MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)), MapTiles = makeMapTiles, MapHeight = makeMapHeight, SpawnPoints = Exts.Lazy(() => new CPos[0]) }; map.PostInit(); return map; }
public void ExploreAll(World world) { explored.Clear(true); Invalidate(); }
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); } }
public static Map FromTileset(TileSet tileset) { var size = new Size(1, 1); var tileShape = Game.modData.Manifest.TileShape; var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0); var makeMapTiles = Exts.Lazy(() => { var ret = new CellLayer<TerrainTile>(tileShape, size); ret.Clear(tileRef); return ret; }); var map = new Map() { Title = "Name your map here", Description = "Describe your map here", Author = "Your name here", MapSize = new int2(size), Tileset = tileset.Id, Options = new MapOptions(), MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)), MapTiles = makeMapTiles, Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()), Smudges = Exts.Lazy(() => new List<SmudgeReference>()) }; map.PostInit(); return map; }
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); } }
/// <summary> /// Initializes a new map created by the editor or importer. /// The map will not recieve a valid UID until after it has been saved and reloaded. /// </summary> public Map(TileSet tileset, int width, int height) { var size = new Size(width, height); var tileShape = Game.ModData.Manifest.TileShape; var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0); Title = "Name your map here"; Description = "Describe your map here"; Author = "Your name here"; MapSize = new int2(size); Tileset = tileset.Id; Videos = new MapVideos(); Options = new MapOptions(); MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size)); MapTiles = Exts.Lazy(() => { var ret = new CellLayer<TerrainTile>(tileShape, size); ret.Clear(tileRef); return ret; }); MapHeight = Exts.Lazy(() => { var ret = new CellLayer<byte>(tileShape, size); ret.Clear(0); return ret; }); SpawnPoints = Exts.Lazy(() => new CPos[0]); TileShape = tileShape; MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight; PostInit(); }
public byte GetTerrainIndex(CPos cell) { const short InvalidCachedTerrainIndex = -1; // Lazily initialize a cache for terrain indexes. if (cachedTerrainIndexes == null) { cachedTerrainIndexes = new CellLayer<short>(this); cachedTerrainIndexes.Clear(InvalidCachedTerrainIndex); // Invalidate the entry for a cell if anything could cause the terrain index to change. Action<CPos> invalidateTerrainIndex = c => cachedTerrainIndexes[c] = InvalidCachedTerrainIndex; CustomTerrain.CellEntryChanged += invalidateTerrainIndex; Tiles.CellEntryChanged += invalidateTerrainIndex; } var uv = cell.ToMPos(this); var terrainIndex = cachedTerrainIndexes[uv]; // PERF: Cache terrain indexes per cell on demand. if (terrainIndex == InvalidCachedTerrainIndex) { var custom = CustomTerrain[uv]; terrainIndex = cachedTerrainIndexes[uv] = custom != byte.MaxValue ? custom : Rules.TileSet.GetTerrainIndex(Tiles[uv]); } return (byte)terrainIndex; }
/// <summary> /// Initializes a new map created by the editor or importer. /// The map will not receive a valid UID until after it has been saved and reloaded. /// </summary> public Map(ModData modData, TileSet tileset, int width, int height) { this.modData = modData; var size = new Size(width, height); Grid = modData.Manifest.Get<MapGrid>(); var tileRef = new TerrainTile(tileset.Templates.First().Key, 0); Title = "Name your map here"; Author = "Your name here"; MapSize = new int2(size); Tileset = tileset.Id; // Empty rules that can be added to by the importers. // Will be dropped on save if nothing is added to it RuleDefinitions = new MiniYaml(""); Tiles = new CellLayer<TerrainTile>(Grid.Type, size); Resources = new CellLayer<ResourceTile>(Grid.Type, size); Height = new CellLayer<byte>(Grid.Type, size); if (Grid.MaximumTerrainHeight > 0) { Height.CellEntryChanged += UpdateProjection; Tiles.CellEntryChanged += UpdateProjection; } Tiles.Clear(tileRef); PostInit(); }