diff --git a/Assets/Scripts/ServerShared/Scenarios/Crossing.cs b/Assets/Scripts/ServerShared/Scenarios/Crossing.cs index b0d593704..880f492df 100644 --- a/Assets/Scripts/ServerShared/Scenarios/Crossing.cs +++ b/Assets/Scripts/ServerShared/Scenarios/Crossing.cs @@ -5,19 +5,22 @@ public sealed class Crossing : Scenario { public override string Name => "Crossing"; public override string Brief => "A Lightning Projector at the starboard gun and a Cell Blaster at the port gun, a fast Djinni crossing close ahead and an " + - "unpiloted one waiting at range. The Djinni starts to port moving across the bow; the arena's gravity bends its run. Make the pass coasting: give no throttle until the Djinni has crossed the bow, then fly freely (thrusting from the start carries you past it). Verify: as the Djinni crosses close, FastBlast lands some and projector " + + "unpiloted one waiting at range. The Djinni starts to port moving across the bow, and its pilot brakes it as it closes. Make the pass coasting: give no throttle until the Djinni has crossed the bow, then fly freely (thrusting from the start carries you past it). Verify: as the Djinni crosses close, FastBlast lands some and projector " + "almost none; against the Djinni at range both land. Fly it again without the Fire Control Array: " + "with it the small gun lands more."; public override uint Seed => 112; public override bool Ambient => false; - // Where the Djinni sit: the player is at the origin facing +z. The crosser starts ahead and to port, facing across - // the bow and already moving at the Djinni's 50 m/s cap, so its run sweeps across the bow within seconds (the arena - // pulls the player to port, which brings the two together). The waiting Djinni sits inside the Lightning Projector's arc at 80% of - // its Range. - public static readonly CultMath.float2 CrosserAt = float2(-150, 200), CrosserFacing = float2(1, 0), CrosserVelocity = float2(50, 0); + // Where the Djinni sit: the player is at Origin facing +z. Origin is 250 m or more from every body, where the zone's + // pull is weakest (about 1.4 u/s^2; the sum of the wells never drops to nothing, and at the old origin the player sat on the star). + // The crosser starts ahead and to port, facing across the bow and already moving at the Djinni's 50 m/s cap; its pilot + // brakes it as it closes, so it only just reaches the bow line, which fixes how far to port it starts (sweeping the starting + // x from -95 to -97.5 moves the pass from 3.0 s to 3.5 s; at -98 it never crosses). The waiting Djinni sits inside the Lightning + // Projector's arc at 80% of its Range. + public static readonly CultMath.float2 Origin = float2(724, 124); + public static readonly CultMath.float2 CrosserAt = Origin + float2(-96.5f, 70), CrosserFacing = float2(1, 0), CrosserVelocity = float2(50, 0); public const float ProjectorRange = 1216f; // the Lightning Projector's Range in metres, 1216.4 as the fit stands settled at rest - public static readonly CultMath.float2 Waiting = float2(0, ProjectorRange * .8f); + public static readonly CultMath.float2 Waiting = Origin + float2(0, ProjectorRange * .8f); public override Galaxy Generate(GalaxyStage stage) => stage.Prelude(DemoTerminus.Cast); @@ -39,7 +42,7 @@ public sealed class Crossing : Scenario ("Compact Sensor", int2(3, 10), None), ("Fire Control Array", int2(1, 6), Clockwise)); - stage.Player(fighter, float2(0, 0), facing: float2(0, 1)); + stage.Player(fighter, Origin, facing: float2(0, 1)); stage.Place(stage.Generated("Djinni"), CrosserAt, facing: CrosserFacing, stance: ScenarioStance.Hostile, piloted: true, velocity: CrosserVelocity); stage.Place(stage.Bare("Djinni"), Waiting); } diff --git a/Assets/Scripts/ServerShared/Scenarios/LockOn.cs b/Assets/Scripts/ServerShared/Scenarios/LockOn.cs index fa669e253..87e5de829 100644 --- a/Assets/Scripts/ServerShared/Scenarios/LockOn.cs +++ b/Assets/Scripts/ServerShared/Scenarios/LockOn.cs @@ -10,11 +10,13 @@ public sealed class LockOn : Scenario public override uint Seed => 113; public override bool Ambient => false; - // The hostile starts about 4000 m off, to the side of the player's axis, facing the player. At that range its passive - // sensors hold no track of the player (the test asks the sim's own PassiveInfo against the detection threshold); the - // player sees the hostile a little sooner, at about tick 20. The hostile closes, sees the player some eight seconds in, - // and locks two ticks later. At Duel's 900 m (and at 600 m) it sees and locks within a second. - public static readonly CultMath.float2 HostileAt = float2(1500, 3700); + // The hostile starts about 4000 m off, ahead and to port of the player, facing the player. At that range its passive + // sensors hold no track of the player (the test asks the sim's own PassiveInfo against the detection threshold). The + // hostile closes, sees the player some fourteen seconds in and locks. The zone's pull bends the hostile's run and moves the + // player, and the warning must still point at where the hostile was staged to within 5 degrees at the lock: this side keeps + // the bend under one degree (on the far side it is more than seven). At Duel's 900 m (and at 600 m) it sees and locks + // within a second. + public static readonly CultMath.float2 HostileAt = float2(-2000, 3450); public override Galaxy Generate(GalaxyStage stage) => stage.Prelude(DemoTerminus.Cast); diff --git a/tests/Aetheria.Shared.Tests/CrossingScenarioTests.cs b/tests/Aetheria.Shared.Tests/CrossingScenarioTests.cs index 8b5dfe019..955c331bd 100644 --- a/tests/Aetheria.Shared.Tests/CrossingScenarioTests.cs +++ b/tests/Aetheria.Shared.Tests/CrossingScenarioTests.cs @@ -84,7 +84,7 @@ public sealed partial class RunStartTests } } Assert.True(swept, $"the crosser's bearing never swept across the bow within {CrossingSeconds} s"); - // At seed 112 with no input the pass is at 3.6 s and 45 m; a seed or staging change that loses it moves these. + // At seed 112 with no input the pass is at 3.2 s and 40 m (the pilot brakes the crosser as it closes, so the pass is sensitive to where it starts: Crossing.CrosserAt); a seed, field or staging change that loses it moves these. Assert.InRange(crossedAt, 3.0f, 4.2f); Assert.InRange(crossedMetres, 30f, 60f); }