예제 #1
0
        public void AddedToWorld(Actor self)
        {
            var map = self.World.Map;

            if (template.PickAny)
            {
                // Fill the footprint with random variants
                foreach (var c in FootprintUtils.Tiles(self))
                {
                    // Only place on allowed terrain types
                    if (!info.TerrainTypes.Contains(map.GetTerrainInfo(c).Type))
                    {
                        continue;
                    }

                    // Don't place under other buildings or custom terrain
                    if (bi.GetBuildingAt(c) != self || map.CustomTerrain[c] != -1)
                    {
                        continue;
                    }

                    var index = Game.CosmeticRandom.Next(template.TilesCount);
                    layer.AddTile(c, new TerrainTile(template.Id, (byte)index));
                }

                return;
            }

            var origin = self.Location + info.Offset;

            for (var i = 0; i < template.TilesCount; i++)
            {
                var c = origin + new CVec(i % template.Size.X, i / template.Size.X);

                // Only place on allowed terrain types
                if (!info.TerrainTypes.Contains(map.GetTerrainInfo(c).Type))
                {
                    continue;
                }

                // Don't place under other buildings or custom terrain
                if (bi.GetBuildingAt(c) != self || map.CustomTerrain[c] != -1)
                {
                    continue;
                }

                layer.AddTile(c, new TerrainTile(template.Id, (byte)i));
            }
        }
예제 #2
0
        public void AddedToWorld(Actor self)
        {
            if (template.PickAny)
            {
                // Fill the footprint with random variants
                foreach (var c in FootprintUtils.Tiles(self))
                {
                    // Only place on allowed terrain types
                    if (!info.TerrainTypes.Contains(self.World.GetTerrainType(c)))
                    {
                        continue;
                    }

                    // Don't place under other buildings or custom terrain
                    if (bi.GetBuildingAt(c) != self || self.World.Map.CustomTerrain[c.X, c.Y] != null)
                    {
                        continue;
                    }

                    var index = template.Tiles.Keys.Random(Game.CosmeticRandom);
                    layer.AddTile(c, new TileReference <ushort, byte>(template.Id, index));
                }

                return;
            }

            var origin = self.Location + info.Offset;

            foreach (var i in template.Tiles.Keys)
            {
                var c = origin + new CVec(i % template.Size.X, i / template.Size.X);

                // Only place on allowed terrain types
                if (!info.TerrainTypes.Contains(self.World.GetTerrainType(c)))
                {
                    continue;
                }

                // Don't place under other buildings or custom terrain
                if (bi.GetBuildingAt(c) != self || self.World.Map.CustomTerrain[c.X, c.Y] != null)
                {
                    continue;
                }

                layer.AddTile(c, new TileReference <ushort, byte>(template.Id, i));
            }
        }
예제 #3
0
        protected override void AddedToWorld(Actor self)
        {
            base.AddedToWorld(self);

            if (layer != null && (!info.ConcretePrerequisites.Any() || techTree == null || techTree.HasPrerequisites(info.ConcretePrerequisites)))
            {
                var map = self.World.Map;

                if (!(self.World.Map.Rules.TerrainInfo is ITemplatedTerrainInfo terrainInfo))
                {
                    throw new InvalidDataException("D2kBuilding requires a template-based tileset.");
                }

                var template = terrainInfo.Templates[info.ConcreteTemplate];
                if (template.PickAny)
                {
                    // Fill the footprint with random variants
                    foreach (var c in info.Tiles(self.Location))
                    {
                        // Only place on allowed terrain types
                        if (!map.Contains(c) || map.CustomTerrain[c] != byte.MaxValue || !info.TerrainTypes.Contains(map.GetTerrainInfo(c).Type))
                        {
                            continue;
                        }

                        // Don't place under other buildings (or their bib)
                        if (bi.GetBuildingsAt(c).Any(a => a != self))
                        {
                            continue;
                        }

                        var index = Game.CosmeticRandom.Next(template.TilesCount);
                        layer.AddTile(c, new TerrainTile(template.Id, (byte)index));
                    }
                }
                else
                {
                    for (var i = 0; i < template.TilesCount; i++)
                    {
                        var c = self.Location + new CVec(i % template.Size.X, i / template.Size.X);

                        // Only place on allowed terrain types
                        if (!map.Contains(c) || map.CustomTerrain[c] != byte.MaxValue || !info.TerrainTypes.Contains(map.GetTerrainInfo(c).Type))
                        {
                            continue;
                        }

                        // Don't place under other buildings (or their bib)
                        if (bi.GetBuildingsAt(c).Any(a => a != self))
                        {
                            continue;
                        }

                        layer.AddTile(c, new TerrainTile(template.Id, (byte)i));
                    }
                }
            }

            if (health == null)
            {
                return;
            }

            foreach (var kv in self.OccupiesSpace.OccupiedCells())
            {
                totalTiles++;
                if (!info.DamageTerrainTypes.Contains(self.World.Map.GetTerrainInfo(kv.Cell).Type))
                {
                    safeTiles++;
                }
            }

            if (totalTiles == 0 || totalTiles == safeTiles)
            {
                return;
            }

            // Cast to long to avoid overflow when multiplying by the health
            damageThreshold = (int)((info.DamageThreshold * (long)health.MaxHP + (100 - info.DamageThreshold) * safeTiles * (long)health.MaxHP / totalTiles) / 100);

            if (!info.StartOnThreshold)
            {
                return;
            }

            // Start with maximum damage applied, ignoring modifiers like player handicap
            var delta = health.HP - damageThreshold;

            if (delta > 0)
            {
                health.InflictDamage(self, self.World.WorldActor, new Damage(delta, info.DamageTypes), true);
            }
        }
예제 #4
0
        protected override void AddedToWorld(Actor self)
        {
            base.AddedToWorld(self);

            if (layer != null && (!info.ConcretePrerequisites.Any() || techTree == null || techTree.HasPrerequisites(info.ConcretePrerequisites)))
            {
                var map      = self.World.Map;
                var template = map.Rules.TileSet.Templates[info.ConcreteTemplate];
                if (template.PickAny)
                {
                    // Fill the footprint with random variants
                    foreach (var c in info.Tiles(self.Location))
                    {
                        if (!map.Contains(c) || map.CustomTerrain[c] != byte.MaxValue)
                        {
                            continue;
                        }

                        // Don't place under other buildings
                        if (self.World.ActorMap.GetActorsAt(c).Any(a => a != self && a.TraitOrDefault <Building>() != null))
                        {
                            continue;
                        }

                        var index = Game.CosmeticRandom.Next(template.TilesCount);
                        layer.AddTile(c, new TerrainTile(template.Id, (byte)index));
                    }
                }
                else
                {
                    for (var i = 0; i < template.TilesCount; i++)
                    {
                        var c = self.Location + new CVec(i % template.Size.X, i / template.Size.X);
                        if (!map.Contains(c) || map.CustomTerrain[c] != byte.MaxValue)
                        {
                            continue;
                        }

                        // Don't place under other buildings
                        if (self.World.ActorMap.GetActorsAt(c).Any(a => a != self && a.TraitOrDefault <Building>() != null))
                        {
                            continue;
                        }

                        layer.AddTile(c, new TerrainTile(template.Id, (byte)i));
                    }
                }
            }

            if (health == null)
            {
                return;
            }

            foreach (var kv in self.OccupiesSpace.OccupiedCells())
            {
                totalTiles++;
                if (!info.DamageTerrainTypes.Contains(self.World.Map.GetTerrainInfo(kv.Cell).Type))
                {
                    safeTiles++;
                }
            }

            if (totalTiles == 0 || totalTiles == safeTiles)
            {
                return;
            }

            // Cast to long to avoid overflow when multiplying by the health
            damageThreshold = (int)((info.DamageThreshold * (long)health.MaxHP + (100 - info.DamageThreshold) * safeTiles * (long)health.MaxHP / totalTiles) / 100);

            if (!info.StartOnThreshold)
            {
                return;
            }

            // Start with maximum damage applied
            var delta = health.HP - damageThreshold;

            if (delta > 0)
            {
                self.InflictDamage(self.World.WorldActor, new Damage(delta, info.DamageTypes));
            }
        }