public IEnumerable <FrozenActor> FrozenActorsInRegion(CellRegion region) { var tl = region.TopLeft; var br = region.BottomRight; return(partitionedFrozenActorIds.InBox(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y)).Select(FromID)); }
void RenderPlayerShroud(CellRegion visibleRegion) { // Render the shroud by drawing the appropriate tile over each cell that is visible on-screen. // For performance we keep a cache tiles we have drawn previously so we don't have to recalculate the // vertices for tiles every frame, since this is costly. // Any shroud marked as dirty has either never been calculated, or has changed since we last drew that // tile. We will calculate the vertices for that tile and cache them before drawing it. // Any shroud that is not marked as dirty means our cached tile is still correct - we can just draw the // cached vertices. var visibleUnderShroud = currentShroud.IsExploredTest(visibleRegion); var visibleUnderFog = currentShroud.IsVisibleTest(visibleRegion); foreach (var uv in visibleRegion.MapCoords) { var offset = VertexArrayOffset(uv); if (shroudDirty[uv]) { shroudDirty[uv] = false; RenderDirtyTile(uv, offset, visibleUnderShroud, shroudSprites, shroudVertices, shroudPalette, shroudSpriteLayer); RenderDirtyTile(uv, offset, visibleUnderFog, fogSprites, fogVertices, fogPalette, fogSpriteLayer); } else { RenderCachedTile(shroudSpriteLayer[uv], shroudVertices, offset); RenderCachedTile(fogSpriteLayer[uv], fogVertices, offset); } } }
public bool HandleMouseInput(MouseInput mi) { // Exclusively uses left and right mouse buttons, but nothing else if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right) { return(false); } if (mi.Button == MouseButton.Right) { if (mi.Event == MouseInputEvent.Up) { editorWidget.ClearBrush(); return(true); } return(false); } if (mi.Button == MouseButton.Left && (mi.Event == MouseInputEvent.Up || mi.Event == MouseInputEvent.Down)) { var cell = worldRenderer.Viewport.ViewToWorld(mi.Location); switch (state) { case State.SelectFirst: if (mi.Event != MouseInputEvent.Down) { break; } start = cell; selectionLayer.SetCopyRegion(start, end); state = State.SelectSecond; break; case State.SelectSecond: if (mi.Event != MouseInputEvent.Up) { break; } end = cell; selectionLayer.SetCopyRegion(start, end); state = State.Paste; break; case State.Paste: { var gridType = worldRenderer.World.Map.Grid.Type; var source = CellRegion.BoundingRegion(gridType, new[] { start, end }); Copy(source, cell - end); editorWidget.ClearBrush(); break; } } return(true); } return(false); }
void Copy(CellRegion source, CVec offset) { var gridType = worldRenderer.World.Map.Grid.Type; var mapTiles = worldRenderer.World.Map.Tiles; var mapHeight = worldRenderer.World.Map.Height; var mapResources = worldRenderer.World.Map.Resources; var dest = new CellRegion(gridType, source.TopLeft + offset, source.BottomRight + offset); var previews = new Dictionary <string, ActorReference>(); var tiles = new Dictionary <CPos, Tuple <TerrainTile, ResourceTile, byte> >(); foreach (var cell in source) { if (!mapTiles.Contains(cell) || !mapTiles.Contains(cell + offset)) { continue; } tiles.Add(cell + offset, Tuple.Create(mapTiles[cell], mapResources[cell], mapHeight[cell])); foreach (var preview in editorLayer.PreviewsAt(cell)) { if (previews.ContainsKey(preview.ID)) { continue; } var copy = preview.Export(); if (copy.InitDict.Contains <LocationInit>()) { var location = copy.InitDict.Get <LocationInit>(); copy.InitDict.Remove(location); copy.InitDict.Add(new LocationInit(location.Value(worldRenderer.World) + offset)); } previews.Add(preview.ID, copy); } } foreach (var kv in tiles) { mapTiles[kv.Key] = kv.Value.Item1; mapResources[kv.Key] = kv.Value.Item2; mapHeight[kv.Key] = kv.Value.Item3; } var removeActors = dest.SelectMany(editorLayer.PreviewsAt).Distinct().ToList(); foreach (var preview in removeActors) { editorLayer.Remove(preview); } foreach (var kv in previews) { editorLayer.Add(kv.Value); } }
/// <summary>Scans the map in chunks, evaluating all actors in each.</summary> CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower) { CPos?bestLocation = null; var powerDecision = powerDecisions[readyPower.Info.OrderName]; if (powerDecision == null) { AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName); return(null); } var map = world.Map; var checkRadius = powerDecision.CoarseScanRadius; var suitableLocations = new List <int[]>(); var totalAttractiveness = 0; for (var i = 0; i < map.MapSize.X; i += checkRadius) { for (var j = 0; j < map.MapSize.Y; j += checkRadius) { var tl = new MPos(i, j); var br = new MPos(i + checkRadius, j + checkRadius); var region = new CellRegion(map.Grid.Type, tl, br); // HACK: The AI code should not be messing with raw coordinate transformations var wtl = world.Map.CenterOfCell(tl.ToCPos(map)); var wbr = world.Map.CenterOfCell(br.ToCPos(map)); var targets = world.ActorMap.ActorsInBox(wtl, wbr); var frozenTargets = player.FrozenActorLayer != null?player.FrozenActorLayer.FrozenActorsInRegion(region) : Enumerable.Empty <FrozenActor>(); var consideredAttractiveness = powerDecision.GetAttractiveness(targets, player) + powerDecision.GetAttractiveness(frozenTargets, player); if (consideredAttractiveness < powerDecision.MinimumAttractiveness) { continue; } suitableLocations.Add(new int[] { i, j, consideredAttractiveness }); totalAttractiveness += consideredAttractiveness; } } if (suitableLocations.Any()) { // Only consider locations of above average attractiveness. var avgAttractiveness = totalAttractiveness / suitableLocations.Count(); foreach (var location in Util.Shuffle(suitableLocations, world.LocalRandom)) { if (location[2] >= avgAttractiveness) { bestLocation = new MPos(location[0], location[1]).ToCPos(map); break; } } } return(bestLocation); }
public IEnumerable <FrozenActor> FrozenActorsInRegion(CellRegion region, bool onlyVisible = true) { var tl = region.TopLeft; var br = region.BottomRight; return(partitionedFrozenActorIds.InBox(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y)) .Select(FromID) .Where(fa => fa.IsValid && (!onlyVisible || fa.Visible))); }
public FrozenActor(Actor self, CPos[] footprint, CellRegion footprintRegion) { actor = self; Footprint = footprint; FootprintRegion = footprintRegion; CenterPosition = self.CenterPosition; Bounds = self.Bounds.Value; }
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 IEnumerable <T> SampleRegionOutward(Rectangle2D region) { if (!_region.Overlaps(region)) { yield break; } CellRegion r = RegionIndicesClamped(region); if (r.Right == 0 && r.Down == 0) { yield return(_data[r.Start]); yield break; } int c = CellIndexClamped(region.Center); //cell where the iteration starts int px = c % _stride; //grid column of the start cell int py = c / _stride; //grid row of the start cell //cells outside these constrains need to be skipped int x0 = r.Start % _stride; int y0 = r.Start / _stride; int x1 = x0 + r.Right; int y1 = y0 + r.Down; //variables to track current offset and direction int ox = 0; int oy = 0; int dx = 0; int dy = -1; int remaining = (1 + r.Right) * (1 + r.Down); //the expected amount of samples so we know when to stop while (remaining > 0) { int x = px + ox; int y = py + oy; //within clamped region? if (x >= x0 && x <= x1 && y >= y0 && y <= y1) { yield return(_data[x + _stride * y]); remaining--; } //change direction? if ((ox == oy) || (ox < 0 && ox == -oy) || (ox > 0 && ox == 1 - oy)) { int tmp = dx; dx = -dy; dy = tmp; } //next ox += dx; oy += dy; } }
public void Cell(CellRegion region, IRichTextString value, ICellStyle style, bool isBorder) { ICell cell = row.CreateCell(region.Col); CellRangeAddress address = region.GetRegion(); sheet.AddMergedRegion(address); cell.SetCellValue(value); if (isBorder) { SetBorder(address); } }
/// <summary>Scans the map in chunks, evaluating all actors in each.</summary> CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower) { var powerDecision = powerDecisions[readyPower.Info.OrderName]; if (powerDecision == null) { AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, readyPower.Info.OrderName); return(null); } var map = world.Map; var checkRadius = powerDecision.CoarseScanRadius; var suitableLocations = new List <(MPos UV, int Attractiveness)>(); var totalAttractiveness = 0; for (var i = 0; i < map.MapSize.X; i += checkRadius) { for (var j = 0; j < map.MapSize.Y; j += checkRadius) { var tl = new MPos(i, j); var br = new MPos(i + checkRadius, j + checkRadius); var region = new CellRegion(map.Grid.Type, tl, br); // HACK: The AI code should not be messing with raw coordinate transformations var wtl = world.Map.CenterOfCell(tl.ToCPos(map)); var wbr = world.Map.CenterOfCell(br.ToCPos(map)); var targets = world.ActorMap.ActorsInBox(wtl, wbr); var frozenTargets = player.FrozenActorLayer != null?player.FrozenActorLayer.FrozenActorsInRegion(region) : Enumerable.Empty <FrozenActor>(); var consideredAttractiveness = powerDecision.GetAttractiveness(targets, player) + powerDecision.GetAttractiveness(frozenTargets, player); if (consideredAttractiveness < powerDecision.MinimumAttractiveness) { continue; } suitableLocations.Add((tl, consideredAttractiveness)); totalAttractiveness += consideredAttractiveness; } } if (suitableLocations.Count == 0) { return(null); } // Pick a random location with above average attractiveness. var averageAttractiveness = totalAttractiveness / suitableLocations.Count; return(suitableLocations.Shuffle(world.LocalRandom) .First(x => x.Attractiveness >= averageAttractiveness) .UV.ToCPos(map)); }
public FrozenUnderFog(ActorInitializer init, FrozenUnderFogInfo info) { // Spawned actors (e.g. building husks) shouldn't be revealed startsRevealed = info.StartsRevealed && !init.Contains <ParentActorInit>(); footprint = FootprintUtils.Tiles(init.self).ToArray(); footprintRegion = CellRegion.BoundingRegion(init.world.Map.TileShape, footprint); tooltip = Exts.Lazy(() => init.self.TraitsImplementing <IToolTip>().FirstOrDefault()); tooltip = Exts.Lazy(() => init.self.TraitsImplementing <IToolTip>().FirstOrDefault()); health = Exts.Lazy(() => init.self.TraitOrDefault <Health>()); frozen = new Dictionary <Player, FrozenActor>(); visible = init.world.Players.ToDictionary(p => p, p => false); }
public void WorldLoaded(World w, WorldRenderer wr) { // Initialize tile cache // Adds a 1-cell border around the border to cover any sprites peeking outside the map foreach (var uv in CellRegion.Expand(w.Map.Cells, 1).MapCoords) { var screen = wr.ScreenPosition(w.Map.CenterOfCell(uv.ToCPos(map))); var variant = (byte)Game.CosmeticRandom.Next(info.ShroudVariants.Length); tileInfos[uv] = new TileInfo(screen, variant); } fogPalette = wr.Palette(info.FogPalette); shroudPalette = wr.Palette(info.ShroudPalette); }
void CacheMapBorderShroud() { // Cache the whole of the map border shroud ahead of time, since it never changes. Func <MPos, bool> mapContains = map.Contains; foreach (var uv in CellRegion.Expand(map.Cells, 1).MapCoords) { var offset = VertexArrayOffset(uv); var edges = GetEdges(uv, mapContains); var tileInfo = tileInfos[uv]; CacheTile(uv, offset, edges, tileInfo, shroudSprites, shroudVertices, shroudPalette, shroudSpriteLayer); CacheTile(uv, offset, edges, tileInfo, fogSprites, fogVertices, fogPalette, fogSpriteLayer); } }
void Copy(CellRegion source, CVec offset) { var gridType = worldRenderer.World.Map.Grid.Type; var mapTiles = worldRenderer.World.Map.Tiles; var mapHeight = worldRenderer.World.Map.Height; var mapResources = worldRenderer.World.Map.Resources; var dest = new CellRegion(gridType, source.TopLeft + offset, source.BottomRight + offset); var previews = new Dictionary <string, ActorReference>(); var tiles = new Dictionary <CPos, (TerrainTile, ResourceTile, byte)>(); var copyFilters = getCopyFilters(); foreach (var cell in source) { if (!mapTiles.Contains(cell) || !mapTiles.Contains(cell + offset)) { continue; } tiles.Add(cell + offset, (mapTiles[cell], mapResources[cell], mapHeight[cell])); if (copyFilters.HasFlag(MapCopyFilters.Actors)) { foreach (var preview in editorLayer.PreviewsAt(cell)) { if (previews.ContainsKey(preview.ID)) { continue; } var copy = preview.Export(); var locationInit = copy.GetOrDefault <LocationInit>(); if (locationInit != null) { copy.RemoveAll <LocationInit>(); copy.Add(new LocationInit(locationInit.Value + offset)); } previews.Add(preview.ID, copy); } } } var action = new CopyPasteEditorAction(copyFilters, worldRenderer.World.Map, tiles, previews, editorLayer, dest); editorActionManager.Add(action); }
public CopyPasteEditorAction(MapCopyFilters copyFilters, Map map, Dictionary <CPos, Tuple <TerrainTile, ResourceTile, byte> > tiles, Dictionary <string, ActorReference> previews, EditorActorLayer editorLayer, CellRegion dest) { this.copyFilters = copyFilters; this.tiles = tiles; this.previews = previews; this.editorLayer = editorLayer; this.dest = dest; mapTiles = map.Tiles; mapHeight = map.Height; mapResources = map.Resources; Text = "Copied {0} tiles".F(tiles.Count); }
public Func <MPos, bool> IsExploredTest(CellRegion region) { // If the region to test extends outside the map we must use the slow test that checks the map boundary every time. if (!map.Cells.Contains(region)) { return(slowExploredTest); } // If shroud isn't enabled, then we can see everything inside the map. if (!ShroudEnabled) { return(shroudEdgeTest); } // If shroud is enabled, we can use the fast test that just does the core check. return(fastExploredTest); }
void Render(CellRegion visibleRegion) { // Due to diamond tile staggering, we need to expand the cordon to get full shroud coverage. if (map.TileShape == TileShape.Diamond) { visibleRegion = CellRegion.Expand(visibleRegion, 1); } if (currentShroud == null) { RenderMapBorderShroud(visibleRegion); } else { RenderPlayerShroud(visibleRegion); } }
public Func <MPos, bool> IsVisibleTest(CellRegion region) { // If the region to test extends outside the map we must use the slow test that checks the map boundary every time. if (!map.Cells.Contains(region)) { return(slowVisibleTest); } // If fog isn't enabled, then we can see everything. if (!FogEnabled) { return(TruthPredicate); } // If fog is enabled, we can use the fast test that just does the core check. return(fastVisibleTest); }
public IEnumerable <T> SamplePerimeter(Rectangle2D rect) { if (!_region.Overlaps(rect)) { yield break; } CellRegion r = RegionIndicesClamped(rect); if (r.Right == 0 && r.Down == 0) { yield return(_data[r.Start]); yield break; } int tl = r.Start; int tr = r.Start + r.Right; int bl = tl + _stride * r.Down; int br = tr + _stride * r.Down; //TOPLEFT - > TOPRIGHT for (int i = tl; i < tr; i++) { yield return(_data[i]); } //TOPRIGHT -> BOTTOMRIGHT for (int i = tr; i < br; i += _stride) { yield return(_data[i]); } //BOTTOMRIGHT -> BOTTOMLEFT for (int i = br; i > bl; i--) { yield return(_data[i]); } //BOTTOMLEFT -> TOPLEFT for (int i = bl; i > tl; i -= _stride) { yield return(_data[i]); } }
void RenderMapBorderShroud(CellRegion visibleRegion) { // The map border shroud only affects the map border. If none of the visible cells are on the border, then // we don't need to render anything and can bail early for performance. if (CellRegion.Expand(map.Cells, -1).Contains(visibleRegion)) { return; } // Render the shroud that just encroaches at the map border. This shroud is always fully cached, so we can // just render straight from the cache. foreach (var uv in visibleRegion.MapCoords) { var offset = VertexArrayOffset(uv); RenderCachedTile(shroudSpriteLayer[uv], shroudVertices, offset); RenderCachedTile(fogSpriteLayer[uv], fogVertices, offset); } }
public IEnumerable <T> SampleRegion(Rectangle2D region) { if (!_region.Overlaps(region)) { yield break; } CellRegion r = RegionIndicesClamped(region); int i = r.Start; for (int y = 0; y <= r.Down; y++) { for (int x = 0; x <= r.Right; x++) { yield return(_data[i + y * _stride + x]); } } }
/// <summary>Scans the map in chunks, evaluating all actors in each.</summary> CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower) { CPos?bestLocation = null; var bestAttractiveness = 0; var powerDecision = powerDecisions[readyPower.Info.OrderName]; if (powerDecision == null) { AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName); return(null); } var map = world.Map; var checkRadius = powerDecision.CoarseScanRadius; for (var i = 0; i < map.MapSize.X; i += checkRadius) { for (var j = 0; j < map.MapSize.Y; j += checkRadius) { var tl = new MPos(i, j); var br = new MPos(i + checkRadius, j + checkRadius); var region = new CellRegion(map.Grid.Type, tl, br); // HACK: The AI code should not be messing with raw coordinate transformations var wtl = world.Map.CenterOfCell(tl.ToCPos(map)); var wbr = world.Map.CenterOfCell(br.ToCPos(map)); var targets = world.ActorMap.ActorsInBox(wtl, wbr); var frozenTargets = player.FrozenActorLayer != null?player.FrozenActorLayer.FrozenActorsInRegion(region) : Enumerable.Empty <FrozenActor>(); var consideredAttractiveness = powerDecision.GetAttractiveness(targets, player) + powerDecision.GetAttractiveness(frozenTargets, player); if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness) { continue; } bestAttractiveness = consideredAttractiveness; bestLocation = new MPos(i, j).ToCPos(map); } } return(bestLocation); }
public void WorldLoaded(World w, WorldRenderer wr) { // Initialize tile cache // Adds a 1-cell border around the border to cover any sprites peeking outside the map foreach (var cell in CellRegion.Expand(w.Map.Cells, 1)) { var screen = wr.ScreenPosition(w.Map.CenterOfCell(cell)); var variant = Game.CosmeticRandom.Next(info.ShroudVariants.Length); tiles[cell] = new ShroudTile(cell, screen, variant); // Set the cells outside the border so they don't need to be touched again if (!map.Contains(cell)) { var index = info.UseExtendedIndex ? 240 : 15; tiles[cell].Shroud = shroudSprites[variant * variantStride + spriteMap[index]]; } } fogPalette = wr.Palette(info.FogPalette); shroudPalette = wr.Palette(info.ShroudPalette); }
public void RenderShroud(WorldRenderer wr, Shroud shroud) { Update(shroud, wr.Viewport.VisibleCells); foreach (var cell in CellRegion.Expand(wr.Viewport.VisibleCells, 1)) { var t = tiles[cell]; if (t.Shroud != null) { var pos = t.ScreenPosition - 0.5f * t.Shroud.size; Game.Renderer.WorldSpriteRenderer.DrawSprite(t.Shroud, pos, shroudPalette); } if (t.Fog != null) { var pos = t.ScreenPosition - 0.5f * t.Fog.size; Game.Renderer.WorldSpriteRenderer.DrawSprite(t.Fog, pos, fogPalette); } } }
public void WorldLoaded(World w, WorldRenderer wr) { // Initialize tile cache // Adds a 1-cell border around the border to cover any sprites peeking outside the map foreach (var cell in CellRegion.Expand(w.Map.Cells, 1)) { var screen = wr.ScreenPosition(w.Map.CenterOfCell(cell)); var variant = (byte)Game.CosmeticRandom.Next(info.ShroudVariants.Length); tiles[cell] = new ShroudTile(screen, variant); // Set the cells outside the border so they don't need to be touched again if (!map.Contains(cell)) { var shroudTile = tiles[cell]; shroudTile.Shroud = GetTile(shroudSprites, notVisibleEdges, variant); tiles[cell] = shroudTile; } } fogPalette = wr.Palette(info.FogPalette); shroudPalette = wr.Palette(info.ShroudPalette); }
public CellRegion RegionIndicesClamped(Rectangle2D rect) { rect = rect.Intersection(_region); CellRegion region = new CellRegion(); //.0 is considered the start of a new cell Vector2D p1 = _toGrid * (rect.TopLeft - _region.TopLeft); int x1 = Math.Min(_stride - 1, Math.Max(0, (int)p1.X)); int y1 = Math.Min(_rows - 1, Math.Max(0, (int)p1.Y)); region.Start = y1 * _stride + x1; //.0 is included in the previous cell Vector2D p2 = _toGrid * (rect.BottomRight - _region.TopLeft); int x2 = Math.Min(_stride - 1, Math.Max(x1, (int)(Math.Ceiling(p2.X) - 1))); int y2 = Math.Min(_rows - 1, Math.Max(y1, (int)(Math.Ceiling(p2.Y) - 1))); region.Right = x2 - x1; region.Down = y2 - y1; return(region); }
void Update(Shroud shroud, CellRegion region) { if (shroud != null) { // If the current shroud hasn't changed and we have already updated the specified area, we don't need to do anything. if (lastShroudHash == shroud.Hash && !clearedForNullShroud && updatedRegion != null && updatedRegion.Contains(region)) { return; } lastShroudHash = shroud.Hash; clearedForNullShroud = false; updatedRegion = region; UpdateShroud(shroud); } else if (!clearedForNullShroud) { // We need to clear any applied shroud. clearedForNullShroud = true; updatedRegion = new CellRegion(map.TileShape, new CPos(0, 0), new CPos(-1, -1)); UpdateNullShroud(); } }
void Render(CellRegion visibleRegion) { // Due to diamond tile staggering, we need to expand the cordon to get full shroud coverage. if (map.TileShape == TileShape.Diamond) visibleRegion = CellRegion.Expand(visibleRegion, 1); if (currentShroud == null) RenderMapBorderShroud(visibleRegion); else RenderPlayerShroud(visibleRegion); }
void RenderMapBorderShroud(CellRegion visibleRegion) { // The map border shroud only affects the map border. If none of the visible cells are on the border, then // we don't need to render anything and can bail early for performance. if (CellRegion.Expand(map.Cells, -1).Contains(visibleRegion)) return; // Render the shroud that just encroaches at the map border. This shroud is always fully cached, so we can // just render straight from the cache. foreach (var uv in visibleRegion.MapCoords) { var offset = VertexArrayOffset(uv); RenderCachedTile(shroudSpriteLayer[uv], shroudVertices, offset); RenderCachedTile(fogSpriteLayer[uv], fogVertices, offset); } }
public Func<CPos, bool> IsExploredTest(CellRegion region) { // If the region to test extends outside the map we must use the slow test that checks the map boundary every time. if (!map.Cells.Contains(region)) return slowExploredTest; // If shroud isn't enabled, then we can see everything inside the map. if (!ShroudEnabled) return shroudEdgeTest; // If shroud is enabled, we can use the fast test that just does the core check. return fastExploredTest; }
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(); }
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 = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top)); var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1)); Cells = new CellRegion(TileShape, tl, br); CustomTerrain = new CellLayer<byte>(this); foreach (var cell in Cells) CustomTerrain[cell] = byte.MaxValue; }
public void SetPasteRegion(CPos start, CPos end) { PasteRegion = CellRegion.BoundingRegion(map.Grid.Type, new[] { start, end }); }
void TimeGrid_PreviewMouseMove(object sender, MouseEventArgs e) { var target = sender as ToggleCell; if (_mouseDragStart != null && _dragSource != target) // Mouse is down { var newRegion = new CellRegion(_hourCells,_dragSource, target); if (_dragRegion != null) { if (newRegion.TopLeft == _dragRegion.TopLeft && newRegion.BottomRight == _dragRegion.BottomRight) return; _dragRegion.SetVisualStates(_hourCells, "NoDrag"); } _dragRegion = newRegion; _dragRegion.SetVisualStates(_hourCells, _dragSource.Selected ? "DragOn" : "DragOff"); } }
void EndDragging() { _mouseDragStart = null; _dragSource = null; _dragRegion = null; }
// 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); }
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); }
void PostInit() { rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this)); cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]); var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top)); var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1)); Cells = new CellRegion(TileShape, tl, br); CustomTerrain = new CellLayer<int>(this); foreach (var cell in Cells) CustomTerrain[cell] = -1; }
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)); }
public Func<CPos, bool> IsVisibleTest(CellRegion region) { // If the region to test extends outside the map we must use the slow test that checks the map boundary every time. if (!map.Cells.Contains(region)) return slowVisibleTest; // If fog isn't enabled, then we can see everything. if (!FogEnabled) return TruthPredicate; // If fog is enabled, we can use the fast test that just does the core check. return fastVisibleTest; }
public void Clear() { CopyRegion = PasteRegion = null; }
void Copy(CellRegion source, CVec offset) { var gridType = worldRenderer.World.Map.Grid.Type; var mapTiles = worldRenderer.World.Map.Tiles; var mapHeight = worldRenderer.World.Map.Height; var mapResources = worldRenderer.World.Map.Resources; var dest = new CellRegion(gridType, source.TopLeft + offset, source.BottomRight + offset); var previews = new Dictionary<string, ActorReference>(); var tiles = new Dictionary<CPos, Tuple<TerrainTile, ResourceTile, byte>>(); foreach (var cell in source) { if (!mapTiles.Contains(cell) || !mapTiles.Contains(cell + offset)) continue; tiles.Add(cell + offset, Tuple.Create(mapTiles[cell], mapResources[cell], mapHeight[cell])); foreach (var preview in editorLayer.PreviewsAt(cell)) { if (previews.ContainsKey(preview.ID)) continue; var copy = preview.Export(); if (copy.InitDict.Contains<LocationInit>()) { var location = copy.InitDict.Get<LocationInit>(); copy.InitDict.Remove(location); copy.InitDict.Add(new LocationInit(location.Value(worldRenderer.World) + offset)); } previews.Add(preview.ID, copy); } } foreach (var kv in tiles) { mapTiles[kv.Key] = kv.Value.Item1; mapResources[kv.Key] = kv.Value.Item2; mapHeight[kv.Key] = kv.Value.Item3; } var removeActors = dest.SelectMany(editorLayer.PreviewsAt).Distinct().ToList(); foreach (var preview in removeActors) editorLayer.Remove(preview); foreach (var kv in previews) editorLayer.Add(kv.Value); }
public void SetBounds(MPos tl, MPos br) { // The tl and br coordinates are inclusive, but the Rectangle // is exclusive. Pad the right and bottom edges to match. Bounds = Rectangle.FromLTRB(tl.U, tl.V, br.U + 1, br.V + 1); CellsInsideBounds = new CellRegion(TileShape, tl.ToCPos(this), br.ToCPos(this)); // Directly calculate the projected map corners in world units avoiding unnecessary // conversions. This abuses the definition that the width of the cell is always // 1024 units, and that the height of two rows is 2048 for classic cells and 1024 // for diamond cells. var wtop = tl.V * 1024; var wbottom = (br.V + 1) * 1024; if (TileShape == TileShape.Diamond) { wtop /= 2; wbottom /= 2; } ProjectedTopLeft = new WPos(tl.U * 1024, wtop, 0); ProjectedBottomRight = new WPos(br.U * 1024 - 1, wbottom - 1, 0); }
void PostInit() { try { Rules = Ruleset.Load(modData, this, Tileset, RuleDefinitions, WeaponDefinitions, VoiceDefinitions, NotificationDefinitions, MusicDefinitions, SequenceDefinitions); } catch (Exception e) { InvalidCustomRules = true; Rules = Ruleset.LoadDefaultsForTileSet(modData, Tileset); Log.Write("debug", "Failed to load rules for {0} with error {1}", Title, e.Message); } Rules.Sequences.Preload(); var tl = new MPos(0, 0).ToCPos(this); var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this); AllCells = new CellRegion(Grid.Type, tl, br); var btl = new PPos(Bounds.Left, Bounds.Top); var bbr = new PPos(Bounds.Right - 1, Bounds.Bottom - 1); SetBounds(btl, bbr); CustomTerrain = new CellLayer<byte>(this); foreach (var uv in AllCells.MapCoords) CustomTerrain[uv] = byte.MaxValue; AllEdgeCells = UpdateEdgeCells(); }
void Update(Shroud shroud, CellRegion region) { if (shroud != null) { // If the current shroud hasn't changed and we have already updated the specified area, we don't need to do anything. if (lastShroudHash == shroud.Hash && !clearedForNullShroud && updatedRegion != null && updatedRegion.Contains(region)) return; lastShroudHash = shroud.Hash; clearedForNullShroud = false; updatedRegion = region; UpdateShroud(shroud); } else if (!clearedForNullShroud) { // We need to clear any applied shroud. clearedForNullShroud = true; updatedRegion = new CellRegion(map.TileShape, new CPos(0, 0), new CPos(-1, -1)); UpdateNullShroud(); } }