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); } }