LoadoutGenerator.IsDrawable is the one definition of 'a maker offers this design'; StationKinds keeps a kind by it

AvailableProducts (Price > 0, a set Manufacturer, offered) and StationKinds.OfferedKinds (offered only) disagreed, so Choose could keep a kind
whose hull draw returns null. Both now ask IsDrawable; OfferedKinds and OfferedStationHulls read the same drawable station products.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
soul 2026-10-23 18:02:47 +02:00
commit e403905e12
2 changed files with 15 additions and 12 deletions

View file

@ -200,11 +200,8 @@ public class LoadoutGenerator
var candidates = ItemManager.ItemData.GetAll<FactionProductData>()
.Select(product => (product, design: ItemManager.ItemData.Get(product.Design) as T))
.Where(entry =>
entry.design != null &&
entry.design.Price > 0 &&
entry.product.Manufacturer.IsSet() &&
// A not-offered product is never a candidate, so the any-manufacturer fallback below cannot reach it either.
IsOffered(ItemManager.ItemData, entry.product) &&
IsDrawable(ItemManager.ItemData, entry.product, entry.design) &&
(!(entry.design is EquippableItemData equippable) || HasHome(equippable, hulls)) &&
(filter?.Invoke(entry.design) ?? true))
.ToArray();
@ -246,6 +243,12 @@ public class LoadoutGenerator
Galaxy == null || Faction == null ||
ItemManager.ItemData.Get(product.Manufacturer) == Faction || Faction.Allegiance.ContainsKey(product.Manufacturer));
// Whether a product can be drawn for its design at all: the design resolves, has a price, the product names a maker and is
// offered. The one definition of 'a maker offers this design'; AvailableProducts selects by it and StationKinds decides which
// station kinds a hull can be drawn for by it, so a kind is kept exactly when a hull of it can be drawn.
public static bool IsDrawable(CultCache items, FactionProductData product, CraftedItemData design) =>
design != null && design.Price > 0 && product.Manufacturer.IsSet() && IsOffered(items, product);
// Whether a product is on the market at all (ruling off-market-is-unoffered-product). The one reader of NotOffered. A bin is
// offered only if both it and its line are (ruling bin-inherits-line-offered); the catalog read guarantees a bin's line exists.
public static bool IsOffered(CultCache items, FactionProductData product) =>

View file

@ -138,17 +138,17 @@ public static class StationKinds
// The hull kinds some maker offers: the pool a station can always be drawn from.
private static HashSet<string> OfferedKinds(CultCache catalog) =>
new HashSet<string>(
catalog.GetAll<FactionProductData>().Where(product => LoadoutGenerator.IsOffered(catalog, product))
.Select(product => catalog.Get(product.Design) as HullData)
.Where(hull => hull != null && hull.HullType == HullType.Station && hull.Kind.IsSet())
.Select(hull => hull.Kind.Key.Value), StringComparer.Ordinal);
new HashSet<string>(DrawableStationProducts(catalog).Select(entry => entry.hull.Kind.Key.Value), StringComparer.Ordinal);
private static IEnumerable<HullData> OfferedStationHulls(CultCache catalog, Faction faction) =>
DrawableStationProducts(catalog).Where(entry => catalog.Get(entry.product.Manufacturer) == faction).Select(entry => entry.hull);
// The station hulls a hull draw can reach (LoadoutGenerator.IsDrawable, the one definition), with the product that sells each.
private static IEnumerable<(FactionProductData product, HullData hull)> DrawableStationProducts(CultCache catalog) =>
catalog.GetAll<FactionProductData>()
.Where(product => LoadoutGenerator.IsOffered(catalog, product) && catalog.Get(product.Manufacturer) == faction)
.Select(product => catalog.Get(product.Design) as HullData)
.Where(hull => hull != null && hull.HullType == HullType.Station && hull.Kind.IsSet());
.Select(product => (product, hull: catalog.Get(product.Design) as HullData))
.Where(entry => entry.hull != null && entry.hull.HullType == HullType.Station && entry.hull.Kind.IsSet() &&
LoadoutGenerator.IsDrawable(catalog, entry.product, entry.hull));
private static CultRecordRef<StationKindData>[] Ordered(IEnumerable<string> keys) =>
keys.OrderBy(key => key, StringComparer.Ordinal).Select(key => new CultRecordRef<StationKindData>(new CultRecordKey(key))).ToArray();