public override float GetValueUnfinalized(StatRequest req, bool applyPostProcess = true)
        {
            if (req.Thing is Pawn pawn)
            {
                float glowFactor = GlowFor.FactorOrFallBack(pawn);

                if (glowFactor.FactorIsNonTrivial())
                {
                    return(CombatHelpers.RangedCooldownMultiplier(pawn.skills.GetSkill(DerivedFrom).Level, glowFactor));
                }
            }

            return(Constants.TRIVIAL_FACTOR);
        }
 public void AddRangedCdDemo(float glow, int skill, float glowFactor)
 {
     AddLine(Str_Combat.RangedCooldownDemo(glow, CombatHelpers.RangedCooldownMultiplier(skill, glowFactor)));
 }
            public void AddSurpriseAttackRow(float glow, float atkLM, float defLM)
            {
                float chance = CombatHelpers.SurpriseAttackChance(atkLM, defGlowFactor: defLM);

                AddLine(Str_Combat.SurpriseAtkCalcRow(glow, atkLM, defLM, chance));
            }
 public void AddDodgeRow(float glow, float atkLM, float defLM, float baseDodge)
 {
     AddLine(Str_Combat.DodgeCalcRow(glow, atkLM, defLM, baseDodge, CombatHelpers.DodgeChanceFunction(baseDodge, atkLM - defLM)));
 }
        public static string CombatPart(Pawn pawn, Comp_NightVision comp)
        {
            var         strHelper       = new CombatStatStrHelper();
            const float NoLight         = 0f;
            const float FullLight       = 1f;
            float       noLightFactor   = comp.FactorFromGlow(glow: NoLight);
            float       fullLightFactor = comp.FactorFromGlow(glow: FullLight);


            strHelper.AddMainHeader();

            if (Settings.CombatStore.RangedHitEffectsEnabled.Value)
            {
                if (ShowRangedEffectsForPawn(pawn))
                {
                    strHelper.AddLine(Str_Combat.ShootTargetAtGlow());


                    for (var i = 1; i <= 4; i++)
                    {
                        float hit = ShotReport.HitFactorFromShooter(caster: pawn, distance: i * 5);

                        strHelper.AddLine(
                            Str_Combat.ShotChanceTransform(
                                distance: i * 5,
                                hitChance: hit,
                                nvResult: CombatHelpers.HitChanceGlowTransform(hitChance: hit,
                                                                               attGlowFactor: noLightFactor),
                                psResult: CombatHelpers.HitChanceGlowTransform(hitChance: hit,
                                                                               attGlowFactor: fullLightFactor)
                                )
                            );
                    }

                    strHelper.NextLine();
                }
                else
                {
                    // TODO add line reporting why effects are not appearing
                }
            }

            if (Settings.CombatStore.MeleeHitEffectsEnabled.Value)
            {
                if (ShowMeleeEffectsForPawn(pawn))
                {
                    float pawnDodgeVal = pawn.GetStatValue(stat: Defs_Rimworld.MeleeDodgeStat);
                    float meleeHit     = pawn.GetStatValue(stat: Defs_Rimworld.MeleeHitStat, applyPostProcess: true);

                    var caps = Settings.Store.MultiplierCaps;

                    strHelper.AddLine(Str_Combat.StrikeTargetAtGlow());


                    strHelper.AddLine(
                        Str_Combat.StrikeChanceTransform(
                            hitChance: meleeHit,
                            nvResult: CombatHelpers.HitChanceGlowTransform(hitChance: meleeHit,
                                                                           attGlowFactor: noLightFactor),
                            psResult: CombatHelpers.HitChanceGlowTransform(hitChance: meleeHit,
                                                                           attGlowFactor: fullLightFactor)
                            )
                        );

                    strHelper.NextLine();

                    strHelper.AddSurpriseAttackHeader();

                    ///////////////////////////////////////////
                    //// Surprise attack stats at 0% light ////

                    float noLightSurpAttChance =
                        CombatHelpers.SurpriseAttackChance(atkGlowFactor: noLightFactor, defGlowFactor: caps.min);
                    // attack vs pawn with minimum LM
                    strHelper.AddSurpriseAttackRow(NoLight, noLightFactor, caps.min);

                    // skip if we need more room to show dodge stats
                    if (pawnDodgeVal.IsTrivial())
                    {
                        //skip if chance was 0% vs pawn with min LM (as it won't be different
                        if (noLightSurpAttChance.IsNonTrivial())
                        {
                            // attack vs pawn with normal LM
                            noLightSurpAttChance =
                                CombatHelpers.SurpriseAttackChance(atkGlowFactor: noLightFactor, defGlowFactor: 1f);

                            strHelper.AddSurpriseAttackRow(NoLight, noLightFactor, 1);

                            // skip as above
                            if (noLightSurpAttChance.IsNonTrivial())
                            {
                                // attack vs pawn with max LM
                                strHelper.AddSurpriseAttackRow(0, noLightFactor, caps.max);
                            }
                        }
                    }
                    ////////////////////////////////////////////

                    /////////////////////////////////////////////
                    //// Surprise attack stats at 100% light ////

                    // skip if we need more room to show dodge stats
                    if (pawnDodgeVal.IsTrivial())
                    {
                        // attack vs pawn with min LM
                        strHelper.AddSurpriseAttackRow(fullLightFactor, fullLightFactor, caps.min);
                    }

                    // attack vs pawn with normal LM
                    strHelper.AddSurpriseAttackRow(fullLightFactor, fullLightFactor, 1f);
                    strHelper.NextLine();
                    /////////////////////////////////////////////

                    /////////////////////////////////////////////
                    ////             Dodge Stats             ////


                    strHelper.AddDodgeHeader();

                    // This pawns chance to dodge when attacked

                    // attacked by pawn with min LM in no light
                    strHelper.AddDodgeRow(NoLight, caps.min, noLightFactor, pawnDodgeVal);

                    // skip if pawns dodge value is zero
                    if (pawnDodgeVal.IsNonTrivial())
                    {
                        // attacked by pawn with normal LM in no light
                        strHelper.AddDodgeRow(NoLight, 1f, noLightFactor, pawnDodgeVal);

                        // attacked by pawn with max LM in no light
                        strHelper.AddDodgeRow(NoLight, caps.max, noLightFactor, pawnDodgeVal);

                        // attacked by pawn with min LM in no light
                        strHelper.AddDodgeRow(FullLight, caps.min, fullLightFactor, pawnDodgeVal);
                    }

                    //attacked by pawn with normal LM in full light
                    strHelper.AddDodgeRow(FullLight, 1, fullLightFactor, pawnDodgeVal);
                }
            }

            return(strHelper.ToString());
        }