예제 #1
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);
            }
        }
예제 #2
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));
            }
        }