Merge cut-scenarios-smoke (verdict cut-scenarios-smoke.s2)

Scenarios.cs Tests list: kept WeaponFeel, Pursuit and Crossing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-11 23:28:05 +02:00
commit b6262467f0
13 changed files with 356 additions and 38 deletions

View file

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

View file

@ -4,34 +4,42 @@ using static ItemRotation;
public sealed class Arcs : Scenario
{
public override string Name => "Arcs";
public override string Brief => "Forward mounts, a bare hull off the bow, one off the stern, a hostile turret. Verify: the hull keeps its " +
public override string Brief => "The Smoke Test Hull with forward mounts and a side mount on each flank; a bare hull off the bow, one off " +
"the stern, one abeam to port, one abeam to starboard, and a hostile turret. Verify: the hull keeps its " +
"heading while you aim at the stern hull, and the forward guns hold. Designate the bow hull and fire with the " +
"aim anywhere: the forward guns fire on it and hit. The turret tracks you all the way round.";
"aim anywhere: the forward guns fire on it and hit. The side guns fire at their beam hull and never through " +
"the hull. Designate the starboard hull, aim ahead and fire its group: it fires on the hull without the aim " +
"and the port group holds; undesignate and aim to port: the port group fires free. The turret tracks you " +
"all the way round.";
public override uint Seed => 103;
public override bool Ambient => false;
// Where the targets sit: the player is at the origin facing +z, and every mount fires forward.
public static readonly CultMath.float2 Bow = float2(0, 400), Stern = float2(0, -400), Turret = float2(600, 0);
// 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, 300),
Port = float2(-400, 0), Starboard = float2(400, 0);
public override Galaxy Generate(GalaxyStage stage) => stage.Prelude();
public override void Stage(ScenarioStage stage)
{
var fighter = stage.Fit("Longinus",
("Cockpit 2x2", int2(2, 6), None),
("Large Drive", int2(1, 0), Reversed),
var fighter = stage.Fit("Smoke Test Hull",
("Cockpit 2x2", int2(4, 6), None),
("Large Drive", int2(3, 0), Reversed),
("Talaria", int2(2, 14), CounterClockwise),
("Talaria", int2(3, 14), Clockwise),
("Core Power", int2(2, 4), None),
("GT 3K", int2(0, 5), None),
("GT 3K", int2(5, 5), None),
("FastBlast+-", int2(1, 8), None),
("FastBlast+-", int2(4, 8), None),
("Iapyx", int2(2, 2), CounterClockwise),
("Iapyx", int2(3, 2), Clockwise),
("not if i see you first", int2(3, 10), None),
("Fire Control Array", int2(1, 6), Clockwise));
("Large Drive", int2(5, 0), Reversed),
("Talaria", int2(4, 14), CounterClockwise),
("Talaria", int2(5, 14), Clockwise),
("Core Power", int2(4, 4), None),
("GT 3K", int2(2, 5), None),
("GT 3K", int2(7, 5), None),
("FastBlast+-", int2(3, 8), None),
("FastBlast+-", int2(6, 8), None),
("Iapyx", int2(4, 2), CounterClockwise),
("Iapyx", int2(5, 2), Clockwise),
("not if i see you first", int2(5, 10), None),
("Fire Control Array", int2(3, 6), Clockwise),
("Autocannon", int2(8, 4), Clockwise),
("ChargeBlast SG", int2(0, 4), CounterClockwise));
var turret = stage.Fit("Turret",
("ClearPath", int2(1, 2), None),
("ClearPath", int2(5, 2), None),
@ -46,5 +54,7 @@ public sealed class Arcs : Scenario
stage.Place(stage.Bare("Longinus"), Bow);
stage.Place(stage.Bare("Longinus"), Stern);
stage.Place(turret, Turret, stance: ScenarioStance.Hostile);
stage.Place(stage.Bare("Longinus"), Port);
stage.Place(stage.Bare("Longinus"), Starboard);
}
}

View file

@ -9,6 +9,6 @@ public static class Scenarios
public static readonly Scenario[] Tests =
{
new DjinniShakedown(), new StarvedReactor(), new Arcs(), new Duel(), new LauncherAngles(), new LongHaul(), new Pursuit(), new Crossing()
new DjinniShakedown(), new StarvedReactor(), new Arcs(), new Duel(), new LauncherAngles(), new WeaponFeel(), new LongHaul(), new Pursuit(), new Crossing()
};
}

View file

@ -0,0 +1,38 @@
using static CultMath.math;
using static ItemRotation;
public sealed class WeaponFeel : Scenario
{
public override string Name => "Weapon Feel";
public override string Brief => "The Smoke Test Hull with a ChargeBlast SG, an Autocannon and a FastBlast+- burst weapon; a bare Longinus dead ahead. " +
"Verify: ChargeBlast SG and Autocannon fire with effects, particles and action-bar icons; the burst weapon's " +
"cadence is as before; a fast release-and-press on the ChargeBlast SG starts no second charge.";
public override uint Seed => 107;
public override bool Ambient => false;
// The one target, ahead of the nose: inside every forward mount's arc.
public static readonly CultMath.float2 Target = float2(0, 400);
public override Galaxy Generate(GalaxyStage stage) => stage.Prelude(DemoTerminus.Cast);
public override void Stage(ScenarioStage stage)
{
var shooter = stage.Fit("Smoke Test Hull",
("Cockpit 2x2", int2(4, 6), None),
("Large Drive", int2(3, 0), Reversed),
("Large Drive", int2(5, 0), Reversed),
("Talaria", int2(4, 14), CounterClockwise),
("Talaria", int2(5, 14), Clockwise),
("Core Power", int2(4, 4), None),
("ChargeBlast SG", int2(3, 17), None),
("Autocannon", int2(5, 17), None),
("FastBlast+-", int2(3, 8), None),
("Iapyx", int2(4, 2), CounterClockwise),
("Iapyx", int2(5, 2), Clockwise),
("not if i see you first", int2(5, 10), None),
("Fire Control Array", int2(3, 6), Clockwise));
stage.Player(shooter, float2(0, 0), facing: float2(0, 1));
stage.Place(stage.Bare("Longinus"), Target);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74c554ab5a6a4ac5ad0334a29135dc7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: