public static void ChooseBestWeaponForTarget(AbstractActor unit, ICombatant target, bool isStationary) { List <Weapon> ammoWeapons = new List <Weapon>(); foreach (Weapon weapon in unit.Weapons) { if (CustomAmmoCategories.isWeaponHasDiffirentAmmo(weapon) == true) { CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " has ammo to choose\n"); ammoWeapons.Add(weapon); } } if (ammoWeapons.Count == 0) { CustomAmmoCategoriesLog.Log.LogWrite(" None choosable ammo\n"); return; } ; if (target is Mech) { CustomAmmoCategoriesLog.Log.LogWrite(" Target is mech\n"); Mech targetMech = (target as Mech); List <Weapon> ammoHeatWeapons = new List <Weapon>(); foreach (Weapon weapon in ammoWeapons) { if (CustomAmmoCategories.isWeaponHasHeatAmmo(weapon) == true) { CustomAmmoCategories.switchToMostHeatAmmo(weapon); CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " has hit ammo\n"); ammoHeatWeapons.Add(weapon); } } float expectedHeat = CustomAmmoCategories.calcHeatCoeff(unit, target); CustomAmmoCategoriesLog.Log.LogWrite(" Expected heat " + expectedHeat + "\n"); if ((targetMech.CurrentHeat + expectedHeat) > targetMech.OverheatLevel) { foreach (Weapon weapon in ammoHeatWeapons) { CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " - ammo choosed\n"); ammoWeapons.Remove(weapon); } } List <int> hitLocations = targetMech.GetPossibleHitLocations(unit); List <Weapon> ammoClusterWeapon = new List <Weapon>(); foreach (Weapon weapon in ammoWeapons) { if (CustomAmmoCategories.isWeaponHasClusterAmmo(weapon)) { CustomAmmoCategories.switchToMostClusterAmmo(weapon); CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " has cluster ammo\n"); ammoClusterWeapon.Add(weapon); } } foreach (Weapon weapon in ammoClusterWeapon) { float toHit = 0f; if (weapon.parent.HasLOFToTargetUnit(target, weapon.MaxRange, CustomAmmoCategories.getIndirectFireCapable(weapon))) { toHit = weapon.GetToHitFromPosition(target, 1, unit.CurrentPosition, target.CurrentPosition, true, targetMech.IsEvasive, false); } if (toHit < 0.4f) { CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " cluster toHit is too low " + toHit + "\n"); continue; } if (CustomAmmoCategories.hasHittableLocations(weapon, hitLocations, targetMech) == true) { CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " can crit one of locations\n"); ammoWeapons.Remove(weapon); } } } AbstractActor targetActor = (target as AbstractActor); foreach (Weapon weapon in ammoWeapons) { List <string> avaibleAmmo = CustomAmmoCategories.getAvaibleEffectiveAmmo(weapon); if (avaibleAmmo.Count == 0) { continue; } ; CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " choose ammo default algorithm\n"); string bestAmmo = ""; float expectedDamage = 0; foreach (string ammoId in avaibleAmmo) { CustomAmmoCategories.SetWeaponAmmo(weapon, ammoId); float toHit = 0f; if (unit.HasLOFToTargetUnit(target, weapon.MaxRange, CustomAmmoCategories.getIndirectFireCapable(weapon))) { toHit = weapon.GetToHitFromPosition(target, 1, unit.CurrentPosition, target.CurrentPosition, true, (targetActor != null) ? targetActor.IsEvasive : false, false); } float nonClusterCoeff = 1f; int numberOfShots = weapon.ShotsWhenFired * weapon.ProjectilesPerShot; if ((toHit > 0.6f) && (numberOfShots == 1)) { nonClusterCoeff = 1.2f; } float tempExpectedDamage = numberOfShots * weapon.DamagePerShot * toHit * nonClusterCoeff; CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " toHit " + toHit + " expectedDamage:" + tempExpectedDamage + "\n"); if (tempExpectedDamage > expectedDamage) { expectedDamage = tempExpectedDamage; bestAmmo = ammoId; } } if (string.IsNullOrEmpty(bestAmmo) == false) { CustomAmmoCategories.SetWeaponAmmo(weapon, bestAmmo); CustomAmmoCategoriesLog.Log.LogWrite(" " + weapon.UIName + " best ammo choosed\n"); } } }