Smoke Test Hull fixes: the home rule reads sold hulls only; command and flank geometry pinned; turret off the starboard line
LoadoutGenerator.SoldHulls is the one definition of the hulls HasHome considers (a hull some product sells); AvailableProducts and the tests read it, so the product-less test hull gives no gear a home. TheSoldHardpointGearWithNoHomeToday describes production again. SmokeHullCommandTests pins each added hardpoint's firing arc, armour and shape; ArcsFlanks asserts the flank hulls abeam from the player's facing within 5 degrees; Arcs' Turret moves to (600,300). Not yet built or run at this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5c294ef994
commit
2a943370ab
6 changed files with 28 additions and 9 deletions
|
|
@ -186,7 +186,7 @@ public class LoadoutGenerator
|
|||
// not once a required item has fallen back to any manufacturer). The one availability rule for every selection.
|
||||
private ((FactionProductData product, T design)[] available, bool preferManufacturers) AvailableProducts<T>(Predicate<T> filter, bool required) where T : CraftedItemData
|
||||
{
|
||||
var hulls = ItemManager.ItemData.GetAll<HullData>().ToArray();
|
||||
var hulls = SoldHulls(ItemManager.ItemData);
|
||||
var candidates = ItemManager.ItemData.GetAll<FactionProductData>()
|
||||
.Select(product => (product, design: ItemManager.ItemData.Get(product.Design) as T))
|
||||
.Where(entry =>
|
||||
|
|
@ -231,6 +231,11 @@ public class LoadoutGenerator
|
|||
// Hardpoint gear that no hull in the catalog can mount has no home (operator, 2026-09-30: "we'll need to author a
|
||||
// bunch more hulls before all the gear variety in the game has a home"): generation never offers it, so no station
|
||||
// stocks it. It gains one the moment a hull with a hardpoint that takes it exists. Tool gear goes in any interior.
|
||||
// Only a hull some product sells gives gear a home: a hull no faction builds (the Smoke Test Hull) is a test fixture, so its
|
||||
// hardpoints never put gear on a shelf. The one definition of the hulls HasHome considers.
|
||||
public static HullData[] SoldHulls(CultCache items) =>
|
||||
items.GetAll<FactionProductData>().Select(product => items.Get(product.Design)).OfType<HullData>().Distinct().ToArray();
|
||||
|
||||
public static bool HasHome(EquippableItemData design, HullData[] hulls) =>
|
||||
design.HardpointType == HardpointType.Tool || design.HardpointType == HardpointType.Hull ||
|
||||
hulls.Any(hull => hull.Hardpoints.Any(hardpoint => hardpoint.Takes(design)));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed class Arcs : Scenario
|
|||
|
||||
// Where the targets sit: the player is at the origin facing +z. The forward mounts fire forward, the starboard mount
|
||||
// (Clockwise) along +x and the port mount (CounterClockwise) along -x.
|
||||
public static readonly CultMath.float2 Bow = float2(0, 400), Stern = float2(0, -400), Turret = float2(600, 0),
|
||||
public static readonly CultMath.float2 Bow = float2(0, 400), Stern = float2(0, -400), Turret = float2(600, 300),
|
||||
Port = float2(-400, 0), Starboard = float2(400, 0);
|
||||
|
||||
public override Galaxy Generate(GalaxyStage stage) => stage.Prelude();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public sealed partial class RunStartTests
|
|||
|
||||
var products = PiratesProducts();
|
||||
Assert.Equal(8, products.Length);
|
||||
var hulls = _cache.GetAll<HullData>().ToArray();
|
||||
var hulls = LoadoutGenerator.SoldHulls(_cache);
|
||||
foreach (var product in products)
|
||||
{
|
||||
var design = _cache.Get(product.Design) as EquippableItemData;
|
||||
|
|
|
|||
|
|
@ -439,17 +439,17 @@ public sealed partial class RunStartTests : IDisposable
|
|||
Assert.True(disagreements.Count == 0, string.Join("; ", disagreements.Take(10)) + $" ({disagreements.Count} in all)");
|
||||
}
|
||||
|
||||
// The sold hardpoint gear that no sold hull fits even loosely today (a test hull no product sells gives no gear a
|
||||
// home), stated so that authoring a hull that takes one shows up here as a changed list.
|
||||
// The sold hardpoint gear the generator gives no home today: the production rule (LoadoutGenerator.HasHome over the hulls a
|
||||
// product sells). The Smoke Test Hull, which no product sells, gives ChargeBlast SG and ChargeBlast+- no home; authoring a
|
||||
// sold hull that takes one shows up here as a changed list.
|
||||
[Fact]
|
||||
public void TheSoldHardpointGearWithNoHomeToday()
|
||||
{
|
||||
var sold = _cache.GetAll<FactionProductData>().Select(product => product.Design.Key).ToHashSet();
|
||||
var hulls = _cache.GetAll<HullData>().Where(hull => sold.Contains(_cache.RefOf(hull).Key)).ToArray();
|
||||
var hulls = LoadoutGenerator.SoldHulls(_cache);
|
||||
var homeless = _cache.GetAll<EquippableItemData>()
|
||||
.Where(design => sold.Contains(_cache.RefOf(design).Key) && design.Price > 0)
|
||||
.Where(design => design.HardpointType != HardpointType.Tool && design.HardpointType != HardpointType.Hull)
|
||||
.Where(design => !hulls.Any(hull => hull.Hardpoints.Any(hardpoint => hardpoint.Takes(design))))
|
||||
.Where(design => !LoadoutGenerator.HasHome(design, hulls))
|
||||
.Select(design => design.Name).OrderBy(name => name, StringComparer.Ordinal).ToArray();
|
||||
Assert.Equal(new[] { "CShot RainbowLite Lazer", "ChargeBlast SG", "ChargeBlast+-", "OK Disperser" }, homeless);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,13 @@ public sealed class SmokeHullCommandTests : IDisposable
|
|||
Assert.Single(added, h => h.Type == HardpointType.Ballistic && h.Rotation == ItemRotation.None && h.Takes(autocannon));
|
||||
Assert.Single(added, h => h.Type == HardpointType.Ballistic && h.Rotation == ItemRotation.Clockwise && h.Takes(autocannon));
|
||||
Assert.Single(added, h => h.Type == HardpointType.Energy && h.Rotation == ItemRotation.CounterClockwise && h.Takes(chargeBlast));
|
||||
// Each is a full 2x2 block with the default firing arc (0 uses the game setting; the side mounts bear by it, never wider)
|
||||
// and the Longinus-class armour the command writes.
|
||||
Assert.All(added, hardpoint =>
|
||||
{
|
||||
Assert.Equal((2, 2, 0f, 20f), (hardpoint.Shape.Width, hardpoint.Shape.Height, hardpoint.FiringArc, hardpoint.Armor));
|
||||
Assert.Equal(4, hardpoint.Shape.Coordinates.Length);
|
||||
});
|
||||
foreach (var hardpoint in added)
|
||||
foreach (var cell in hardpoint.Shape.Coordinates)
|
||||
Assert.True(hull.Shape[hardpoint.Position + cell], "a new hardpoint lies outside the hull's cells");
|
||||
|
|
|
|||
|
|
@ -46,7 +46,14 @@ public sealed partial class RunStartTests
|
|||
var player = staged.Player;
|
||||
player.GenerateWeaponGroups();
|
||||
var (bow, stern, port, starboard) = (staged.Entities[0], staged.Entities[1], staged.Entities[3], staged.Entities[4]);
|
||||
Assert.Equal((Arcs.Port, Arcs.Starboard), (port.Position.xz, starboard.Position.xz));
|
||||
// The flank hulls lie abeam from the player's facing, read from the staged positions: within 5 degrees of the
|
||||
// perpendicular, starboard on the right of the facing and port on the left.
|
||||
var facing = player.Direction;
|
||||
var right = CultMath.math.float2(facing.y, -facing.x);
|
||||
float Abeam(Entity flank, CultMath.float2 side) => CultMath.math.dot(CultMath.math.normalize(flank.Position.xz - player.Position.xz), side);
|
||||
var abeam = CultMath.math.cos(CultMath.math.radians(5f));
|
||||
Assert.True(Abeam(starboard, right) >= abeam, "the starboard hull is not abeam to starboard");
|
||||
Assert.True(Abeam(port, -right) >= abeam, "the port hull is not abeam to port");
|
||||
|
||||
var mounts = WeaponMounts(player);
|
||||
var forward = mounts.Where(item => item.EquippableItem.Rotation == ItemRotation.None).ToList();
|
||||
|
|
|
|||
Loading…
Reference in a new issue