Require a targeting system on every armed loadout; AI aims through reveal
LoadoutGenerator.FillInterior equips a targeting-system product, required: true, on any entity EquipHardpoints already gave a weapon -- Q4's "not an upgrade" ruling made structural. CombatState now selects the target's most dangerous revealed weapon item each tick through the same IsRevealed predicate and TrySelectTargetItem writer the player path uses, instead of never touching TargetItem at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c4a57a8df0
commit
52a18efcdc
2 changed files with 39 additions and 0 deletions
|
|
@ -33,6 +33,25 @@ public class CombatState : BaseState
|
|||
|
||||
var toTarget = target.Position - _agent.Ship.Position;
|
||||
var targetDistance = length(toTarget);
|
||||
|
||||
// Cut 2 (docs/fire-control-cut.md): aim at whichever revealed weapon on the target hits hardest at
|
||||
// this range, or clear the aim point when nothing qualifies -- the same predicate
|
||||
// (FireControl.IsRevealed) and the same writer (TrySelectTargetItem) the player path uses.
|
||||
EquippedItem bestTargetItem = null;
|
||||
var bestTargetDps = float.MinValue;
|
||||
foreach (var targetItem in target.Equipment)
|
||||
{
|
||||
if (!(targetItem.Behaviors.FirstOrDefault(b => b is Weapon) is Weapon targetWeapon)) continue;
|
||||
if (!FireControl.IsRevealed(_agent.Ship, targetItem)) continue;
|
||||
var dps = targetWeapon.RangeDamagePerSecond(targetDistance);
|
||||
if (dps > bestTargetDps)
|
||||
{
|
||||
bestTargetDps = dps;
|
||||
bestTargetItem = targetItem;
|
||||
}
|
||||
}
|
||||
_agent.Ship.TrySelectTargetItem(bestTargetItem);
|
||||
|
||||
for (var i = 0; i < _agent.Ship.WeaponGroups.Length; i++)
|
||||
{
|
||||
var group = _agent.Ship.WeaponGroups[i];
|
||||
|
|
|
|||
|
|
@ -258,6 +258,26 @@ public class LoadoutGenerator
|
|||
capacitor.Rotation = capacitorRotation;
|
||||
if (!entity.TryEquip(capacitor, capacitorPosition))
|
||||
throw new InvalidLoadoutException("Failed to equip selected capacitor!");
|
||||
|
||||
// Cut 2 (docs/fire-control-cut.md, Q4): required equipment for anything that can fire -- unaided
|
||||
// fire is a last resort, not an alternative loadout choice. EquipHardpoints runs before FillInterior
|
||||
// (OutfitEntity), so entity.Weapons is already populated here. Zenith and anything else with no
|
||||
// weapon hardpoints gets none.
|
||||
if (entity.Weapons.Any())
|
||||
{
|
||||
emptyShape = entity.UnoccupiedSpace;
|
||||
|
||||
var (targetingProduct, targetingData) = RandomProduct<GearData>(2, item =>
|
||||
item.Behaviors.Any(b => b is TargetingSystemData) &&
|
||||
item.Shape.FitsWithin(emptyShape, out _, out _), required: true);
|
||||
if (targetingData == null) throw new InvalidLoadoutException("No compatible targeting system found for entity!");
|
||||
|
||||
targetingData.Shape.FitsWithin(emptyShape, out var targetingRotation, out var targetingPosition);
|
||||
var targetingSystem = ItemManager.CreateInstance(targetingProduct) as EquippableItem;
|
||||
targetingSystem.Rotation = targetingRotation;
|
||||
if (!entity.TryEquip(targetingSystem, targetingPosition))
|
||||
throw new InvalidLoadoutException("Failed to equip selected targeting system!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue