Refine ship orders and viewer controls
This commit is contained in:
@@ -6,27 +6,12 @@ namespace SpaceGame.Api.Ships.AI;
|
||||
|
||||
public sealed partial class ShipAiService
|
||||
{
|
||||
private static ShipOrderRuntime? GetTopOrder(ShipRuntime ship) =>
|
||||
ship.OrderQueue
|
||||
.Where(order => order.Status is OrderStatus.Queued or OrderStatus.Active)
|
||||
.OrderByDescending(GetOrderSourcePriority)
|
||||
.ThenByDescending(order => order.Priority)
|
||||
.ThenBy(order => order.CreatedAtUtc)
|
||||
.FirstOrDefault();
|
||||
|
||||
private static int GetOrderSourcePriority(ShipOrderRuntime order) => order.SourceKind switch
|
||||
{
|
||||
ShipOrderSourceKind.Player => 300,
|
||||
ShipOrderSourceKind.Commander => 200,
|
||||
ShipOrderSourceKind.Behavior => 100,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
private void SyncBehaviorOrders(SimulationWorld world, ShipRuntime ship)
|
||||
{
|
||||
var desiredOrder = BuildManagedBehaviorOrder(world, ship);
|
||||
ship.OrderQueue.RemoveAll(order =>
|
||||
ship.OrderQueue.RemoveWhere(order =>
|
||||
order.SourceKind == ShipOrderSourceKind.Behavior
|
||||
&& order.Id.StartsWith("behavior-", StringComparison.Ordinal)
|
||||
&& (desiredOrder is null || !string.Equals(order.Id, desiredOrder.Id, StringComparison.Ordinal)));
|
||||
|
||||
if (desiredOrder is null)
|
||||
@@ -34,10 +19,10 @@ public sealed partial class ShipAiService
|
||||
return;
|
||||
}
|
||||
|
||||
var existing = ship.OrderQueue.FirstOrDefault(order => string.Equals(order.Id, desiredOrder.Id, StringComparison.Ordinal));
|
||||
var existing = ship.OrderQueue.FindById(desiredOrder.Id);
|
||||
if (existing is null)
|
||||
{
|
||||
ship.OrderQueue.Add(desiredOrder);
|
||||
ship.OrderQueue.AddOrReplaceManagedOrder(desiredOrder);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,8 +31,7 @@ public sealed partial class ShipAiService
|
||||
return;
|
||||
}
|
||||
|
||||
ship.OrderQueue.Remove(existing);
|
||||
ship.OrderQueue.Add(desiredOrder);
|
||||
ship.OrderQueue.AddOrReplaceManagedOrder(desiredOrder);
|
||||
}
|
||||
|
||||
private ShipOrderRuntime? BuildManagedBehaviorOrder(SimulationWorld world, ShipRuntime ship)
|
||||
@@ -76,7 +60,7 @@ public sealed partial class ShipAiService
|
||||
};
|
||||
}
|
||||
|
||||
if (string.Equals(behaviorKind, DockAndWait, StringComparison.Ordinal))
|
||||
if (string.Equals(behaviorKind, DockAtStation, StringComparison.Ordinal))
|
||||
{
|
||||
var station = ResolveStation(world, assignment?.TargetEntityId ?? ship.DefaultBehavior.TargetEntityId ?? ship.DefaultBehavior.HomeStationId);
|
||||
if (station is null)
|
||||
@@ -88,38 +72,36 @@ public sealed partial class ShipAiService
|
||||
ship.LastAccessFailureReason = null;
|
||||
return new ShipOrderRuntime
|
||||
{
|
||||
Id = $"behavior-{ship.Id}-dock-and-wait",
|
||||
Kind = ShipOrderKinds.DockAndWait,
|
||||
Id = $"behavior-{ship.Id}-dock-at-station",
|
||||
Kind = ShipOrderKinds.DockAtStation,
|
||||
SourceKind = ShipOrderSourceKind.Behavior,
|
||||
SourceId = behaviorKind,
|
||||
Priority = 0,
|
||||
InterruptCurrentPlan = false,
|
||||
Label = $"Dock and wait at {station.Label}",
|
||||
Label = $"Dock at {station.Label}",
|
||||
TargetEntityId = station.Id,
|
||||
TargetSystemId = station.SystemId,
|
||||
DestinationStationId = station.Id,
|
||||
WaitSeconds = MathF.Max(2f, ship.DefaultBehavior.WaitSeconds),
|
||||
Radius = ship.DefaultBehavior.Radius,
|
||||
MaxSystemRange = ship.DefaultBehavior.MaxSystemRange,
|
||||
KnownStationsOnly = ship.DefaultBehavior.KnownStationsOnly,
|
||||
};
|
||||
}
|
||||
|
||||
if (string.Equals(behaviorKind, FlyAndWait, StringComparison.Ordinal))
|
||||
if (string.Equals(behaviorKind, Move, StringComparison.Ordinal))
|
||||
{
|
||||
ship.LastAccessFailureReason = null;
|
||||
return new ShipOrderRuntime
|
||||
{
|
||||
Id = $"behavior-{ship.Id}-fly-and-wait",
|
||||
Kind = ShipOrderKinds.FlyAndWait,
|
||||
Id = $"behavior-{ship.Id}-move",
|
||||
Kind = ShipOrderKinds.Move,
|
||||
SourceKind = ShipOrderSourceKind.Behavior,
|
||||
SourceId = behaviorKind,
|
||||
Priority = 0,
|
||||
InterruptCurrentPlan = false,
|
||||
Label = "Fly and wait",
|
||||
Label = "Fly to position",
|
||||
TargetSystemId = systemId,
|
||||
TargetPosition = ship.DefaultBehavior.TargetPosition ?? ship.Position,
|
||||
WaitSeconds = MathF.Max(2f, ship.DefaultBehavior.WaitSeconds),
|
||||
Radius = ship.DefaultBehavior.Radius,
|
||||
MaxSystemRange = ship.DefaultBehavior.MaxSystemRange,
|
||||
KnownStationsOnly = ship.DefaultBehavior.KnownStationsOnly,
|
||||
@@ -306,13 +288,12 @@ public sealed partial class ShipAiService
|
||||
}
|
||||
|
||||
ship.LastAccessFailureReason = null;
|
||||
return CreateManagedFlyAndWaitOrder(
|
||||
return CreateManagedMoveOrder(
|
||||
ship,
|
||||
behaviorKind,
|
||||
"Protect position",
|
||||
targetSystemId,
|
||||
targetPosition,
|
||||
MathF.Max(2f, ship.DefaultBehavior.WaitSeconds),
|
||||
MathF.Max(6f, ship.DefaultBehavior.Radius));
|
||||
}
|
||||
|
||||
@@ -365,13 +346,12 @@ public sealed partial class ShipAiService
|
||||
}
|
||||
|
||||
ship.LastAccessFailureReason = null;
|
||||
return CreateManagedFlyAndWaitOrder(
|
||||
return CreateManagedMoveOrder(
|
||||
ship,
|
||||
behaviorKind,
|
||||
$"Guard {station.Label}",
|
||||
station.SystemId,
|
||||
GetFormationPosition(station.Position, ship.Id, MathF.Max(station.Radius + 18f, ship.DefaultBehavior.Radius)),
|
||||
MathF.Max(2f, ship.DefaultBehavior.WaitSeconds),
|
||||
MathF.Max(6f, ship.DefaultBehavior.Radius));
|
||||
}
|
||||
|
||||
@@ -410,7 +390,7 @@ public sealed partial class ShipAiService
|
||||
&& SelectKnownStationVisit(world, ship, homeStation) is { } visitStation)
|
||||
{
|
||||
ship.LastAccessFailureReason = null;
|
||||
return CreateManagedDockAndWaitOrder(ship, behaviorKind, visitStation, MathF.Max(2f, ship.DefaultBehavior.WaitSeconds), $"Revisit {visitStation.Label}");
|
||||
return CreateManagedDockAtStationOrder(ship, behaviorKind, visitStation, $"Revisit {visitStation.Label}");
|
||||
}
|
||||
|
||||
ship.LastAccessFailureReason = "no-trade-route";
|
||||
@@ -641,7 +621,7 @@ public sealed partial class ShipAiService
|
||||
}
|
||||
|
||||
ship.LastAccessFailureReason = null;
|
||||
return CreateManagedFlyAndWaitOrder(ship, sourceKind, "Patrol waypoint", targetSystemId, targetPosition, MathF.Max(2f, ship.DefaultBehavior.WaitSeconds), MathF.Max(6f, ship.DefaultBehavior.Radius), orderIdSuffix: "patrol-fly-and-wait");
|
||||
return CreateManagedMoveOrder(ship, sourceKind, "Patrol waypoint", targetSystemId, targetPosition, MathF.Max(6f, ship.DefaultBehavior.Radius), orderIdSuffix: "patrol-move");
|
||||
}
|
||||
|
||||
private static ShipOrderRuntime CreateManagedAttackOrder(
|
||||
@@ -687,11 +667,11 @@ public sealed partial class ShipAiService
|
||||
KnownStationsOnly = ship.DefaultBehavior.KnownStationsOnly,
|
||||
};
|
||||
|
||||
private static ShipOrderRuntime CreateManagedDockAndWaitOrder(ShipRuntime ship, string behaviorKind, StationRuntime station, float waitSeconds, string label) =>
|
||||
private static ShipOrderRuntime CreateManagedDockAtStationOrder(ShipRuntime ship, string behaviorKind, StationRuntime station, string label) =>
|
||||
new()
|
||||
{
|
||||
Id = $"behavior-{ship.Id}-{behaviorKind}-dock-and-wait",
|
||||
Kind = ShipOrderKinds.DockAndWait,
|
||||
Id = $"behavior-{ship.Id}-{behaviorKind}-dock-at-station",
|
||||
Kind = ShipOrderKinds.DockAtStation,
|
||||
SourceKind = ShipOrderSourceKind.Behavior,
|
||||
SourceId = behaviorKind,
|
||||
Priority = 0,
|
||||
@@ -700,25 +680,23 @@ public sealed partial class ShipAiService
|
||||
TargetEntityId = station.Id,
|
||||
TargetSystemId = station.SystemId,
|
||||
DestinationStationId = station.Id,
|
||||
WaitSeconds = waitSeconds,
|
||||
Radius = ship.DefaultBehavior.Radius,
|
||||
MaxSystemRange = ship.DefaultBehavior.MaxSystemRange,
|
||||
KnownStationsOnly = ship.DefaultBehavior.KnownStationsOnly,
|
||||
};
|
||||
|
||||
private static ShipOrderRuntime CreateManagedFlyAndWaitOrder(
|
||||
private static ShipOrderRuntime CreateManagedMoveOrder(
|
||||
ShipRuntime ship,
|
||||
string behaviorKind,
|
||||
string label,
|
||||
string targetSystemId,
|
||||
Vector3 targetPosition,
|
||||
float waitSeconds,
|
||||
float radius,
|
||||
string? orderIdSuffix = null) =>
|
||||
new()
|
||||
{
|
||||
Id = $"behavior-{ship.Id}-{orderIdSuffix ?? behaviorKind}",
|
||||
Kind = ShipOrderKinds.FlyAndWait,
|
||||
Kind = ShipOrderKinds.Move,
|
||||
SourceKind = ShipOrderSourceKind.Behavior,
|
||||
SourceId = behaviorKind,
|
||||
Priority = 0,
|
||||
@@ -726,7 +704,6 @@ public sealed partial class ShipAiService
|
||||
Label = label,
|
||||
TargetSystemId = targetSystemId,
|
||||
TargetPosition = targetPosition,
|
||||
WaitSeconds = waitSeconds,
|
||||
Radius = radius,
|
||||
MaxSystemRange = ship.DefaultBehavior.MaxSystemRange,
|
||||
KnownStationsOnly = ship.DefaultBehavior.KnownStationsOnly,
|
||||
|
||||
Reference in New Issue
Block a user