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 float ApplyToPawn(DamageInfo dinfo, Pawn pawn) { if (dinfo.Amount <= 0) { return(0f); } if (!DebugSettings.enablePlayerDamage && pawn.Faction == Faction.OfPlayer) { return(0f); } if (!dinfo.Part.HasValue) { dinfo.SetPart(new BodyPartDamageInfo(null, null)); } DamageWorker_AddInjuryCR.LocalInjuryResult localInjuryResult = DamageWorker_AddInjuryCR.LocalInjuryResult.MakeNew(); if (dinfo.Def.spreadOut) { if (pawn.apparel != null) { List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int i = wornApparel.Count - 1; i >= 0; i--) { this.CheckApplySpreadDamage(dinfo, wornApparel[i]); } } if (pawn.equipment != null && pawn.equipment.Primary != null) { this.CheckApplySpreadDamage(dinfo, pawn.equipment.Primary); } if (pawn.inventory != null) { ThingContainer container = pawn.inventory.container; for (int j = container.Count - 1; j >= 0; j--) { this.CheckApplySpreadDamage(dinfo, container[j]); } } } if (!this.FragmentDamageForDamageType(dinfo, pawn, ref localInjuryResult)) { this.ApplyDamagePartial(dinfo, pawn, ref localInjuryResult); this.CheckDuplicateSmallPawnDamageToPartParent(dinfo, pawn, ref localInjuryResult); } if (localInjuryResult.wounded) { DamageWorker_AddInjuryCR.PlayWoundedVoiceSound(dinfo, pawn); pawn.Drawer.Notify_DamageApplied(dinfo); DamageWorker_AddInjuryCR.InformPsychology(dinfo, pawn); } if (localInjuryResult.headshot && pawn.Spawned) { MoteThrower.ThrowText(new Vector3((float)pawn.Position.x + 1f, (float)pawn.Position.y, (float)pawn.Position.z + 1f), "Headshot".Translate(), Color.white, -1); if (dinfo.Instigator != null) { Pawn pawn2 = dinfo.Instigator as Pawn; if (pawn2 != null) { pawn2.records.Increment(RecordDefOf.Headshots); } } } if (localInjuryResult.absorbed) { if (pawn.health.deflectionEffecter == null) { pawn.health.deflectionEffecter = EffecterDef.Named("ArmorRating").Spawn(); } pawn.health.deflectionEffecter.Trigger(pawn, pawn); } else { ImpactSoundUtility.PlayImpactSound(pawn, dinfo.Def.impactSoundType); } return(localInjuryResult.totalDamageDealt); }
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); }
/// <summary> /// Handles damage and armor calculations /// </summary> /// <param name="dinfo"></param> /// <param name="pawn"></param> /// <param name="result"></param> private void ApplyDamagePartial(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { BodyPartRecord exactPartFromDamageInfo = DamageWorker_AddInjuryCR.GetExactPartFromDamageInfo(dinfo, pawn); if (exactPartFromDamageInfo == null) { return; } bool flag = true; if (dinfo.InstantOldInjury) { flag = false; } int damageAmount = dinfo.Amount; bool shotAbsorbed = false; if (!result.deflected && flag) { //damageAmount = ArmorUtility.GetAfterArmorDamage(pawn, dinfo.Amount, exactPartFromDamageInfo, dinfo.Def); damageAmount = Utility.GetAfterArmorDamage(pawn, dinfo.Amount, exactPartFromDamageInfo, dinfo, true, ref shotAbsorbed); } if ((double)damageAmount < 0.001) { result.deflected = true; return; } //Shot absorbed and converted into blunt if (shotAbsorbed) { result.deflected = true; if (dinfo.Def != Utility.absorbDamageDef) { //Get outer parent of struck part BodyPartRecord parentPart = exactPartFromDamageInfo; while (parentPart != null && parentPart.parent != null && parentPart.depth != BodyPartDepth.Outside) { parentPart = parentPart.parent; } DamageInfo dinfo2 = new DamageInfo(Utility.absorbDamageDef, damageAmount, dinfo.Instigator, new BodyPartDamageInfo(parentPart, 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 = dinfo.InstantOldInjury; } 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, flag, ref result); this.CheckDuplicateDamageToOuterParts(dinfo, pawn, hediff_Injury, flag, ref result); }
private void FinalizeAndAddInjury(Pawn pawn, Hediff_Injury injury, DamageInfo dinfo, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { this.CalculateOldInjuryDamageThreshold(pawn, injury); result.totalDamageDealt += injury.Severity; pawn.health.AddHediff(injury, null, new DamageInfo?(dinfo)); }
/// <summary> /// Distributes damage over multiple body parts on damage types which spread out /// </summary> /// <param name="dinfo"></param> /// <param name="pawn"></param> /// <param name="result"></param> /// <returns></returns> private bool FragmentDamageForDamageType(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { if (!dinfo.AllowDamagePropagation) { return false; } if (dinfo.Amount < 9) { return false; } if (!dinfo.Def.spreadOut) { return false; } int num = Rand.RangeInclusive(3, 4); for (int i = 0; i < num; i++) { DamageInfo dinfo2 = dinfo; dinfo2.SetAmount(dinfo.Amount / num); this.ApplyDamagePartial(dinfo2, pawn, ref result); } return true; }
private void CheckPropagateDamageToInnerSolidParts(DamageInfo dinfo, Pawn pawn, Hediff_Injury injury, bool involveArmor, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { if (!dinfo.AllowDamagePropagation) { return; } if (Rand.Value >= HealthTunings.ChanceToAdditionallyDamageInnerSolidPart) { return; } if (dinfo.Def.hasChanceToAdditionallyDamageInnerSolidParts && !injury.Part.def.IsSolid(injury.Part, pawn.health.hediffSet.hediffs) && injury.Part.depth == BodyPartDepth.Outside) { IEnumerable<BodyPartRecord> source = from x in pawn.health.hediffSet.GetNotMissingParts(null, null) where x.parent == injury.Part && x.def.IsSolid(x, pawn.health.hediffSet.hediffs) && x.depth == BodyPartDepth.Inside select x; BodyPartRecord part; if (source.TryRandomElementByWeight((BodyPartRecord x) => x.absoluteFleshCoverage, out part)) { HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(dinfo.Def, pawn, part); Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); hediff_Injury.Part = part; hediff_Injury.source = injury.source; hediff_Injury.sourceBodyPartGroup = injury.sourceBodyPartGroup; hediff_Injury.Severity = (float)(dinfo.Amount / 2); if (involveArmor) { hediff_Injury.Severity = (float)Utility.GetAfterArmorDamage(pawn, dinfo.Amount / 2, part, dinfo); } if (hediff_Injury.Severity <= 0f) { return; } result.lastHitPart = hediff_Injury.Part; this.FinalizeAndAddInjury(pawn, hediff_Injury, dinfo, ref result); } } }
private void CheckDuplicateSmallPawnDamageToPartParent(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { if (!dinfo.AllowDamagePropagation) { return; } if (result.lastHitPart != null && dinfo.Def.harmsHealth && result.lastHitPart != pawn.RaceProps.body.corePart && result.lastHitPart.parent != null && pawn.health.hediffSet.GetPartHealth(result.lastHitPart.parent) > 0f && dinfo.Amount >= 10 && pawn.HealthScale <= 0.5001f) { DamageInfo dinfo2 = dinfo; BodyPartDamageInfo part = new BodyPartDamageInfo(result.lastHitPart.parent, false); dinfo2.SetPart(part); this.ApplyDamagePartial(dinfo2, pawn, ref result); } }
private void CheckDuplicateDamageToOuterParts(DamageInfo dinfo, Pawn pawn, Hediff_Injury injury, bool involveArmor, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { if (!dinfo.AllowDamagePropagation) { return; } if (dinfo.Def.harmAllLayersUntilOutside && injury.Part.depth == BodyPartDepth.Inside) { BodyPartRecord parent = injury.Part.parent; do { if (pawn.health.hediffSet.GetPartHealth(parent) != 0f) { HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(dinfo.Def, pawn, parent); Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); hediff_Injury.Part = parent; hediff_Injury.source = injury.source; hediff_Injury.sourceBodyPartGroup = injury.sourceBodyPartGroup; hediff_Injury.Severity = (float)dinfo.Amount; if (involveArmor) { hediff_Injury.Severity = (float)Utility.GetAfterArmorDamage(pawn, dinfo.Amount, parent, dinfo); } if (hediff_Injury.Severity <= 0f) { hediff_Injury.Severity = 1f; } result.lastHitPart = hediff_Injury.Part; this.FinalizeAndAddInjury(pawn, hediff_Injury, dinfo, ref result); } if (parent.depth == BodyPartDepth.Outside) { break; } parent = parent.parent; } while (parent != null); } }
/// <summary> /// Handles damage and armor calculations /// </summary> /// <param name="dinfo"></param> /// <param name="pawn"></param> /// <param name="result"></param> private void ApplyDamagePartial(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCR.LocalInjuryResult result) { BodyPartRecord exactPartFromDamageInfo = DamageWorker_AddInjuryCR.GetExactPartFromDamageInfo(dinfo, pawn); if (exactPartFromDamageInfo == null) { return; } bool flag = true; if (dinfo.InstantOldInjury) { flag = false; } int damageAmount = dinfo.Amount; bool shotAbsorbed = false; if (!result.deflected && flag) { //damageAmount = ArmorUtility.GetAfterArmorDamage(pawn, dinfo.Amount, exactPartFromDamageInfo, dinfo.Def); damageAmount = Utility.GetAfterArmorDamage(pawn, dinfo.Amount, exactPartFromDamageInfo, dinfo, true, ref shotAbsorbed); } if ((double)damageAmount < 0.001) { result.deflected = true; return; } //Shot absorbed and converted into blunt if (shotAbsorbed) { result.deflected = true; if (dinfo.Def != Utility.absorbDamageDef) { //Get outer parent of struck part BodyPartRecord parentPart = exactPartFromDamageInfo; while (parentPart != null && parentPart.parent != null && parentPart.depth != BodyPartDepth.Outside) { parentPart = parentPart.parent; } DamageInfo dinfo2 = new DamageInfo(Utility.absorbDamageDef, damageAmount, dinfo.Instigator, new BodyPartDamageInfo(parentPart, 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 = dinfo.InstantOldInjury; } 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, flag, ref result); this.CheckDuplicateDamageToOuterParts(dinfo, pawn, hediff_Injury, flag, 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); } }