Note: Projectiles that can track their target need minor additional changes, but for InstantHit (which already implemented support for this) and unguided projectiles (Bullet, GravityBomb) this commit is already sufficient.
Rather than simply taking the first valid armament, regardless of available ammo and regardless of which valid armament has the highest range, the attack cursor is now chosen a) by whether the armament has ammo and b) by which valid armament has the highest range.
This should prevent attacking helicopters (or other actors) staying at the range to target of a weapon that is out of ammo and needs manual reloading at a RearmBuilding or via upgrades.
This adresses the issue that actors would ignore the validity of weapons when deciding the attack distance versus a target. This could result in actors staying out of range of a weapon valid versus target if they carried a weapon with higher range but invalid versus target.
Most auto target scans will be conducted among groups of allied units unable to target each other because they are allied and their weapons only target enemies. Since they cannot target each other, the scan will be repeated constantly. Realising this, we can significantly reduce the performance impact of auto target scanning by bailing early in this scenario to avoid carrying out expensive targeting checks on friendly units which we know will fail anyway.
Move self.IsDisabled right after IsInWorld and IsTraitDisabled checks.
This should skip/avoid a lot of the following checks when actors are disabled by low power, EMP or similar, potentially saving some performance when there are many disabled actors with attack trait.
Move IsValidFor before HasAnyValidWeapons because the latter is more
expensive.
Remove the unused onlyEnabled parameter to avoid it needlessly being captured in the closure, and simplify the logic.
Evaluate RequiresForceFire and Weapon.IsValidAgainst last in their respective logic chains as these are the most expensive operations and benefit from short-circuiting being able to skip their evaluation.
Enabled firing multiple armaments at a target simultaneously.
Each armament defines own cursor for targeting.
The force attack modifier influences armament choice for target.
Autotargeting modified to handle firing multiple armaments simultaneously.
As a consequence, healers (medics) no longer require separate Heal
activity and AttackMedic and AutoHeal traits.
If a class is caching the TraitsImplementing enumerable, instead cache the results of enumerating it to an array. The avoids having to enumerate the sequence each time it is needed.