public static bool IsCellBuildable(this World world, CPos cell, ActorInfo ai, BuildingInfo bi, Actor toIgnore = null)
        {
            if (!world.Map.Contains(cell))
            {
                return(false);
            }

            if (!bi.AllowInvalidPlacement)
            {
                // Replaceable actors are rare, so avoid initializing state unless we have to
                var checkReplacements = ai != null && ai.HasTraitInfo <ReplacementInfo>();
                HashSet <string> acceptedReplacements = null;

                var foundActors = false;
                foreach (var a in world.ActorMap.GetActorsAt(cell))
                {
                    if (a == toIgnore)
                    {
                        continue;
                    }

                    // If this is potentially a replacement actor we must check *all* cell occupants
                    // before we know the placement is invalid
                    // Otherwise, we can bail immediately
                    if (!checkReplacements)
                    {
                        return(false);
                    }

                    foundActors = true;
                    foreach (var r in a.TraitsImplementing <Replaceable>())
                    {
                        if (r.IsTraitDisabled)
                        {
                            continue;
                        }

                        if (acceptedReplacements == null)
                        {
                            acceptedReplacements = new HashSet <string>();
                        }

                        acceptedReplacements.UnionWith(r.Info.Types);
                    }
                }

                // Replacements are enabled and the cell contained at least one (not ignored) actor or building bib
                var building = world.WorldActor.Trait <BuildingInfluence>().GetBuildingAt(cell);
                if (foundActors || building != null)
                {
                    // The cell contains at least one actor, and none were replaceable
                    if (acceptedReplacements == null)
                    {
                        return(false);
                    }

                    // The cell contains at least one replaceable actor, but not of the types we accept
                    var foundReplacement = ai.TraitInfos <ReplacementInfo>()
                                           .Any(r => r.ReplaceableTypes.Overlaps(acceptedReplacements));

                    if (!foundReplacement)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                // HACK: To preserve legacy behaviour, AllowInvalidPlacement should display red placement indicators
                // if (and only if) there is a building or bib in the cell
                var building = world.WorldActor.Trait <BuildingInfluence>().GetBuildingAt(cell);
                if (building != null)
                {
                    return(false);
                }
            }

            // Buildings can never be placed on ramps
            return(world.Map.Ramp[cell] == 0 && bi.TerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type));
        }
        public static bool CanPlaceBuilding(this World world, CPos cell, ActorInfo ai, BuildingInfo bi, Actor toIgnore)
        {
            if (bi.AllowInvalidPlacement)
            {
                return(true);
            }

            var res = world.WorldActor.TraitOrDefault <ResourceLayer>();

            return(bi.Tiles(cell).All(t => world.Map.Contains(t) &&
                                      (bi.AllowPlacementOnResources || res == null || res.GetResourceType(t) == null) &&
                                      world.IsCellBuildable(t, ai, bi, toIgnore)));
        }
        public static IEnumerable <(CPos Cell, Actor Actor)> GetLineBuildCells(World world, CPos cell, ActorInfo ai, BuildingInfo bi, Player owner)
        {
            var lbi     = ai.TraitInfo <LineBuildInfo>();
            var topLeft = cell;                 // 1x1 assumption!

            if (world.IsCellBuildable(topLeft, ai, bi))
            {
                yield return(topLeft, null);
            }

            // Start at place location, search outwards
            // TODO: First make it work, then make it nice
            var vecs = new[] { new CVec(1, 0), new CVec(0, 1), new CVec(-1, 0), new CVec(0, -1) };

            int[]   dirs       = { 0, 0, 0, 0 };
            Actor[] connectors = { null, null, null, null };

            for (var d = 0; d < 4; d++)
            {
                for (var i = 1; i < lbi.Range; i++)
                {
                    if (dirs[d] != 0)
                    {
                        continue;
                    }

                    // Continue the search if the cell is empty or not visible
                    var c = topLeft + i * vecs[d];
                    if (world.IsCellBuildable(c, ai, bi) || !owner.Shroud.IsExplored(c))
                    {
                        continue;
                    }

                    // Cell contains an actor. Is it the type we want?
                    connectors[d] = world.ActorMap.GetActorsAt(c)
                                    .FirstOrDefault(a => a.Info.TraitInfos <LineBuildNodeInfo>()
                                                    .Any(info => info.Types.Overlaps(lbi.NodeTypes) && info.Connections.Contains(vecs[d])));

                    dirs[d] = connectors[d] != null ? i : -1;
                }

                // Place intermediate-line sections
                if (dirs[d] > 0)
                {
                    for (var i = 1; i < dirs[d]; i++)
                    {
                        yield return(topLeft + i * vecs[d], connectors[d]);
                    }
                }
            }
        }
 public WithBuildingExplosion(Actor self, WithBuildingExplosionInfo info)
 {
     this.info    = info;
     buildingInfo = self.Info.Traits.Get <BuildingInfo>();
 }
Exemple #5
0
 public Bib(Actor self, BibInfo info)
 {
     this.info = info;
     rs        = self.Trait <RenderSprites>();
     bi        = self.Info.Traits.Get <BuildingInfo>();
 }
Exemple #6
0
 public IsometricSelectable(Actor self, IsometricSelectableInfo info)
 {
     this.info      = info;
     selectionClass = string.IsNullOrEmpty(info.Class) ? self.Info.Name : info.Class;
     buildingInfo   = self.Info.TraitInfo <BuildingInfo>();
 }
Exemple #7
0
        public static IEnumerable <Pair <CPos, Actor> > GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi)
        {
            var lbi     = world.Map.Rules.Actors[name].TraitInfo <LineBuildInfo>();
            var topLeft = location;             // 1x1 assumption!

            if (world.IsCellBuildable(topLeft, bi))
            {
                yield return(Pair.New <CPos, Actor>(topLeft, null));
            }

            // Start at place location, search outwards
            // TODO: First make it work, then make it nice
            var vecs = new[] { new CVec(1, 0), new CVec(0, 1), new CVec(-1, 0), new CVec(0, -1) };

            int[]   dirs       = { 0, 0, 0, 0 };
            Actor[] connectors = { null, null, null, null };

            for (var d = 0; d < 4; d++)
            {
                for (var i = 1; i < lbi.Range; i++)
                {
                    if (dirs[d] != 0)
                    {
                        continue;
                    }

                    var cell = topLeft + i * vecs[d];
                    if (world.IsCellBuildable(cell, bi))
                    {
                        continue;                         // Cell is empty; continue search
                    }
                    // Cell contains an actor. Is it the type we want?
                    connectors[d] = world.ActorMap.GetActorsAt(cell)
                                    .FirstOrDefault(a => a.Info.TraitInfos <LineBuildNodeInfo>()
                                                    .Any(info => info.Types.Overlaps(lbi.NodeTypes) && info.Connections.Contains(vecs[d])));

                    dirs[d] = connectors[d] != null ? i : -1;
                }

                // Place intermediate-line sections
                if (dirs[d] > 0)
                {
                    for (var i = 1; i < dirs[d]; i++)
                    {
                        yield return(Pair.New(topLeft + i * vecs[d], connectors[d]));
                    }
                }
            }
        }
Exemple #8
0
 void INotifyCreated.Created(Actor self)
 {
     buildingInfo = self.Info.TraitInfoOrDefault <BuildingInfo>();
 }
 bool IsRallyPointValid(CPos x, BuildingInfo info)
 {
     return(info != null && world.IsCellBuildable(x, null, info));
 }
Exemple #10
0
        public static bool IsCellBuildable(this World world, CPos cell, ActorInfo ai, BuildingInfo bi, Actor toIgnore = null)
        {
            if (!world.Map.Contains(cell))
            {
                return(false);
            }

            var building = world.WorldActor.Trait <BuildingInfluence>().GetBuildingAt(cell);

            if (building != null)
            {
                if (ai == null)
                {
                    return(false);
                }

                var replacementInfo = ai.TraitInfoOrDefault <ReplacementInfo>();
                if (replacementInfo == null)
                {
                    return(false);
                }

                if (!building.TraitsImplementing <Replaceable>().Any(p => !p.IsTraitDisabled &&
                                                                     p.Info.Types.Overlaps(replacementInfo.ReplaceableTypes)))
                {
                    return(false);
                }
            }
            else if (!bi.AllowInvalidPlacement && world.ActorMap.GetActorsAt(cell).Any(a => a != toIgnore))
            {
                return(false);
            }

            var tile     = world.Map.Tiles[cell];
            var tileInfo = world.Map.Rules.TileSet.GetTileInfo(tile);

            // TODO: This is bandaiding over bogus tilesets.
            if (tileInfo != null && tileInfo.RampType > 0)
            {
                return(false);
            }

            return(bi.TerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type));
        }
Exemple #11
0
 protected override void Created(Actor self)
 {
     buildingInfo = self.Info.TraitInfoOrDefault <BuildingInfo>();
     base.Created(self);
 }
Exemple #12
0
        public static IEnumerable <CPos> GetLineBuildCells(World world, CPos location, string name, BuildingInfo bi)
        {
            var lbi     = world.Map.Rules.Actors[name].TraitInfo <LineBuildInfo>();
            var topLeft = location;             // 1x1 assumption!

            if (world.IsCellBuildable(topLeft, bi))
            {
                yield return(topLeft);
            }

            // Start at place location, search outwards
            // TODO: First make it work, then make it nice
            var vecs = new[] { new CVec(1, 0), new CVec(0, 1), new CVec(-1, 0), new CVec(0, -1) };

            int[] dirs = { 0, 0, 0, 0 };
            for (var d = 0; d < 4; d++)
            {
                for (var i = 1; i < lbi.Range; i++)
                {
                    if (dirs[d] != 0)
                    {
                        continue;
                    }

                    var cell = topLeft + i * vecs[d];
                    if (world.IsCellBuildable(cell, bi))
                    {
                        continue;                         // Cell is empty; continue search
                    }
                    // Cell contains an actor. Is it the type we want?
                    if (world.ActorsWithTrait <LineBuildNode>().Any(a =>
                                                                    (a.Actor.Location == cell &&
                                                                     a.Actor.Info.TraitInfo <LineBuildNodeInfo>()
                                                                     .Types.Overlaps(lbi.NodeTypes))))
                    {
                        dirs[d] = i;                         // Cell contains actor of correct type
                    }
                    else
                    {
                        dirs[d] = -1;                         // Cell is blocked by another actor type
                    }
                }

                // Place intermediate-line sections
                if (dirs[d] > 0)
                {
                    for (var i = 1; i < dirs[d]; i++)
                    {
                        yield return(topLeft + i * vecs[d]);
                    }
                }
            }
        }
Exemple #13
0
        public static bool IsCellBuildable(this World world, CPos cell, ActorInfo ai, BuildingInfo bi, Actor toIgnore = null)
        {
            if (!world.Map.Contains(cell))
            {
                return(false);
            }

            var building = world.WorldActor.Trait <BuildingInfluence>().GetBuildingAt(cell);

            if (building != null)
            {
                if (ai == null)
                {
                    return(false);
                }

                var replacementInfo = ai.TraitInfoOrDefault <ReplacementInfo>();
                if (replacementInfo == null)
                {
                    return(false);
                }

                if (!building.TraitsImplementing <Replaceable>().Any(p => !p.IsTraitDisabled &&
                                                                     p.Info.Types.Overlaps(replacementInfo.ReplaceableTypes)))
                {
                    return(false);
                }
            }
            else if (!bi.AllowInvalidPlacement && world.ActorMap.GetActorsAt(cell).Any(a => a != toIgnore))
            {
                return(false);
            }

            // Buildings can never be placed on ramps
            return(world.Map.Ramp[cell] == 0 && bi.TerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type));
        }
Exemple #14
0
        public static CVec AdjustForBuildingSize(BuildingInfo buildingInfo)
        {
            var dim = buildingInfo.Dimensions;

            return(new CVec(dim.X / 2, dim.Y > 1 ? (dim.Y + 1) / 2 : 0));
        }