Пример #1
0
        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));
        }
Пример #2
0
        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);
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #6
0
        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)));
        }
Пример #7
0
        public FrozenActor(Actor self, CPos[] footprint, CellRegion footprintRegion)
        {
            actor           = self;
            Footprint       = footprint;
            FootprintRegion = footprintRegion;

            CenterPosition = self.CenterPosition;
            Bounds         = self.Bounds.Value;
        }
Пример #8
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();
        }
Пример #9
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();
        }
Пример #10
0
        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);
                }
            }
Пример #12
0
        /// <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));
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
            }
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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);
        }
Пример #19
0
        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);
            }
        }
Пример #20
0
        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);
        }
Пример #21
0
        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]);
            }
        }
Пример #22
0
        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);
            }
        }
Пример #23
0
        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]);
                }
            }
        }
Пример #24
0
        /// <summary>Scans the map in chunks, evaluating all actors in each.</summary>
        CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

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

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

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

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

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

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

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

            return(bestLocation);
        }
Пример #25
0
        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);
        }
Пример #26
0
        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);
                }
            }
        }
Пример #27
0
        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);
        }
Пример #28
0
        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);
        }
Пример #29
0
        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();
            }
        }
Пример #30
0
        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);
        }
Пример #31
0
        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);
            }
        }
Пример #32
0
        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;
        }
Пример #33
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();
        }
Пример #34
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 = 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 });
 }
Пример #36
0
 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);
         }
     }
 }
 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;
 }
Пример #39
0
 public void SetPasteRegion(CPos start, CPos end)
 {
     PasteRegion = CellRegion.BoundingRegion(map.Grid.Type, new[] { start, end });
 }
Пример #40
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);
        }
Пример #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);
        }
Пример #42
0
		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;
		}
Пример #43
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));
        }
Пример #44
0
        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;
 }
Пример #46
0
        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);
        }
Пример #47
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);
        }
Пример #48
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();
        }
Пример #49
0
 public void Clear()
 {
     CopyRegion = PasteRegion = null;
 }
Пример #50
0
        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();
            }
        }