public static void Postfix(AttackDirector __instance, MessageCenterMessage message)
 {
     CustomAmmoCategoriesLog.Log.LogWrite($"Try jamm weapon\n");
     while (JammingEnabler.jammQueue.Count > 0)
     {
         AbstractActor actor = JammingEnabler.jammQueue.Dequeue();
         CustomAmmoCategoriesLog.Log.LogWrite($"Try jamm weapon of " + actor.DisplayName + "\n");
         foreach (Weapon weapon in actor.Weapons)
         {
             CustomAmmoCategoriesLog.Log.LogWrite($"  weapon " + weapon.UIName + " rounds since last fire " + weapon.roundsSinceLastFire + "\n");
             if (weapon.roundsSinceLastFire > 0)
             {
                 continue;
             }
             float flatJammingChance = CustomAmmoCategories.getWeaponFlatJammingChance(weapon);
             CustomAmmoCategoriesLog.Log.LogWrite($"  flatJammingChance " + flatJammingChance + "\n");
             if (flatJammingChance > CustomAmmoCategories.Epsilon)
             {
                 CustomAmmoCategoriesLog.Log.LogWrite($"  Try jamm weapon " + weapon.UIName + "\n");
                 float Roll = Random.Range(0.0f, 1.0f);
                 CustomAmmoCategoriesLog.Log.LogWrite($" Jamming chance " + flatJammingChance + " roll " + Roll + "\n");
                 if (Roll < flatJammingChance)
                 {
                     CustomAmmoCategoriesLog.Log.LogWrite($" Jammed!\n");
                     CustomAmmoCategories.AddJam(actor, weapon);
                 }
             }
             if (CustomAmmoCategories.getWeaponCooldown(weapon) > 0)
             {
                 CustomAmmoCategories.AddCooldown(actor, weapon);
             }
         }
     }
 }
 public static void AddCooldown(AbstractActor actor, Weapon weapon)
 {
     if (CustomAmmoCategories.checkExistance(weapon.StatCollection, CustomAmmoCategories.CooldownWeaponStatisticName) == false)
     {
         weapon.StatCollection.AddStatistic <int>(CustomAmmoCategories.CooldownWeaponStatisticName, 0);
     }
     if (CustomAmmoCategories.getWeaponCooldown(weapon) > 0)
     {
         weapon.StatCollection.Set <int>(CustomAmmoCategories.CooldownWeaponStatisticName, CustomAmmoCategories.getWeaponCooldown(weapon));
         weapon.StatCollection.Set <bool>(CustomAmmoCategories.TemporarilyDisabledStatisticName, true);
         actor.Combat.MessageCenter.PublishMessage(
             new AddSequenceToStackMessage(
                 new ShowActorInfoSequence(actor, $"{weapon.Name} Cooldown!", FloatieMessage.MessageNature.Debuff,
                                           true)));
     }
 }
        public static void fillWeaponPredictRecord(ref DamagePredictRecord record, AbstractActor unit, ICombatant target, Weapon weapon, ref List <int> hitLocations, ref float AverageArmor)
        {
            CustomAmmoCategoriesLog.Log.LogWrite("fillWeaponPredictRecord " + unit.DisplayName + " target " + target.DisplayName + " weapon " + weapon.defId + "\n");
            CustomAmmoCategories.applyWeaponAmmoMode(weapon, record.Id.modeId, record.Id.ammoId);
            AbstractActor targetActor = target as AbstractActor;

            if (hitLocations == null)
            {
                hitLocations = target.GetPossibleHitLocations(unit);
                foreach (int hitLocation in hitLocations)
                {
                    CustomAmmoCategoriesLog.Log.LogWrite("Hit Location " + hitLocation + "\n");
                }
            }
            if (float.IsNaN(AverageArmor))
            {
                AverageArmor = CustomAmmoCategories.getTargetAvarageArmor(hitLocations, target);
            }
            float toHit = 0;

            if (weapon.WillFireAtTargetFromPosition(target, unit.CurrentPosition) == true)
            {
                toHit = weapon.GetToHitFromPosition(target, 1, unit.CurrentPosition, target.CurrentPosition, true, (targetActor != null) ? targetActor.IsEvasive : false, false);
            }
            if (toHit < Epsilon)
            {
                record.HeatDamageCoeff = 0f; record.NormDamageCoeff = 0f; record.PredictHeatDamage = 0f;
            }
            ;
            float coolDownCoeff    = 1.0f / (1.0f + CustomAmmoCategories.getWeaponCooldown(weapon));
            float jammCoeff        = 1.0f - CustomAmmoCategories.getWeaponFlatJammingChance(weapon);
            float damageJammCoeff  = CustomAmmoCategories.getWeaponDamageOnJamming(weapon) ? 0.5f : 1.0f;
            float damageShotsCount = (float)weapon.ShotsWhenFired;
            float damagePerShot    = weapon.DamagePerShot;
            float heatPerShot      = weapon.HeatDamagePerShot;

            if (weapon.componentDef.ComponentTags.Contains("wr-clustered_shots") || (CustomAmmoCategories.getWeaponDisabledClustering(weapon) == false))
            {
                damageShotsCount *= (float)weapon.ProjectilesPerShot;
            }
            float piercedLocationsCount = (float)CustomAmmoCategories.getWeaponPierceLocations(hitLocations, target, damagePerShot);
            float hitLocationsCount     = (hitLocations.Count > 0) ? (float)hitLocations.Count : 1.0f;
            float clusterCoeff          = 1.0f + ((piercedLocationsCount / hitLocationsCount) * damageShotsCount) * CustomAmmoCategories.Settings.ClusterAIMult;
            float pierceCoeff           = 1.0f;

            if (AverageArmor > damagePerShot)
            {
                pierceCoeff += (damagePerShot / AverageArmor) * CustomAmmoCategories.Settings.PenetrateAIMult;
            }
            record.NormDamageCoeff   = damagePerShot * damageShotsCount * toHit * coolDownCoeff * jammCoeff * damageJammCoeff * clusterCoeff * pierceCoeff;
            record.HeatDamageCoeff   = heatPerShot * damageShotsCount * toHit * jammCoeff * damageJammCoeff;
            record.PredictHeatDamage = heatPerShot * damageShotsCount * toHit;
            CustomAmmoCategoriesLog.Log.LogWrite(" toHit = " + toHit + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" coolDownCoeff = " + coolDownCoeff + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" jammCoeff = " + jammCoeff + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" damageJammCoeff = " + damageJammCoeff + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" damageShotsCount = " + damageShotsCount + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" damagePerShot = " + damagePerShot + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" heatPerShot = " + heatPerShot + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" piercedLocationsCount = " + piercedLocationsCount + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" hitLocationsCount = " + hitLocationsCount + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" AverageArmor = " + AverageArmor + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" clusterCoeff = " + clusterCoeff + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" pierceCoeff = " + pierceCoeff + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" NormDamageCoeff = " + record.NormDamageCoeff + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite(" HeatDamageCoeff = " + record.HeatDamageCoeff + "\n");
        }