AI pilots vent on a Track paint past half and overdrive to close (consumable-ai r3)
Re-land on master of the h1 cut with the s1 fixes: the vent rule reads one Track paint in the ship's own IncomingPaints, TryActivateConsumable refuses on an inactive ship, the AI holds while a consumable of the kind is active, and the top of the lock strength range is pinned. Not yet built or run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
533b301e49
commit
fcf1b46880
4 changed files with 387 additions and 1 deletions
|
|
@ -10,6 +10,12 @@ using float2x2 = CultMath.float2x2;
|
|||
public class CombatState : BaseState
|
||||
{
|
||||
private const int DPS_SAMPLE_COUNT = 32;
|
||||
// The Strength of one Track paint in this ship's own IncomingPaints: a fire-control emitter tracking this ship
|
||||
// that hard (rulings lock-warning-strength, sensor-stat-set item 4, launcher-lock-solution-quality).
|
||||
private const float LockAlarm = .5f;
|
||||
// Overdrive only to close a target farther than this many optimum ranges, while heading within this many degrees of it.
|
||||
private const float OverdriveRangeFactor = 2f;
|
||||
private const float OverdriveArcDegrees = 15f;
|
||||
private float _optimumRange;
|
||||
private readonly List<(int index, float dps)> _availableGroups = new List<(int index, float dps)>();
|
||||
private readonly List<LockWeapon> _availableLockingWeapons = new List<LockWeapon>();
|
||||
|
|
@ -78,6 +84,8 @@ public class CombatState : BaseState
|
|||
|
||||
foreach(var w in _availableLockingWeapons) w.Activate();
|
||||
|
||||
UseConsumables(toTarget, targetDistance);
|
||||
|
||||
var selectedGroup = -1;
|
||||
var maxDps = Single.MinValue;
|
||||
foreach (var group in _availableGroups)
|
||||
|
|
@ -132,6 +140,27 @@ public class CombatState : BaseState
|
|||
// Fire charged guns!
|
||||
}
|
||||
|
||||
// The AI plays the player's rule on the player's information: vent when one Track paint on this ship passes half,
|
||||
// otherwise overdrive to close a distant target ahead. It reads only this ship's own IncomingPaints. Both go
|
||||
// through TryActivateConsumable, and a ship carrying neither does nothing.
|
||||
private void UseConsumables(float3 toTarget, float targetDistance)
|
||||
{
|
||||
var ship = _agent.Ship;
|
||||
if (ship.IncomingPaints.Any(p => p.Mode == PaintMode.Track && p.Strength > LockAlarm))
|
||||
Use(b => b is VapourDumpData);
|
||||
else if (targetDistance > OverdriveRangeFactor * _optimumRange &&
|
||||
dot(normalize(ship.Direction), normalize(toTarget.xz)) > cos(radians(OverdriveArcDegrees)))
|
||||
Use(b => b is ThrottleLockData);
|
||||
}
|
||||
|
||||
// One of a kind at a time: a Stackable design would otherwise be drained once per tick.
|
||||
private void Use(Predicate<BehaviorData> kind)
|
||||
{
|
||||
if (_agent.Ship.HasActiveConsumable(kind)) return;
|
||||
var consumable = _agent.Ship.FirstCarriedConsumable(kind);
|
||||
if (consumable != null) _agent.Ship.TryActivateConsumable(consumable);
|
||||
}
|
||||
|
||||
private void SampleDps()
|
||||
{
|
||||
var minRange = Single.MaxValue;
|
||||
|
|
|
|||
|
|
@ -1350,8 +1350,20 @@ public abstract class Entity
|
|||
return data.Stackable || FindActiveConsumable(data) == null;
|
||||
}
|
||||
|
||||
// The first consumable design in cargo with a behaviour of the asked kind, or null. Callers ask by kind, never
|
||||
// by name: a design's name is a label and its behaviours are what it does.
|
||||
public ConsumableItemData FirstCarriedConsumable(Predicate<BehaviorData> kind) =>
|
||||
CargoBays.SelectMany(bay => bay.Cargo.Keys).OfType<ConsumableItem>()
|
||||
.Select(item => ItemManager.GetData(item) as ConsumableItemData)
|
||||
.FirstOrDefault(data => data != null && data.Behaviors.Any(b => kind(b)));
|
||||
|
||||
public bool HasActiveConsumable(Predicate<BehaviorData> kind) =>
|
||||
_activeConsumables.Any(e => e.Data.Behaviors.Any(b => kind(b)));
|
||||
|
||||
public bool TryActivateConsumable(ConsumableItemData data)
|
||||
{
|
||||
// Death and docking Remove and Deactivate the ship while its agent keeps ticking.
|
||||
if (!_active) return false;
|
||||
if (!CanActivateConsumable(data)) return false;
|
||||
|
||||
var key = ItemManager.ItemData.RefOf<ItemData>(data).Key;
|
||||
|
|
|
|||
Loading…
Reference in a new issue