private void CalculateOldInjuryDamageThreshold(Pawn pawn, Hediff_Injury injury) { HediffCompProperties hediffCompProperties = injury.def.CompPropsFor(typeof(HediffComp_GetsOld)); if (hediffCompProperties == null) { return; } if (injury.Part.def.IsSolid(injury.Part, pawn.health.hediffSet.hediffs) || pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(injury.Part) || injury.IsOld() || injury.Part.def.oldInjuryBaseChance < 1E-05f) { return; } bool isDelicate = injury.Part.def.IsDelicate; if ((Rand.Value <= injury.Part.def.oldInjuryBaseChance * hediffCompProperties.becomeOldChance && injury.Severity >= injury.Part.def.GetMaxHealth(pawn) * 0.25f && injury.Severity >= 7f) || isDelicate) { HediffComp_GetsOld hediffComp_GetsOld = injury.TryGetComp <HediffComp_GetsOld>(); float num = 1f; float num2 = injury.Severity / 2f; if (num <= num2) { hediffComp_GetsOld.oldDamageThreshold = Rand.Range(num, num2); } if (isDelicate) { hediffComp_GetsOld.oldDamageThreshold = injury.Severity; hediffComp_GetsOld.IsOld = true; } } }
public override void AddToPawn(CustomPawn customPawn, Pawn pawn) { if (Option.Giver != null) { Hediff hediff = HediffMaker.MakeHediff(Option.HediffDef, pawn, BodyPartRecord); hediff.Severity = this.Severity; pawn.health.AddHediff(hediff, BodyPartRecord, null); this.hediff = hediff; } else if (Option.IsOldInjury) { Hediff hediff = HediffMaker.MakeHediff(Option.HediffDef, pawn, null); hediff.Severity = this.Severity; HediffComp_GetsOld getsOld = hediff.TryGetComp <HediffComp_GetsOld>(); if (getsOld != null) { hediff.TryGetComp <HediffComp_GetsOld>().IsOld = true; // TODO: Pain factor should not be hard-coded. hediff.TryGetComp <HediffComp_GetsOld>().painFactor = 4; } pawn.health.AddHediff(hediff, BodyPartRecord, null); this.hediff = hediff; } else { Hediff hediff = HediffMaker.MakeHediff(Option.HediffDef, pawn, null); hediff.Severity = this.Severity; pawn.health.AddHediff(hediff, null, null); this.hediff = hediff; } pawn.health.capacities.Clear(); }
public override void AddToPawn(CustomPawn customPawn, Pawn pawn) { if (Option.Giver != null) { Hediff hediff = HediffMaker.MakeHediff(Option.HediffDef, pawn, BodyPartRecord); hediff.Severity = this.Severity; pawn.health.AddHediff(hediff, BodyPartRecord, null); this.hediff = hediff; } else if (Option.IsOldInjury) { Hediff hediff = HediffMaker.MakeHediff(Option.HediffDef, pawn, null); hediff.Severity = this.Severity; HediffComp_GetsOld getsOld = hediff.TryGetComp <HediffComp_GetsOld>(); if (getsOld != null) { getsOld.IsOld = true; getsOld.painFactor = painFactor == null ? 0 : painFactor.Value; } pawn.health.AddHediff(hediff, BodyPartRecord, null); this.hediff = hediff; } else { Hediff hediff = HediffMaker.MakeHediff(Option.HediffDef, pawn, null); hediff.Severity = this.Severity; pawn.health.AddHediff(hediff, null, null); this.hediff = hediff; } pawn.health.capacities.Clear(); }
private void CalculateOldInjuryDamageThreshold(Pawn pawn, Hediff_Injury injury) { HediffComp_GetsOld comp = injury.TryGetComp <HediffComp_GetsOld>(); if (comp == null) { return; } // No permanent injuries on solid parts, prosthetics or injuries that are already old if (injury.Part.def.IsSolid(injury.Part, pawn.health.hediffSet.hediffs) || pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(injury.Part) || injury.IsOld()) { return; } // Delicate parts get old instantly if (injury.Part.def.IsDelicate) { comp.oldDamageThreshold = injury.Severity; comp.IsOld = true; } // Check if injury is at least 10% of part health and make a random roll else if (injury.Severity >= injury.Part.def.GetMaxHealth(pawn) * 0.1f && injury.Severity > 1) { float getOldChance = injury.Part.def.oldInjuryBaseChance * comp.Props.becomeOldChance * Mathf.Pow((injury.Severity / injury.Part.def.GetMaxHealth(pawn)), 2); if (Rand.Value < getOldChance) { comp.oldDamageThreshold = Rand.Range(1, injury.Severity); } } }
public static bool IsOld(this Hediff hd) { HediffWithComps hediffWithComps = hd as HediffWithComps; if (hediffWithComps == null) { return(false); } HediffComp_GetsOld hediffComp_GetsOld = hediffWithComps.TryGetComp <HediffComp_GetsOld>(); if (hediffComp_GetsOld == null) { return(false); } return(hediffComp_GetsOld.IsOld); }
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); }
private void ApplyDamageToPart(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCE.LocalInjuryResult result) { BodyPartRecord exactPartFromDamageInfo = GetExactPartFromDamageInfo(dinfo, pawn); if (exactPartFromDamageInfo == null) { return; } bool involveArmor = !dinfo.InstantOldInjury; DamageInfo postArmorDinfo = dinfo; bool shieldAbsorbed = false; if (involveArmor) { postArmorDinfo = ArmorUtilityCE.GetAfterArmorDamage(dinfo, pawn, exactPartFromDamageInfo, out shieldAbsorbed); if (dinfo.ForceHitPart == null && postArmorDinfo.ForceHitPart != null && exactPartFromDamageInfo != postArmorDinfo.ForceHitPart) { exactPartFromDamageInfo = postArmorDinfo.ForceHitPart; // If the shot was deflected, update our body part if (pawn.Spawned) { LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_ArmorSystem, OpportunityType.Critical); // Inform the player about armor deflection } } } // Vanilla code - apply hediff if ((double)postArmorDinfo.Amount < 0.001) { result.deflected = true; return; } HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(postArmorDinfo.Def, pawn, exactPartFromDamageInfo); Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); hediff_Injury.Part = exactPartFromDamageInfo; hediff_Injury.source = postArmorDinfo.WeaponGear; hediff_Injury.sourceBodyPartGroup = postArmorDinfo.WeaponBodyPartGroup; hediff_Injury.sourceHediffDef = postArmorDinfo.WeaponLinkedHediff; hediff_Injury.Severity = (float)postArmorDinfo.Amount; if (postArmorDinfo.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_AddInjuryCE.IsHeadshot(postArmorDinfo, hediff_Injury, pawn)) { result.headshot = true; } if (postArmorDinfo.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, postArmorDinfo, ref result); this.CheckPropagateDamageToInnerSolidParts(postArmorDinfo, pawn, hediff_Injury, involveArmor, ref result); this.CheckDuplicateDamageToOuterParts(postArmorDinfo, pawn, hediff_Injury, involveArmor, ref result); // Apply secondary damage if (!shieldAbsorbed) { var props = dinfo.WeaponGear?.projectile as ProjectilePropertiesCE; if (props != null && !props.secondaryDamage.NullOrEmpty() && dinfo.Def == props.damageDef) { foreach (SecondaryDamage sec in props.secondaryDamage) { if (pawn.Dead) { return; } var secDinfo = sec.GetDinfo(postArmorDinfo); secDinfo.SetForcedHitPart(exactPartFromDamageInfo); pawn.TakeDamage(secDinfo); } } } }
/// <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); }