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); } }
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)); } }