public CandidateWeapons(AbstractActor attacker, ICombatant target) { Mod.Log.Debug?.Write($"Calculating candidate weapons"); for (int i = 0; i < attacker.Weapons.Count; i++) { Weapon weapon = attacker.Weapons[i]; CondensedWeapon cWeapon = new CondensedWeapon(weapon); if (cWeapon.First.CanFire) { Mod.Log.Debug?.Write($" -- '{cWeapon.First.defId}' included"); string cWepKey = cWeapon.First.weaponDef.Description.Id; if (condensed.ContainsKey(cWepKey)) { condensed[cWepKey].AddWeapon(weapon); } else { condensed[cWepKey] = cWeapon; } } else { Mod.Log.Debug?.Write($" -- '{cWeapon.First.defId}' excluded (disabled or out of ammo)"); } } Mod.Log.Debug?.Write(" -- DONE"); // TODO: Can fire only evaluates ammo once... check for enough ammo for all shots? float distance = (target.CurrentPosition - attacker.CurrentPosition).magnitude; Mod.Log.Debug?.Write($" Checking range {distance} and LOF from attacker: ({attacker.CurrentPosition}) to " + $"target: ({target.CurrentPosition})"); foreach (KeyValuePair <string, CondensedWeapon> kvp in condensed) { CondensedWeapon cWeapon = kvp.Value; // Evaluate being able to hit the target bool willFireAtTarget = cWeapon.First.WillFireAtTargetFromPosition(target, attacker.CurrentPosition, attacker.CurrentRotation); bool withinRange = distance <= cWeapon.First.MaxRange; if (willFireAtTarget && withinRange) { Mod.Log.Debug?.Write($" ({cWeapon.First.defId}) has LOF and is within range, adding "); RangedWeapons.Add(cWeapon); } else { Mod.Log.Debug?.Write($" ({cWeapon.First.defId}) is out of range (MaxRange: {cWeapon.First.MaxRange} vs {distance}) " + $"or has no LOF, skipping."); } if (cWeapon.First.WeaponCategoryValue.IsSupport) { Mod.Log.Debug?.Write($" ({cWeapon.First.defId}) is anti-personnel, adding to melee and DFA sets."); MeleeWeapons.Add(cWeapon); DFAWeapons.Add(cWeapon); } } }
// === CLONE METHODS BELOW == // CLONE OF HBS CODE - LIKELY BRITTLE! public static List <List <CondensedWeapon> > MakeWeaponSets(List <CondensedWeapon> potentialWeapons) { List <List <CondensedWeapon> > list = new List <List <CondensedWeapon> >(); if (potentialWeapons.Count > 0) { CondensedWeapon item = potentialWeapons[0]; List <CondensedWeapon> range = potentialWeapons.GetRange(1, potentialWeapons.Count - 1); List <List <CondensedWeapon> > list2 = MakeWeaponSets(range); for (int i = 0; i < list2.Count; i++) { List <CondensedWeapon> list3 = list2[i]; list.Add(list3); list.Add(new List <CondensedWeapon>(list3) { item }); } } else { List <CondensedWeapon> item2 = new List <CondensedWeapon>(); list.Add(item2); } return(list); }
public static int HeatForAttack(List <CondensedWeapon> weaponList) { int num = 0; for (int i = 0; i < weaponList.Count; i++) { CondensedWeapon cWeapon = weaponList[i]; num += ((int)cWeapon.First.HeatGenerated * cWeapon.weaponsCondensed); } return(num); }
public static float LowestHitChance(List <CondensedWeapon> weaponList, ICombatant target, Vector3 attackPosition, Vector3 targetPosition, bool targetIsEvasive) { float num = float.MaxValue; for (int i = 0; i < weaponList.Count; i++) { CondensedWeapon cWeapon = weaponList[i]; float toHitFromPosition = cWeapon.First.GetToHitFromPosition(target, 1, attackPosition, targetPosition, true, targetIsEvasive, false); num = Mathf.Min(num, toHitFromPosition); } return(num); }
// CLONE OF HBS CODE - LIKELY BRITTLE! public static List <List <CondensedWeapon> > MakeWeaponSetsForEvasive(List <CondensedWeapon> potentialWeapons, float toHitFrac, ICombatant target, Vector3 shooterPosition) { List <CondensedWeapon> likelyToHitWeapons = new List <CondensedWeapon>(); List <CondensedWeapon> unlikelyNonAmmoWeapons = new List <CondensedWeapon>(); List <CondensedWeapon> unlikelyAmmoWeapons = new List <CondensedWeapon>(); // Separate weapons into likely to hit, and unlikely to hit. Add only a single unlikely to hit weapon to the sets to be created. // TODO: Make this multi-step marginal... don't fire 9% weapons, but do fire 30%? for (int i = 0; i < potentialWeapons.Count; i++) { CondensedWeapon weapon = potentialWeapons[i]; if (weapon.First.CanFire) { float toHitFromPosition = weapon.First.GetToHitFromPosition(target, 1, shooterPosition, target.CurrentPosition, true, true, false); if (toHitFromPosition < toHitFrac) { if (weapon.First.AmmoCategoryValue.Is_NotSet) { unlikelyNonAmmoWeapons.Add(weapon); } else { unlikelyAmmoWeapons.Add(weapon); } } else { likelyToHitWeapons.Add(weapon); } } } float unlikelyWeaponChanceToHit = float.MinValue; CondensedWeapon weapon2 = null; for (int j = 0; j < unlikelyNonAmmoWeapons.Count; j++) { CondensedWeapon nonAmmoWeapon = unlikelyNonAmmoWeapons[j]; float toHitFromPosition2 = nonAmmoWeapon.First.GetToHitFromPosition(target, 1, shooterPosition, target.CurrentPosition, true, true, false); float weaponChanceToHit = toHitFromPosition2 * (float)nonAmmoWeapon.First.ShotsWhenFired * nonAmmoWeapon.First.DamagePerShot; if (weaponChanceToHit > unlikelyWeaponChanceToHit) { unlikelyWeaponChanceToHit = weaponChanceToHit; weapon2 = nonAmmoWeapon; } } if (weapon2 == null) { for (int k = 0; k < unlikelyAmmoWeapons.Count; k++) { CondensedWeapon weapon4 = unlikelyAmmoWeapons[k]; float toHitFromPosition3 = weapon4.First.GetToHitFromPosition(target, 1, shooterPosition, target.CurrentPosition, true, true, false); float weaponChanceToHit = toHitFromPosition3 * (float)weapon4.First.ShotsWhenFired * weapon4.First.DamagePerShot; if (weaponChanceToHit > unlikelyWeaponChanceToHit) { unlikelyWeaponChanceToHit = weaponChanceToHit; weapon2 = weapon4; } } } if (weapon2 != null) { likelyToHitWeapons.Add(weapon2); } return(MakeWeaponSets(likelyToHitWeapons)); }