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;
                }
            }
        }
Exemplo n.º 2
0
        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();
        }
Exemplo n.º 3
0
        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);
        }