public static bool CheckForCrit(AIMCritInfo info, int hitLocation, bool logCrit) { try { if (info?.weapon == null) { return(true); } info.SetHitLocation(hitLocation); AbstractActor target = info.target; if (SkipCritingDeadMech && IsBeatingDeadMech(target)) { return(false); } float chance = info.GetCritChance(); for (int i = 1; chance > 0; i++) { float critRoll = Combat.NetworkRandom.Float(); // If use original code AttackDirector.GetRandomFromCache( info.hitInfo, 2 ), may run out of rolls if (DebugLog) { Verbo("Crit {3} roll {0} <= chance {1}? {2}", critRoll, chance, critRoll <= chance, i); } if (i == 1) { AttackLog.LogAIMCritRoll(critRoll); } if (critRoll > chance) { break; } float slotRoll = Combat.NetworkRandom.Float(); if (AttackLog.thisCritComp == null) { AttackLog.LogAIMSlotRoll(slotRoll); } MechComponent component = FindAndCritComponent(info, slotRoll); if (i > 1) { Verbo("Crit x{0} on location {1} of {2} by {3}. Roll {4} <= Chance {5}. Crit'ed {6}", i, component?.Location ?? hitLocation, info.target, info.weapon, critRoll, chance, component?.UIName.ToString() ?? "(None)"); } if (logCrit) { AttackLog.LogCritResult(target, info.weapon); logCrit = false; } if (!Settings.MultipleCrits) { break; } chance -= critRoll; } PostCheckForCrit(info, logCrit); } catch (Exception ex) { Error(ex); } return(false); }
private static void ConsolidateCrit(AIMCritInfo info) { try { damaged.Clear(); allowConsolidateOnce = true; damages = info.hitInfo.ConsolidateCriticalHitInfo(GetWeaponDamage(info)); damages.Remove(0); damages.Remove(65536); if (DebugLog) { Verbo("SplitCriticalHitInfo found {0} hit locations by {1} on {2}.", damages.Count, info.weapon, info.target); } foreach (var damage in damages) { info.SetHitLocation(damage.Key); if (!info.CanBeCrit()) { continue; } if (info.IsArmourBreached) { if (DebugLog) { Verbo("Struct damage {0} = {1}", damage.Key, damage.Value); } damaged.Add(damage.Key, damage.Value); continue; } if (!ThroughArmorCritEnabled) { continue; } if (DebugLog) { Verbo("Armour damage {0} = {1}", damage.Key, damage.Value); } if ((TAC_Threshold == 0 && TAC_ThresholdPerc == 0) || // No threshold /*const*/ (TAC_Threshold > 0 && damage.Value >= TAC_Threshold) || /*abs% */ (TAC_ThresholdPerc > 0 && damage.Value >= TAC_ThresholdPerc * info.maxArmour) || /*curr%*/ (TAC_ThresholdPerc < 0 && damage.Value >= TAC_ThresholdPerc * (info.currentArmour + damage.Value))) { damaged.Add(damage.Key, damage.Value); } else if (DebugLog) { Verbo("Damage not reach threshold {0} / {1}% (Armour {2}/{3})", TAC_Threshold, TAC_ThresholdPerc * 100, info.currentArmour, info.maxArmour); } } damages.Clear(); } catch (Exception ex) { Error(ex); } }