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