diff --git a/tools/AetherDb/Program.cs b/tools/AetherDb/Program.cs index 253d0598f..034bbfd6f 100644 --- a/tools/AetherDb/Program.cs +++ b/tools/AetherDb/Program.cs @@ -36,10 +36,8 @@ public static class Program case "targeting-catalog": return TargetingCatalog(args.Contains("apply")); case "targeting-catalog-6c": return TargetingCatalog6c(args.Contains("apply")); case "targeting-catalog-6d": return TargetingCatalog6d(args.Contains("apply")); - case "product-gap": return ProductGap(args.Contains("apply")); - case "station-reactor": return StationReactor(args.Contains("apply")); default: - Console.WriteLine("commands: census, factions, station-fit, hardpoint-fit, loadout [seed], save, settings, settings-dump, dangling [clear ]... [apply], shield-migrate [apply], brownout-migrate [apply], roles-migrate [apply], firing-arc-migrate [apply], targeting-catalog [apply], targeting-catalog-6c [apply], targeting-catalog-6d [apply], product-gap [apply], station-reactor [apply]"); + Console.WriteLine("commands: census, factions, station-fit, hardpoint-fit, loadout [seed], save, settings, settings-dump, dangling [clear ]... [apply], shield-migrate [apply], brownout-migrate [apply], roles-migrate [apply], firing-arc-migrate [apply], targeting-catalog [apply], targeting-catalog-6c [apply], targeting-catalog-6d [apply]"); return 1; } } @@ -1473,151 +1471,4 @@ public static class Program Console.WriteLine($"\nLanded {precisionChanges.Length} Precision changes in Aetheria.cc"); return 0; } - - // Scenarios map, operator rulings 2026-09-30 ("the ten product-less designs"): after this, a design with no - // product is a Q3 scenario test design and nothing else. The five RTS-era industrial placeholders are deleted - // (nothing references them). The four weapons are a content gap and get a product each, from the maker of their - // nearest analogue: same hardpoint and firing behaviour, then nearest size. The Industrial Thermostatic Heater is - // generic gear every generated station carries; it gets a product from the maker of the cockpit whose thermostat - // it shares (Thermotoggle, EnergyDraw, Heat in one group), and the price and durability without which generation - // cannot offer it (RandomProducts skips a zero price) and it can never come online (zero durability). - private static int ProductGap(bool apply) - { - var db = AetherDb.Open(catalogWritable: apply); - var cache = db.Cache; - - T Design(string name) where T : EquippableItemData => - cache.GetAll().SingleOrDefault(d => d.Name == name) ?? throw new InvalidOperationException($"No design named \"{name}\"."); - Faction MakerOf(string productName) => - cache.Get(cache.GetAll().Single(p => p.Name == productName).Manufacturer); - Faction Named(string factionName) => cache.GetAll().Single(f => f.Name == factionName); - bool HasProduct(EquippableItemData design) => - cache.GetAll().Any(p => p.Design.Key.Equals(cache.RefOf(design).Key)); - - var industrial = new[] { "Assembly Line", "Deep Ore Extractor", "Surface Ore Extractor", "Refinery", "Shipyard" } - .Select(Design).ToArray(); - foreach (var design in industrial) - if (HasProduct(design)) throw new InvalidOperationException($"{design.Name} has a product; it is not a placeholder."); - - var heater = Design("Industrial Thermostatic Heater"); - var products = new (EquippableItemData Design, string Name, string Description, Faction Maker, string Analogue)[] - { - (Design("Autocannon"), "Autocannon", "", MakerOf("DeathCluster"), - "DeathCluster: Ballistic, 4 cells, AutoWeapon"), - (Design("LRMM72"), "LRMM72", "", MakerOf("GT 3K"), - "GT 3K: the only other unguided LauncherData"), - (Design("SRMM72"), "SRMM72", "", MakerOf("scorched void policy"), - "scorched void policy: GuidedWeapon launcher, nearest in size and price"), - (Design("Tractor Beam"), "Space Tractor", "It's a tractor. In space.", Named("Ewan Hart Inc"), - "none (no behaviours); Ewan Hart's wishlist Space Tractor, docs/content-batch-one.md section 10"), - (heater, "Industrial Thermostatic Heater", "", MakerOf("Cockpit 2x2"), - "Cockpit 2x2: the same thermostat behaviours"), - }; - foreach (var (design, _, _, _, _) in products) - if (HasProduct(design)) throw new InvalidOperationException($"{design.Name} already has a product."); - const int heaterPrice = 100000; // between Cockpit 2x2 (50,000) and Fire Control Array (150,000) - const float heaterDurability = 100; // Cockpit 2x2's - - Console.WriteLine("Delete (no product, no reference):"); - foreach (var design in industrial) Console.WriteLine($" {design.Name}"); - Console.WriteLine("Products:"); - foreach (var (design, name, _, maker, analogue) in products) - Console.WriteLine($" {design.Name,-32} -> {name,-32} by {maker.Name,-24} ({analogue})"); - Console.WriteLine($"Heater design: Price {heater.Price} -> {heaterPrice}, Durability {heater.Durability} -> {heaterDurability}"); - - if (!apply) - { - Console.WriteLine("\nDry run. Pass \"apply\" to land it."); - return 0; - } - - heater.Price = heaterPrice; - heater.Durability = heaterDurability; - CultRecordRefs.Validate(heater); - var industrialKeys = industrial.Select(design => cache.RefOf(design).Key).ToArray(); - var heaterKey = cache.RefOf(heater).Key; - var made = products.Select(entry => new FactionProductData - { - Name = entry.Name, - Description = entry.Description, - Design = new CultRecordRef(cache.RefOf(entry.Design).Key), - Manufacturer = cache.RefOf(entry.Maker), - Roles = (entry.Design.Roles ?? new List()).Select(role => new ProductRole { Role = role.Name }).ToList() - }).ToArray(); - cache.Commit(batch => - { - foreach (var key in industrialKeys) batch.Remove(key); - batch.Upsert(typeof(GearData), heater, heaterKey); - foreach (var product in made) batch.Upsert(typeof(FactionProductData), product, new CultRecordKey(Guid.NewGuid().ToString("N"))); - }); - Console.WriteLine($"\nLanded {industrial.Length} deletions, {made.Length} products and the heater's price and durability in Aetheria.cc"); - return 0; - } - - // Scenarios map, operator ruling 2026-09-30 ("Yep, we need a station reactor"): Zenith's 16-cell Reactor hardpoint - // had no design to fill it, so generated stations had no power and their heater never ran. The station reactor is - // Manhattan, the largest and most industrial reactor, scaled to the slot: a full 4x4, its charge, mass and price - // times 16/9 (its cells over Manhattan's), every other value and stat term Manhattan's own, sold by Manhattan's maker. - private static int StationReactor(bool apply) - { - var db = AetherDb.Open(catalogWritable: apply); - var cache = db.Cache; - if (cache.GetAll().Any(d => d.Name == "Station Reactor")) throw new InvalidOperationException("Station Reactor already exists."); - var manhattan = cache.GetAll().Single(d => d.Name == "Manhattan"); - var manhattanProduct = cache.GetAll().Single(p => p.Design.Key.Equals(cache.RefOf(manhattan).Key)); - const float scale = 16f / 9f; - - var shape = new Shape(4, 4); - foreach (var cell in shape.AllCoordinates) shape[cell] = true; - var design = new GearData - { - Name = "Station Reactor", - Description = "A reactor sized for a station's core.", - Hardpoint = HardpointType.Reactor, - Shape = shape, - Mass = manhattan.Mass * scale, - Price = (int) Math.Round(manhattan.Price * scale / 50000) * 50000, - SpecificHeat = manhattan.SpecificHeat, - Conductivity = manhattan.Conductivity, - Durability = manhattan.Durability, - MinimumTemperature = manhattan.MinimumTemperature, - MaximumTemperature = manhattan.MaximumTemperature, - OptimalTemperature = manhattan.OptimalTemperature, - PlateauWidth = manhattan.PlateauWidth, - ThermalResilience = manhattan.ThermalResilience, - SoundBank = manhattan.SoundBank, - Roles = manhattan.Roles.Select(role => new ItemRole { Name = role.Name }).ToList(), - Behaviors = MessagePack.MessagePackSerializer.Deserialize>(MessagePack.MessagePackSerializer.Serialize(manhattan.Behaviors)), - }; - var reactor = design.Behaviors.OfType().Single(); - reactor.Charge.Min *= scale; - reactor.Charge.Max *= scale; - var product = new FactionProductData - { - Name = "Station Reactor", - Description = "", - Manufacturer = manhattanProduct.Manufacturer, - Roles = design.Roles.Select(role => new ProductRole { Role = role.Name }).ToList(), - }; - - Console.WriteLine($"Station Reactor, from Manhattan x {scale:F3}: shape 4x4 (16), mass {manhattan.Mass} -> {design.Mass}, " + - $"price {manhattan.Price} -> {design.Price}, charge {reactor.Charge.Min / scale}..{reactor.Charge.Max / scale} -> {reactor.Charge.Min}..{reactor.Charge.Max}; " + - $"product by {cache.Get(product.Manufacturer).Name}"); - if (!apply) - { - Console.WriteLine("\nDry run. Pass \"apply\" to land it."); - return 0; - } - - CultRecordRefs.Validate(design); - var key = new CultRecordKey(Guid.NewGuid().ToString("N")); - product.Design = new CultRecordRef(key); - cache.Commit(batch => - { - batch.Upsert(typeof(GearData), design, key); - batch.Upsert(typeof(FactionProductData), product, new CultRecordKey(Guid.NewGuid().ToString("N"))); - }); - Console.WriteLine("\nLanded the Station Reactor and its product in Aetheria.cc"); - return 0; - } }