protected override void Impact(Thing hitThing) { base.Impact(hitThing); if (hitThing != null) { int damageAmountBase = this.def.projectile.damageAmountBase; BodyPartDamageInfo value; DamageDef_CR damDefCR = def.projectile.damageDef as DamageDef_CR; if (damDefCR != null && damDefCR.harmOnlyOutsideLayers) { value = new BodyPartDamageInfo(null, BodyPartDepth.Outside); } else { value = new BodyPartDamageInfo(null, null); } DamageInfo dinfo = new DamageInfo(this.def.projectile.damageDef, damageAmountBase, this.launcher, this.ExactRotation.eulerAngles.y, new BodyPartDamageInfo?(value), this.def); ProjectilePropertiesCR propsCR = def.projectile as ProjectilePropertiesCR; if (propsCR != null && !propsCR.secondaryDamage.NullOrEmpty()) { // Get the correct body part Pawn pawn = hitThing as Pawn; if (pawn != null && def.projectile.damageDef.workerClass == typeof(DamageWorker_AddInjuryCR)) { dinfo = new DamageInfo(dinfo.Def, dinfo.Amount, dinfo.Instigator, dinfo.Angle, new BodyPartDamageInfo(DamageWorker_AddInjuryCR.GetExactPartFromDamageInfo(dinfo, pawn), false, (HediffDef)null), dinfo.Source); } List <DamageInfo> dinfoList = new List <DamageInfo>() { dinfo }; foreach (SecondaryDamage secDamage in propsCR.secondaryDamage) { dinfoList.Add(new DamageInfo(secDamage.def, secDamage.amount, dinfo.Instigator, dinfo.Part, dinfo.Source)); } foreach (DamageInfo curDinfo in dinfoList) { hitThing.TakeDamage(curDinfo); } } else { hitThing.TakeDamage(dinfo); } } else { SoundDefOf.BulletImpactGround.PlayOneShot(base.Position); MoteThrower.ThrowStatic(this.ExactPosition, ThingDefOf.Mote_ShotHit_Dirt, 1f); } }
private static bool ApplyArmor(ref float damAmount, ref float pierceAmount, float armorRating, Thing armorThing, DamageDef damageDef) { float originalDamage = damAmount; bool deflected = false; DamageDef_CR damageDefCR = damageDef as DamageDef_CR; float penetrationChance = 1; if (damageDefCR != null && damageDefCR.deflectable) { penetrationChance = Mathf.Clamp((pierceAmount - armorRating) * 6, 0, 1); } //Shot is deflected if (penetrationChance == 0 || Rand.Value > penetrationChance) { deflected = true; } //Damage calculations float dMult = 1; if (damageDefCR != null) { if (damageDefCR.absorbable && deflected) { dMult = 0; } else if (damageDefCR.deflectable) { dMult = Mathf.Clamp01(0.5f + (pierceAmount - armorRating) * 3); } } else { dMult = Mathf.Clamp01(1 - armorRating); } damAmount *= dMult; //Damage armor if (armorThing != null && armorThing as Pawn == null) { float absorbedDamage = (originalDamage - damAmount) * Mathf.Min(pierceAmount, 1f); if (deflected) { absorbedDamage *= 0.5f; } armorThing.TakeDamage(new DamageInfo(damageDef, Mathf.CeilToInt(absorbedDamage), null, null, null)); } pierceAmount *= dMult; return(deflected); }
private void ApplyDamagePartial(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { BodyPartRecord exactPartFromDamageInfo = DamageWorker_AddInjuryCR.GetExactPartFromDamageInfo(dinfo, pawn); if (exactPartFromDamageInfo == null) { return; } // Only apply armor if we propagate damage to the outside or the body part itself is outside, secondary damage types should directly damage organs, bypassing armor bool involveArmor = !dinfo.InstantOldInjury && !result.deflected && (dinfo.Def.harmAllLayersUntilOutside || exactPartFromDamageInfo.depth == BodyPartDepth.Outside); int damageAmount = dinfo.Amount; if (involveArmor) { damageAmount = Utility.GetAfterArmorDamage(pawn, dinfo.Amount, exactPartFromDamageInfo, dinfo, true, ref result.deflected); } if ((double)damageAmount < 0.001) { result.absorbed = true; return; } // Shot absorbed and converted into blunt DamageDef_CR damageDefCR = dinfo.Def as DamageDef_CR; if (damageDefCR != null && damageDefCR.deflectable && result.deflected && dinfo.Def != Utility.absorbDamageDef) { // Get outer parent of struck part BodyPartRecord currentPart = exactPartFromDamageInfo; while (currentPart != null && currentPart.parent != null && currentPart.depth != BodyPartDepth.Outside) { currentPart = currentPart.parent; } DamageInfo dinfo2 = new DamageInfo(Utility.absorbDamageDef, damageAmount, dinfo.Instigator, new BodyPartDamageInfo(currentPart, false), dinfo.Source); this.ApplyDamagePartial(dinfo2, pawn, ref result); return; } //Creating the Hediff HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(dinfo.Def, pawn, exactPartFromDamageInfo); Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); hediff_Injury.Part = exactPartFromDamageInfo; hediff_Injury.source = dinfo.Source; hediff_Injury.sourceBodyPartGroup = dinfo.LinkedBodyPartGroup; hediff_Injury.sourceHediffDef = dinfo.LinkedHediffDef; hediff_Injury.Severity = (float)damageAmount; if (dinfo.InstantOldInjury) { HediffComp_GetsOld hediffComp_GetsOld = hediff_Injury.TryGetComp <HediffComp_GetsOld>(); if (hediffComp_GetsOld != null) { hediffComp_GetsOld.IsOld = true; } else { Log.Error(string.Concat(new object[] { "Tried to create instant old injury on Hediff without a GetsOld comp: ", hediffDefFromDamage, " on ", pawn })); } } result.wounded = true; result.lastHitPart = hediff_Injury.Part; if (DamageWorker_AddInjuryCR.IsHeadshot(dinfo, hediff_Injury, pawn)) { result.headshot = true; } if (dinfo.InstantOldInjury && (hediff_Injury.def.CompPropsFor(typeof(HediffComp_GetsOld)) == null || hediff_Injury.Part.def.oldInjuryBaseChance == 0f || hediff_Injury.Part.def.IsSolid(hediff_Injury.Part, pawn.health.hediffSet.hediffs) || pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(hediff_Injury.Part))) { return; } this.FinalizeAndAddInjury(pawn, hediff_Injury, dinfo, ref result); this.CheckPropagateDamageToInnerSolidParts(dinfo, pawn, hediff_Injury, !dinfo.InstantOldInjury, damageAmount, ref result); this.CheckDuplicateDamageToOuterParts(dinfo, pawn, hediff_Injury, !dinfo.InstantOldInjury, damageAmount, ref result); }
protected override void Impact(Thing hitThing) { Map map = base.Map; base.Impact(hitThing); if (hitThing != null) { int damageAmountBase = def.projectile.damageAmountBase; ThingDef equipmentDef = this.equipmentDef; DamageDef_CR damDefCR = def.projectile.damageDef as DamageDef_CR; DamageInfo dinfo = new DamageInfo( def.projectile.damageDef, damageAmountBase, ExactRotation.eulerAngles.y, launcher, null, equipmentDef); // if (damDefCR != null && damDefCR.harmOnlyOutsideLayers) dinfo.ForceHitPart.depth = BodyPartDepth.Outside; ProjectilePropertiesCR propsCR = def.projectile as ProjectilePropertiesCR; if (propsCR != null && !propsCR.secondaryDamage.NullOrEmpty()) { // Log.Message("propsCR: " + propsCR.ToString()); // Get the correct body part Pawn pawn = hitThing as Pawn; if (pawn != null && def.projectile.damageDef.workerClass == typeof(DamageWorker_AddInjuryCR)) { BodyPartRecord exactPartFromDamageInfo = DamageWorker_AddInjuryCR.GetExactPartFromDamageInfo(dinfo, pawn); dinfo = new DamageInfo( dinfo.Def, dinfo.Amount, dinfo.Angle, dinfo.Instigator, exactPartFromDamageInfo = (DamageWorker_AddInjuryCR.GetExactPartFromDamageInfo(dinfo, pawn)), dinfo.WeaponGear); } List <DamageInfo> dinfoList = new List <DamageInfo>() { dinfo }; foreach (SecondaryDamage secDamage in propsCR.secondaryDamage) { dinfoList.Add(new DamageInfo( secDamage.def, secDamage.amount, dinfo.Angle, dinfo.Instigator, dinfo.ForceHitPart, dinfo.WeaponGear)); } foreach (DamageInfo curDinfo in dinfoList) { hitThing.TakeDamage(curDinfo); } } else { hitThing.TakeDamage(dinfo); } } else { SoundDefOf.BulletImpactGround.PlayOneShot(new TargetInfo(base.Position, map, false)); MoteMaker.MakeStaticMote(ExactPosition, map, ThingDefOf.Mote_ShotHit_Dirt, 1f); } }