protected override bool TryCastShot()
        {
            //    Log.Message("Try Cast Shot Called");
            //Log.Message("Cast");
            bool          GetsHot                    = this.UseAbilityProps.GetsHot;
            bool          Jams                       = this.UseAbilityProps.Jams;
            bool          GetsHotCrit                = this.UseAbilityProps.GetsHotCrit;
            float         GetsHotCritChance          = this.UseAbilityProps.GetsHotCritChance;
            bool          GetsHotCritExplosion       = this.UseAbilityProps.GetsHotCritExplosion;
            float         GetsHotCritExplosionChance = this.UseAbilityProps.GetsHotCritExplosionChance;
            bool          canDamageWeapon            = this.UseAbilityProps.HotDamageWeapon || this.UseAbilityProps.JamsDamageWeapon;
            float         extraWeaponDamage          = (Jams && this.UseAbilityProps.JamsDamageWeapon) ? this.UseAbilityProps.JamDamage : (GetsHot && this.UseAbilityProps.HotDamageWeapon) ? this.UseAbilityProps.HotDamage : 0f;
            bool          TwinLinked                 = this.UseAbilityProps.TwinLinked;
            bool          Multishot                  = this.UseAbilityProps.Multishot;
            int           ScattershotCount           = this.UseAbilityProps.ScattershotCount;
            bool          UserEffect                 = this.UseAbilityProps.EffectsUser;
            HediffDef     UserHediff                 = this.UseAbilityProps.UserEffect;
            float         AddHediffChance            = this.UseAbilityProps.EffectsUserChance;
            List <string> Immunitylist               = this.UseAbilityProps.UserEffectImmuneList;
            var           result                     = false;

            TargetsAoE.Clear();
            UpdateTargets();
            var burstShots = ShotsPerBurst;

            if (UseAbilityProps.AbilityTargetCategory != AbilityTargetCategory.TargetAoE && TargetsAoE.Count > 1)
            {
                TargetsAoE.RemoveRange(0, TargetsAoE.Count - 1);
            }
            if (UseAbilityProps.mustHaveTarget && TargetsAoE.Count == 0)
            {
                Messages.Message("AU_NoTargets".Translate(), MessageTypeDefOf.RejectInput);
                Ability.Notify_AbilityFailed(true);
                return(false);
            }

            for (var i = 0; i < TargetsAoE.Count; i++)
            {
                //                for (int j = 0; j < burstshots; j++)
                //                {
                if (verbProps.defaultProjectile != null) //ranged attacks WILL have projectiles
                {
                    if ((GetsHot && AMASettings.Instance.AllowGetsHot) || (Jams && AMASettings.Instance.AllowJams))
                    {
                        string msg = string.Format("");
                        string reliabilityString;
                        float  failChance;
                        StatPart_Reliability.GetReliability(this.UseAbilityProps, out reliabilityString, out failChance);
                        failChance = GetsHot ? (failChance / 10) : (failChance / 100);
                        if (Rand.Chance(failChance))
                        {
                            if (GetsHot)
                            {
                                DamageDef damageDef        = this.Projectile.projectile.damageDef;
                                HediffDef HediffToAdd      = damageDef.hediff;
                                float     ArmorPenetration = this.Projectile.projectile.GetArmorPenetration(this.EquipmentSource, null);
                                float     DamageAmount     = 0;
                                Pawn      launcherPawn     = this.caster as Pawn;
                                if (Rand.Chance(GetsHotCritChance))
                                {
                                    DamageAmount = this.Projectile.projectile.GetDamageAmount(this.EquipmentSource, null);
                                    msg          = string.Format("{0}'s {1} critically overheated. ({2} chance) causing {3} damage", this.caster.LabelCap, this.EquipmentSource.LabelCap, failChance.ToStringPercent(), DamageAmount);
                                    if (GetsHotCritExplosion && Rand.Chance(GetsHotCritExplosionChance))
                                    {
                                        CriticalOverheatExplosion();
                                    }
                                }
                                else
                                {
                                    DamageAmount = this.Projectile.projectile.GetDamageAmount(this.EquipmentSource, null);
                                    msg          = string.Format("{0}'s {1} overheated. ({2} chance) causing {3} damage", this.caster.LabelCap, this.EquipmentSource.LabelCap, failChance.ToStringPercent(), DamageAmount);
                                }
                                float maxburndmg = DamageAmount / 10;
                                while (DamageAmount > 0f)
                                {
                                    List <BodyPartRecord> list = launcherPawn.health.hediffSet.GetNotMissingParts().Where(x => x.def.defName.Contains("Finger") || x.def.defName.Contains("Hand")).ToList <BodyPartRecord>();
                                    if (list.NullOrEmpty())
                                    {
                                        list = launcherPawn.health.hediffSet.GetNotMissingParts().Where(x => x.def.defName.Contains("Arm") || x.def.defName.Contains("Shoulder")).ToList <BodyPartRecord>();
                                    }
                                    if (list.NullOrEmpty())
                                    {
                                        list = launcherPawn.health.hediffSet.GetNotMissingParts().Where(x => x.def.tags.Contains(BodyPartTagDefOf.ManipulationLimbCore) || x.def.tags.Contains(BodyPartTagDefOf.ManipulationLimbSegment) || x.def.tags.Contains(BodyPartTagDefOf.ManipulationLimbDigit)).ToList <BodyPartRecord>();
                                    }
                                    if (list.NullOrEmpty())
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        BodyPartRecord part = list.RandomElement();
                                        Hediff         hediff;
                                        float          severity = Rand.Range(Math.Min(0.1f, DamageAmount), Math.Min(DamageAmount, maxburndmg));
                                        hediff          = HediffMaker.MakeHediff(HediffToAdd, launcherPawn, null);
                                        hediff.Severity = severity;
                                        launcherPawn.health.AddHediff(hediff, part, null);
                                        DamageAmount -= severity;
                                    }
                                }
                                Messages.Message(msg, MessageTypeDefOf.NegativeHealthEvent);
                            }
                            else
                            {
                                msg = string.Format("{0}'s {1} had a weapon jam. ({2} chance)", this.caster.LabelCap, this.EquipmentSource.LabelCap, failChance.ToStringPercent());
                                Messages.Message(msg, MessageTypeDefOf.SilentInput);
                            }
                            float defaultCooldownTime = this.verbProps.defaultCooldownTime * 2;
                            this.verbProps.defaultCooldownTime = defaultCooldownTime;
                            if (canDamageWeapon)
                            {
                                if (extraWeaponDamage != 0f)
                                {
                                    if (this.EquipmentSource != null)
                                    {
                                        if (this.EquipmentSource.HitPoints - (int)extraWeaponDamage >= 0)
                                        {
                                            this.EquipmentSource.HitPoints = this.EquipmentSource.HitPoints - (int)extraWeaponDamage;
                                        }
                                        else if (this.EquipmentSource.HitPoints - (int)extraWeaponDamage < 0)
                                        {
                                            this.EquipmentSource.HitPoints = 0;
                                            this.EquipmentSource.Destroy();
                                        }
                                    }
                                    if (this.HediffCompSource != null)
                                    {
                                        /*
                                         * if (__instance.HediffCompSource.parent.Part..HitPoints - (int)extraWeaponDamage >= 0)
                                         * {
                                         *  __instance.HediffCompSource.HitPoints = __instance.HediffCompSource.HitPoints - (int)extraWeaponDamage;
                                         * }
                                         * else if (__instance.HediffCompSource.HitPoints - (int)extraWeaponDamage < 0)
                                         * {
                                         *  __instance.HediffCompSource.HitPoints = 0;
                                         *  __instance.HediffCompSource.Destroy();
                                         * }
                                         */
                                    }
                                }
                                else
                                {
                                    if (this.EquipmentSource != null)
                                    {
                                        if (this.EquipmentSource.HitPoints > 0)
                                        {
                                            this.EquipmentSource.HitPoints--;
                                        }
                                    }
                                }
                            }
                            if (Jams)
                            {
                                if (this.EquipmentSource != null)
                                {
                                    SpinningLaserGun spinner = (SpinningLaserGun)this.EquipmentSource;
                                    if (spinner != null)
                                    {
                                        spinner.state = SpinningLaserGunBase.State.Idle;
                                        spinner.ReachRotationSpeed(0, 0);
                                    }
                                }
                                return(false);
                            }
                        }
                    }

                    var attempt = TryLaunchProjectile(verbProps.defaultProjectile, TargetsAoE[i]);

                    if (ScattershotCount > 0 && Multishot && AMASettings.Instance.AllowMultiShot)
                    {
                        //    Log.Message(string.Format("AllowMultiShot: {0} Projectile Count: {1}", AMASettings.Instance.AllowMultiShot && Multishot, ScattershotCount));
                        for (int ii = 0; ii < ScattershotCount; ii++)
                        {
                            //    Log.Message(string.Format("Launching extra projectile {0} / {1}", i+1, ScattershotCount));
                            //    AccessTools.Method(typeof(Verb_Shoot).BaseType, "TryCastShot", null, null).Invoke(__instance, null);
                            TryLaunchProjectile(verbProps.defaultProjectile, TargetsAoE[i]);
                        }
                    }
                    else
                    if (TwinLinked)
                    {
                        TryLaunchProjectile(verbProps.defaultProjectile, TargetsAoE[i]);
                    }
                    if (UserEffect && AMASettings.Instance.AllowUserEffects)
                    {
                        if (caster.def.category == ThingCategory.Pawn)
                        {
                            bool Immunityflag = false;
                            Pawn launcherPawn = this.caster as Pawn;
                            if (!Immunitylist.NullOrEmpty())
                            {
                                foreach (var item in Immunitylist)
                                {
                                    Immunityflag = launcherPawn.def.defName.Contains(item);
                                    if (Immunityflag)
                                    {
                                        //    Log.Message(string.Format("{0} is immune to their {1}'s UseEffect", launcherPawn.LabelShortCap, __instance.EquipmentSource.LabelShortCap));
                                    }
                                }

                                /*
                                 * List<string> list = GunExt.UserEffectImmuneList.Where(x => DefDatabase<ThingDef>.GetNamedSilentFail(x) != null).ToList();
                                 * bool Immunityflag = list.Contains(launcherPawn.def.defName);
                                 * if (Immunityflag)
                                 * {
                                 *  return;
                                 * }
                                 */
                            }
                            if (!Immunityflag)
                            {
                                var rand = Rand.Value;       // This is a random percentage between 0% and 100%
                                                             //    Log.Message(string.Format("GunExt.EffectsUser Effect: {0}, Chance: {1}, Roll: {2}, Result: {3}" + GunExt.ResistEffectStat != null ? ", Resist Stat: "+GunExt.ResistEffectStat.LabelCap+", Resist Amount"+ __instance.caster.GetStatValue(GunExt.ResistEffectStat, true) : null, GunExt.UserEffect.LabelCap, AddHediffChance, rand, rand <= AddHediffChance));
                                if (rand <= AddHediffChance) // If the percentage falls under the chance, success!
                                {
                                    var randomSeverity = Rand.Range(0.05f, 0.15f);
                                    var effectOnPawn   = launcherPawn?.health?.hediffSet?.GetFirstHediffOfDef(UserHediff);
                                    if (effectOnPawn != null)
                                    {
                                        effectOnPawn.Severity += randomSeverity;
                                    }
                                    else
                                    {
                                        Hediff hediff = HediffMaker.MakeHediff(UserHediff, launcherPawn, null);
                                        hediff.Severity = randomSeverity;
                                        launcherPawn.health.AddHediff(hediff, null, null);
                                    }
                                }
                            }
                        }
                    }
                    ////Log.Message(TargetsAoE[i].ToString());
                    if (attempt != null)
                    {
                        if (attempt == true)
                        {
                            result = true;
                        }
                        if (attempt == false)
                        {
                            result = false;
                        }
                    }
                }
                else //melee attacks WON'T have projectiles
                {
                    //    Log.Message("No Projectile");
                    var victim = TargetsAoE[i].Thing;
                    if (victim != null)
                    {
                        //    Log.Message("Yes victim");
                        if (victim is Pawn pawnVictim)
                        {
                            //    Log.Message("Yes victim is pawn");
                            AbilityEffectUtility.ApplyMentalStates(pawnVictim, CasterPawn, UseAbilityProps.mentalStatesToApply, UseAbilityProps.abilityDef, null);
                            AbilityEffectUtility.ApplyHediffs(pawnVictim, CasterPawn, UseAbilityProps.hediffsToApply, null);
                            AbilityEffectUtility.SpawnSpawnables(UseAbilityProps.thingsToSpawn, pawnVictim, victim.MapHeld, victim.PositionHeld);
                        }
                    }
                    else
                    {
                        //    Log.Message("Victim is null");
                        AbilityEffectUtility.SpawnSpawnables(UseAbilityProps.thingsToSpawn, CasterPawn, CasterPawn.MapHeld, CasterPawn.PositionHeld);
                    }
                }
                //                }
            }

            PostCastShot(result, out result);
            if (result == false)
            {
                Ability.Notify_AbilityFailed(UseAbilityProps.refundsPointsAfterFailing);
            }
            return(result);
        }
        protected new virtual void UpdateTargets()
        {
            TargetsAoE.Clear();
            if (UseAbilityProps.AbilityTargetCategory == AbilityTargetCategory.TargetAoE)
            {
                //Log.Message("AoE Called");
                if (UseAbilityProps.TargetAoEProperties == null)
                {
                    Log.Error("Tried to Cast AoE-Ability without defining a target class");
                }

                var targets = new List <Thing>();

                //Handle TargetAoE start location.
                var aoeStartPosition = caster.PositionHeld;
                if (!UseAbilityProps.TargetAoEProperties.startsFromCaster)
                {
                    aoeStartPosition = currentTarget.Cell;
                }

                //Handle friendly fire targets.
                if (!UseAbilityProps.TargetAoEProperties.friendlyFire)
                {
                    targets = caster.Map.listerThings.AllThings.Where(x =>
                                                                      x.Position.InHorDistOf(aoeStartPosition, UseAbilityProps.TargetAoEProperties.range) &&
                                                                      UseAbilityProps.TargetAoEProperties.targetClass.IsAssignableFrom(x.GetType()) &&
                                                                      x.Faction.HostileTo(Faction.OfPlayer)).ToList();
                }
                else if (UseAbilityProps.TargetAoEProperties.targetClass == typeof(Plant) ||
                         UseAbilityProps.TargetAoEProperties.targetClass == typeof(Building))
                {
                    targets = caster.Map.listerThings.AllThings.Where(x =>
                                                                      x.Position.InHorDistOf(aoeStartPosition, UseAbilityProps.TargetAoEProperties.range) &&
                                                                      UseAbilityProps.TargetAoEProperties.targetClass.IsAssignableFrom(x.GetType())).ToList();
                    foreach (var targ in targets)
                    {
                        var tinfo = new LocalTargetInfo(targ);
                        TargetsAoE.Add(tinfo);
                    }
                    return;
                }
                else
                {
                    targets.Clear();
                    targets = caster.Map.listerThings.AllThings.Where(x =>
                                                                      x.Position.InHorDistOf(aoeStartPosition, UseAbilityProps.TargetAoEProperties.range) &&
                                                                      UseAbilityProps.TargetAoEProperties.targetClass.IsAssignableFrom(x.GetType()) &&
                                                                      (x.HostileTo(Faction.OfPlayer) || UseAbilityProps.TargetAoEProperties.friendlyFire)).ToList();
                }

                var maxTargets  = UseAbilityProps.abilityDef.MainVerb.TargetAoEProperties.maxTargets;
                var randTargets = new List <Thing>(targets.InRandomOrder());
                for (var i = 0; i < maxTargets && i < randTargets.Count(); i++)
                {
                    var tinfo = new TargetInfo(randTargets[i]);
                    if (UseAbilityProps.targetParams.CanTarget(tinfo))
                    {
                        TargetsAoE.Add(new LocalTargetInfo(randTargets[i]));
                    }
                }
            }
            else
            {
                TargetsAoE.Clear();
                TargetsAoE.Add(currentTarget);
            }
        }